Asterisk - The Open Source Telephony Project  GIT-master-a24979a
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 [64]
 
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 574 of file chan_dahdi.c.

◆ CALLPROGRESS_FAX

#define CALLPROGRESS_FAX   (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)

Definition at line 614 of file chan_dahdi.c.

◆ CALLPROGRESS_FAX_INCOMING

#define CALLPROGRESS_FAX_INCOMING   4

Definition at line 613 of file chan_dahdi.c.

◆ CALLPROGRESS_FAX_OUTGOING

#define CALLPROGRESS_FAX_OUTGOING   2

Definition at line 612 of file chan_dahdi.c.

◆ CALLPROGRESS_PROGRESS

#define CALLPROGRESS_PROGRESS   1

Definition at line 611 of file chan_dahdi.c.

◆ CALLWAITING_REPEAT_SAMPLES

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

10,000 ms

Definition at line 732 of file chan_dahdi.c.

◆ CALLWAITING_SILENT_SAMPLES

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

300 ms

Definition at line 731 of file chan_dahdi.c.

◆ CALLWAITING_SUPPRESS_SAMPLES

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

100 ms

Definition at line 733 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 646 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 647 of file chan_dahdi.c.

◆ CHAN_PSEUDO

#define CHAN_PSEUDO   -2

Definition at line 609 of file chan_dahdi.c.

◆ CIDCW_EXPIRE_SAMPLES

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

500 ms

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

◆ DEFAULT_DIALTONE_DETECT_TIMEOUT

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

10,000 ms

Definition at line 737 of file chan_dahdi.c.

◆ DEFAULT_RINGT

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

8,000 ms

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

◆ GET_CHANNEL

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

Definition at line 1110 of file chan_dahdi.c.

◆ HANGUP

#define HANGUP   1

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

◆ MASK_AVAIL

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 728 of file chan_dahdi.c.

◆ MASK_INUSE

#define MASK_INUSE   (1 << 1)

Channel currently in use

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

◆ MIN_MS_SINCE_FLASH

#define MIN_MS_SINCE_FLASH   ((2000) )

2000 ms

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

◆ NUM_CADENCE_MAX

#define NUM_CADENCE_MAX   25

Definition at line 616 of file chan_dahdi.c.

◆ NUM_SPANS

#define NUM_SPANS   32

Definition at line 606 of file chan_dahdi.c.

◆ POLARITY_IDLE

#define POLARITY_IDLE   0

Definition at line 845 of file chan_dahdi.c.

◆ POLARITY_REV

#define POLARITY_REV   1

Definition at line 846 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 17894 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 17896 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 726 of file chan_dahdi.c.

◆ REPORT_CHANNEL_ALARMS

#define REPORT_CHANNEL_ALARMS   1

Definition at line 668 of file chan_dahdi.c.

◆ REPORT_SPAN_ALARMS

#define REPORT_SPAN_ALARMS   2

Definition at line 669 of file chan_dahdi.c.

◆ sig2str

#define sig2str   dahdi_sig2str

Definition at line 4490 of file chan_dahdi.c.

◆ SMDI_MD_WAIT_TIMEOUT

#define SMDI_MD_WAIT_TIMEOUT   1500 /* 1.5 seconds */

Definition at line 535 of file chan_dahdi.c.

◆ TRAILER_MS

#define TRAILER_MS   5

◆ TRANSFER

#define TRANSFER   0

Definition at line 16269 of file chan_dahdi.c.

Function Documentation

◆ __dahdi_exception()

static struct ast_frame* __dahdi_exception ( struct ast_channel ast)
static

Definition at line 8311 of file chan_dahdi.c.

8312 {
8313  int res;
8314  int idx;
8315  struct ast_frame *f;
8316  int usedindex = -1;
8317  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
8318 
8319  if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
8320  idx = SUB_REAL;
8321  }
8322 
8323  p->subs[idx].f.frametype = AST_FRAME_NULL;
8324  p->subs[idx].f.datalen = 0;
8325  p->subs[idx].f.samples = 0;
8326  p->subs[idx].f.mallocd = 0;
8327  p->subs[idx].f.offset = 0;
8328  p->subs[idx].f.subclass.integer = 0;
8329  p->subs[idx].f.delivery = ast_tv(0,0);
8330  p->subs[idx].f.src = "dahdi_exception";
8331  p->subs[idx].f.data.ptr = NULL;
8332 
8333 
8334  if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
8335  /* If nobody owns us, absorb the event appropriately, otherwise
8336  we loop indefinitely. This occurs when, during call waiting, the
8337  other end hangs up our channel so that it no longer exists, but we
8338  have neither FLASH'd nor ONHOOK'd to signify our desire to
8339  change to the other channel. */
8340  if (p->fake_event) {
8341  res = p->fake_event;
8342  p->fake_event = 0;
8343  } else
8344  res = dahdi_get_event(p->subs[SUB_REAL].dfd);
8345  /* Switch to real if there is one and this isn't something really silly... */
8346  if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
8347  (res != DAHDI_EVENT_HOOKCOMPLETE)) {
8348  ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
8349  p->owner = p->subs[SUB_REAL].owner;
8350  if (p->owner) {
8351  ast_queue_unhold(p->owner);
8352  }
8353  p->subs[SUB_REAL].needunhold = 1;
8354  }
8355  switch (res) {
8356  case DAHDI_EVENT_ONHOOK:
8357  dahdi_ec_disable(p);
8358  if (p->owner) {
8359  ast_verb(3, "Channel %s still has call, ringing phone\n", ast_channel_name(p->owner));
8360  dahdi_ring_phone(p);
8361  p->callwaitingrepeat = 0;
8362  p->cidcwexpire = 0;
8363  p->cid_suppress_expire = 0;
8364  } else
8365  ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
8366  dahdi_conf_update(p);
8367  break;
8368  case DAHDI_EVENT_RINGOFFHOOK:
8369  dahdi_ec_enable(p);
8370  dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
8371  if (p->owner && (ast_channel_state(p->owner) == AST_STATE_RINGING)) {
8372  p->subs[SUB_REAL].needanswer = 1;
8373  p->dialing = 0;
8374  }
8375  break;
8376  case DAHDI_EVENT_HOOKCOMPLETE:
8377  case DAHDI_EVENT_RINGERON:
8378  case DAHDI_EVENT_RINGEROFF:
8379  /* Do nothing */
8380  break;
8381  case DAHDI_EVENT_WINKFLASH:
8382  p->flashtime = ast_tvnow();
8383  if (p->owner) {
8384  ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, ast_channel_name(p->owner));
8385  if (ast_channel_state(p->owner) != AST_STATE_UP) {
8386  /* Answer if necessary */
8387  usedindex = dahdi_get_index(p->owner, p, 0);
8388  if (usedindex > -1) {
8389  p->subs[usedindex].needanswer = 1;
8390  }
8392  }
8393  p->callwaitingrepeat = 0;
8394  p->cidcwexpire = 0;
8395  p->cid_suppress_expire = 0;
8396  ast_queue_unhold(p->owner);
8397  p->subs[SUB_REAL].needunhold = 1;
8398  } else
8399  ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
8400  dahdi_conf_update(p);
8401  break;
8402  default:
8403  ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
8404  }
8405  f = &p->subs[idx].f;
8406  return f;
8407  }
8408  if (!(p->radio || (p->oprmode < 0)))
8409  ast_debug(1, "Exception on %d, channel %d\n", ast_channel_fd(ast, 0), p->channel);
8410  /* If it's not us, return NULL immediately */
8411  if (ast != p->owner) {
8412  if (p->owner) {
8413  ast_log(LOG_WARNING, "We're %s, not %s\n", ast_channel_name(ast), ast_channel_name(p->owner));
8414  }
8415  f = &p->subs[idx].f;
8416  return f;
8417  }
8418 
8419  f = dahdi_handle_event(ast);
8420  if (!f) {
8421  const char *name = ast_strdupa(ast_channel_name(ast));
8422 
8423  /* Tell the CDR this DAHDI device hung up */
8424  ast_mutex_unlock(&p->lock);
8425  ast_channel_unlock(ast);
8426  ast_set_hangupsource(ast, name, 0);
8427  ast_channel_lock(ast);
8428  ast_mutex_lock(&p->lock);
8429  }
8430  return f;
8431 }
#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:7409
static int dahdi_ring_phone(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7124
char * name
Definition: chan_dahdi.c:4396
static int dahdi_set_hook(int fd, int hs)
Definition: chan_dahdi.c:4957
void dahdi_ec_enable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4673
void dahdi_conf_update(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4618
static const char * event2str(int event)
Definition: chan_dahdi.c:4417
void dahdi_ec_disable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4745
static int dahdi_get_event(int fd)
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition: chan_dahdi.c:705
#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_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
#define LOG_WARNING
#define ast_mutex_unlock(a)
Definition: lock.h:188
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
union ast_frame::@254 data
struct timeval delivery
enum ast_frame_type frametype
const char * src
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:157
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:233

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

◆ __unload_module()

static int __unload_module ( void  )
static

Definition at line 17573 of file chan_dahdi.c.

17574 {
17575  struct dahdi_pvt *p;
17576 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17577  int i, j;
17578 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
17579 
17580 #ifdef HAVE_PRI
17581  for (i = 0; i < NUM_SPANS; i++) {
17582  if (pris[i].pri.master != AST_PTHREADT_NULL) {
17583  pthread_cancel(pris[i].pri.master);
17584  pthread_kill(pris[i].pri.master, SIGURG);
17585  }
17586  }
17587  ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
17588  ast_unregister_application(dahdi_send_keypad_facility_app);
17589 #ifdef HAVE_PRI_PROG_W_CAUSE
17590  ast_unregister_application(dahdi_send_callrerouting_facility_app);
17591 #endif
17592 #endif
17593 #if defined(HAVE_SS7)
17594  for (i = 0; i < NUM_SPANS; i++) {
17595  if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
17596  pthread_cancel(linksets[i].ss7.master);
17597  pthread_kill(linksets[i].ss7.master, SIGURG);
17598  }
17599  }
17600  ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
17601 #endif /* defined(HAVE_SS7) */
17602 #if defined(HAVE_OPENR2)
17603  dahdi_r2_destroy_links();
17604  ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
17605  ast_unregister_application(dahdi_accept_r2_call_app);
17606 #endif
17607 
17609  ast_manager_unregister("DAHDIDialOffhook");
17610  ast_manager_unregister("DAHDIHangup");
17611  ast_manager_unregister("DAHDITransfer");
17612  ast_manager_unregister("DAHDIDNDoff");
17613  ast_manager_unregister("DAHDIDNDon");
17614  ast_manager_unregister("DAHDIShowChannels");
17615  ast_manager_unregister("DAHDIRestart");
17616 #if defined(HAVE_PRI)
17617  ast_manager_unregister("PRIShowSpans");
17618  ast_manager_unregister("PRIDebugSet");
17619  ast_manager_unregister("PRIDebugFileSet");
17620  ast_manager_unregister("PRIDebugFileUnset");
17621 #endif /* defined(HAVE_PRI) */
17623 
17624  /* Hangup all interfaces if they have an owner */
17626  for (p = iflist; p; p = p->next) {
17627  if (p->owner)
17629  }
17631 
17634  pthread_cancel(monitor_thread);
17635  pthread_kill(monitor_thread, SIGURG);
17636  pthread_join(monitor_thread, NULL);
17637  }
17640 
17642 
17643 #if defined(HAVE_PRI)
17644  for (i = 0; i < NUM_SPANS; i++) {
17645  if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
17646  pthread_join(pris[i].pri.master, NULL);
17647  }
17648  for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
17649  dahdi_close_pri_fd(&(pris[i]), j);
17650  }
17651  sig_pri_stop_pri(&pris[i].pri);
17652  }
17653 #if defined(HAVE_PRI_CCSS)
17654  ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
17655  ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
17656 #endif /* defined(HAVE_PRI_CCSS) */
17657  sig_pri_unload();
17658 #endif
17659 
17660 #if defined(HAVE_SS7)
17661  for (i = 0; i < NUM_SPANS; i++) {
17662  if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
17663  pthread_join(linksets[i].ss7.master, NULL);
17664  }
17665  for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
17666  dahdi_close_ss7_fd(&(linksets[i]), j);
17667  }
17668  if (linksets[i].ss7.ss7) {
17669  ss7_destroy(linksets[i].ss7.ss7);
17670  linksets[i].ss7.ss7 = NULL;
17671  }
17672  }
17673 #endif /* defined(HAVE_SS7) */
17675 
17677 
17680  STASIS_MESSAGE_TYPE_CLEANUP(dahdichannel_type);
17681  return 0;
17682 }
#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:678
#define NUM_SPANS
Definition: chan_dahdi.c:606
static struct dahdi_pvt * iflist
Definition: chan_dahdi.c:854
static ast_cond_t ss_thread_complete
Definition: chan_dahdi.c:694
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:689
static struct ast_channel_tech dahdi_tech
Definition: chan_dahdi.c:1087
static struct ast_cli_entry dahdi_cli[]
Definition: chan_dahdi.c:16255
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:693
static void destroy_all_channels(void)
Definition: chan_dahdi.c:5688
@ 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:7268
#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 19962 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 3468 of file chan_dahdi.c.

3469 {
3470  int res;
3471  if (p->subs[SUB_REAL].owner == ast)
3472  res = 0;
3473  else if (p->subs[SUB_CALLWAIT].owner == ast)
3474  res = 1;
3475  else if (p->subs[SUB_THREEWAY].owner == ast)
3476  res = 2;
3477  else {
3478  res = -1;
3479  if (!nullok)
3481  "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
3482  ast ? ast_channel_name(ast) : "", p->channel, fname, line);
3483  }
3484  return res;
3485 }
#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 16407 of file chan_dahdi.c.

16408 {
16409  struct dahdi_pvt *p;
16410  const char *channel = astman_get_header(m, "DAHDIChannel");
16411  const char *number = astman_get_header(m, "Number");
16412  int i;
16413 
16414  if (ast_strlen_zero(channel)) {
16415  astman_send_error(s, m, "No channel specified");
16416  return 0;
16417  }
16418  if (ast_strlen_zero(number)) {
16419  astman_send_error(s, m, "No number specified");
16420  return 0;
16421  }
16423  if (!p) {
16424  astman_send_error(s, m, "No such channel");
16425  return 0;
16426  }
16427  if (!p->owner) {
16428  astman_send_error(s, m, "Channel does not have it's owner");
16429  return 0;
16430  }
16431  for (i = 0; i < strlen(number); i++) {
16432  struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16433  dahdi_queue_frame(p, &f);
16434  }
16435  astman_send_ack(s, m, "DAHDIDialOffhook");
16436  return 0;
16437 }
static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
Definition: chan_dahdi.c:3525
static struct dahdi_pvt * find_channel_from_str(const char *channel)
Definition: chan_dahdi.c:16311
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3166
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3198
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:2827
#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 16342 of file chan_dahdi.c.

16343 {
16344  struct dahdi_pvt *p;
16345  const char *channel = astman_get_header(m, "DAHDIChannel");
16346 
16347  if (ast_strlen_zero(channel)) {
16348  astman_send_error(s, m, "No channel specified");
16349  return 0;
16350  }
16352  if (!p) {
16353  astman_send_error(s, m, "No such channel");
16354  return 0;
16355  }
16356  dahdi_dnd(p, 0);
16357  astman_send_ack(s, m, "DND Disabled");
16358  return 0;
16359 }
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:9496

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

16324 {
16325  struct dahdi_pvt *p;
16326  const char *channel = astman_get_header(m, "DAHDIChannel");
16327 
16328  if (ast_strlen_zero(channel)) {
16329  astman_send_error(s, m, "No channel specified");
16330  return 0;
16331  }
16333  if (!p) {
16334  astman_send_error(s, m, "No such channel");
16335  return 0;
16336  }
16337  dahdi_dnd(p, 1);
16338  astman_send_ack(s, m, "DND Enabled");
16339  return 0;
16340 }

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

15598 {
15599  if (dahdi_restart() != 0) {
15600  astman_send_error(s, m, "Failed rereading DAHDI configuration");
15601  return 1;
15602  }
15603  astman_send_ack(s, m, "DAHDIRestart: Success");
15604  return 0;
15605 }
static int dahdi_restart(void)
Definition: chan_dahdi.c:15459

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

16440 {
16441  struct dahdi_pvt *tmp = NULL;
16442  const char *id = astman_get_header(m, "ActionID");
16443  const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16444  char idText[256];
16445  int channels = 0;
16446  int dahdichanquery;
16447 
16448  if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16449  /* Not numeric string. */
16450  dahdichanquery = -1;
16451  }
16452 
16453  idText[0] = '\0';
16454  if (!ast_strlen_zero(id)) {
16455  snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16456  }
16457 
16458  astman_send_listack(s, m, "DAHDI channel status will follow", "start");
16459 
16461 
16462  for (tmp = iflist; tmp; tmp = tmp->next) {
16463  if (tmp->channel > 0) {
16464  int alm;
16465 
16466  /* If a specific channel is queried for, only deliver status for that channel */
16467  if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16468  continue;
16469 
16470  alm = get_alarms(tmp);
16471  channels++;
16472  if (tmp->owner) {
16473  /* Add data if we have a current call */
16474  astman_append(s,
16475  "Event: DAHDIShowChannels\r\n"
16476  "DAHDIChannel: %d\r\n"
16477  "Channel: %s\r\n"
16478  "Uniqueid: %s\r\n"
16479  "AccountCode: %s\r\n"
16480  "Signalling: %s\r\n"
16481  "SignallingCode: %d\r\n"
16482  "Context: %s\r\n"
16483  "DND: %s\r\n"
16484  "Alarm: %s\r\n"
16485  "Description: %s\r\n"
16486  "%s"
16487  "\r\n",
16488  tmp->channel,
16489  ast_channel_name(tmp->owner),
16490  ast_channel_uniqueid(tmp->owner),
16491  ast_channel_accountcode(tmp->owner),
16492  sig2str(tmp->sig),
16493  tmp->sig,
16494  tmp->context,
16495  dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16496  alarm2str(alm),
16497  tmp->description, idText);
16498  } else {
16499  astman_append(s,
16500  "Event: DAHDIShowChannels\r\n"
16501  "DAHDIChannel: %d\r\n"
16502  "Signalling: %s\r\n"
16503  "SignallingCode: %d\r\n"
16504  "Context: %s\r\n"
16505  "DND: %s\r\n"
16506  "Alarm: %s\r\n"
16507  "Description: %s\r\n"
16508  "%s"
16509  "\r\n",
16510  tmp->channel, sig2str(tmp->sig), tmp->sig,
16511  tmp->context,
16512  dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16513  alarm2str(alm),
16514  tmp->description, idText);
16515  }
16516  }
16517  }
16518 
16520 
16521  astman_send_list_complete_start(s, m, "DAHDIShowChannelsComplete", channels);
16522  astman_append(s, "Items: %d\r\n", channels);
16524  return 0;
16525 }
static int tmp()
Definition: bt_open.c:389
static char * alarm2str(int alm)
Definition: chan_dahdi.c:4407
#define sig2str
Definition: chan_dahdi.c:4490
static int get_alarms(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7227
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:3208
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:3244
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3252
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3087

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

16362 {
16363  struct dahdi_pvt *p;
16364  const char *channel = astman_get_header(m, "DAHDIChannel");
16365 
16366  if (ast_strlen_zero(channel)) {
16367  astman_send_error(s, m, "No channel specified");
16368  return 0;
16369  }
16371  if (!p) {
16372  astman_send_error(s, m, "No such channel");
16373  return 0;
16374  }
16375  if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16376  astman_send_error(s, m, "Channel signaling is not analog");
16377  return 0;
16378  }
16380  astman_send_ack(s, m, "DAHDITransfer");
16381  return 0;
16382 }
#define TRANSFER
Definition: chan_dahdi.c:16269
static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
Definition: chan_dahdi.c:16272
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 16384 of file chan_dahdi.c.

16385 {
16386  struct dahdi_pvt *p;
16387  const char *channel = astman_get_header(m, "DAHDIChannel");
16388 
16389  if (ast_strlen_zero(channel)) {
16390  astman_send_error(s, m, "No channel specified");
16391  return 0;
16392  }
16394  if (!p) {
16395  astman_send_error(s, m, "No such channel");
16396  return 0;
16397  }
16398  if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16399  astman_send_error(s, m, "Channel signaling is not analog");
16400  return 0;
16401  }
16403  astman_send_ack(s, m, "DAHDIHangup");
16404  return 0;
16405 }
#define HANGUP
Definition: chan_dahdi.c:16270

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

4408 {
4409  int x;
4410  for (x = 0; x < ARRAY_LEN(alarms); x++) {
4411  if (alarms[x].alarm & alm)
4412  return alarms[x].name;
4413  }
4414  return alm ? "Unknown Alarm" : "No Alarm";
4415 }
int alarm
Definition: chan_dahdi.c:4395
static struct @105 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 4202 of file chan_dahdi.c.

4203 {
4204  struct dahdi_bufferinfo bi;
4205  int res;
4206  if (p->subs[x].dfd >= 0) {
4207  ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
4208  return -1;
4209  }
4210 
4211  p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
4212  if (p->subs[x].dfd <= -1) {
4213  ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
4214  return -1;
4215  }
4216 
4217  res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
4218  if (!res) {
4219  bi.txbufpolicy = p->buf_policy;
4220  bi.rxbufpolicy = p->buf_policy;
4221  bi.numbufs = p->buf_no;
4222  res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
4223  if (res < 0) {
4224  ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
4225  }
4226  } else
4227  ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
4228 
4229  if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
4230  ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
4231  dahdi_close_sub(p, x);
4232  p->subs[x].dfd = -1;
4233  return -1;
4234  }
4235  ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
4236  return 0;
4237 }
static int dahdi_open(char *fn)
Definition: chan_dahdi.c:4121
static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
Definition: chan_dahdi.c:4174
const char *const subnames[]
Definition: chan_dahdi.c:848
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 9542 of file chan_dahdi.c.

9543 {
9544  struct ast_channel *chan = data;
9545  struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
9546  char exten[AST_MAX_EXTENSION] = "";
9547  char exten2[AST_MAX_EXTENSION] = "";
9548  unsigned char buf[256];
9549  char dtmfcid[300];
9550  char dtmfbuf[300];
9551  struct callerid_state *cs = NULL;
9552  char *name = NULL, *number = NULL;
9553  int distMatches;
9554  int curRingData[3];
9555  int receivedRingT;
9556  int counter1;
9557  int counter;
9558  int samples = 0;
9559  struct ast_smdi_md_message *smdi_msg = NULL;
9560  int flags = 0;
9561  int i;
9562  int timeout;
9563  int getforward = 0;
9564  char *s1, *s2;
9565  int len = 0;
9566  int res;
9567  int idx;
9568  RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
9569  const char *pickupexten;
9570 
9572  ss_thread_count++;
9574  /* in the bizarre case where the channel has become a zombie before we
9575  even get started here, abort safely
9576  */
9577  if (!p) {
9578  ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", ast_channel_name(chan));
9579  ast_hangup(chan);
9580  goto quit;
9581  }
9582  ast_verb(3, "Starting simple switch on '%s'\n", ast_channel_name(chan));
9583  idx = dahdi_get_index(chan, p, 1);
9584  if (idx < 0) {
9585  ast_log(LOG_WARNING, "Huh?\n");
9586  ast_hangup(chan);
9587  goto quit;
9588  }
9589 
9590  ast_channel_lock(chan);
9591  pickup_cfg = ast_get_chan_features_pickup_config(chan);
9592  if (!pickup_cfg) {
9593  ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
9594  pickupexten = "";
9595  } else {
9596  pickupexten = ast_strdupa(pickup_cfg->pickupexten);
9597  }
9598  ast_channel_unlock(chan);
9599 
9600  if (p->dsp)
9601  ast_dsp_digitreset(p->dsp);
9602  switch (p->sig) {
9603  case SIG_FEATD:
9604  case SIG_FEATDMF:
9605  case SIG_FEATDMF_TA:
9606  case SIG_E911:
9607  case SIG_FGC_CAMAMF:
9608  case SIG_FEATB:
9609  case SIG_EMWINK:
9610  case SIG_SF_FEATD:
9611  case SIG_SF_FEATDMF:
9612  case SIG_SF_FEATB:
9613  case SIG_SFWINK:
9614  if (dahdi_wink(p, idx))
9615  goto quit;
9616  /* Fall through */
9617  case SIG_EM:
9618  case SIG_EM_E1:
9619  case SIG_SF:
9620  case SIG_FGC_CAMA:
9621  res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9622  if (p->dsp)
9623  ast_dsp_digitreset(p->dsp);
9624  /* set digit mode appropriately */
9625  if (p->dsp) {
9626  if (NEED_MFDETECT(p))
9628  else
9630  }
9631  memset(dtmfbuf, 0, sizeof(dtmfbuf));
9632  /* Wait for the first digit only if immediate=no */
9633  if (!p->immediate)
9634  /* Wait for the first digit (up to 5 seconds). */
9635  res = ast_waitfordigit(chan, 5000);
9636  else
9637  res = 0;
9638  if (res > 0) {
9639  /* save first char */
9640  dtmfbuf[0] = res;
9641  switch (p->sig) {
9642  case SIG_FEATD:
9643  case SIG_SF_FEATD:
9644  res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
9645  if (res > 0)
9646  res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
9647  if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9648  break;
9649  case SIG_FEATDMF_TA:
9650  res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9651  if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9652  if (dahdi_wink(p, idx)) goto quit;
9653  dtmfbuf[0] = 0;
9654  /* Wait for the first digit (up to 5 seconds). */
9655  res = ast_waitfordigit(chan, 5000);
9656  if (res <= 0) break;
9657  dtmfbuf[0] = res;
9658  /* fall through intentionally */
9659  case SIG_FEATDMF:
9660  case SIG_E911:
9661  case SIG_FGC_CAMAMF:
9662  case SIG_SF_FEATDMF:
9663  res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9664  /* if international caca, do it again to get real ANO */
9665  if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
9666  {
9667  if (dahdi_wink(p, idx)) goto quit;
9668  dtmfbuf[0] = 0;
9669  /* Wait for the first digit (up to 5 seconds). */
9670  res = ast_waitfordigit(chan, 5000);
9671  if (res <= 0) break;
9672  dtmfbuf[0] = res;
9673  res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9674  }
9675  if (res > 0) {
9676  /* if E911, take off hook */
9677  if (p->sig == SIG_E911)
9678  dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
9679  res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
9680  }
9681  if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9682  break;
9683  case SIG_FEATB:
9684  case SIG_SF_FEATB:
9685  res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9686  if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9687  break;
9688  case SIG_EMWINK:
9689  /* if we received a '*', we are actually receiving Feature Group D
9690  dial syntax, so use that mode; otherwise, fall through to normal
9691  mode
9692  */
9693  if (res == '*') {
9694  res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
9695  if (res > 0)
9696  res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
9697  if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9698  break;
9699  }
9700  default:
9701  /* If we got the first digit, get the rest */
9702  len = 1;
9703  dtmfbuf[len] = '\0';
9704  while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
9705  if (ast_exists_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
9706  timeout = p->matchdigit_timeout;
9707  } else {
9708  timeout = p->interdigit_timeout;
9709  }
9710  res = ast_waitfordigit(chan, timeout);
9711  if (res < 0) {
9712  ast_debug(1, "waitfordigit returned < 0...\n");
9713  ast_hangup(chan);
9714  goto quit;
9715  } else if (res) {
9716  dtmfbuf[len++] = res;
9717  dtmfbuf[len] = '\0';
9718  } else {
9719  break;
9720  }
9721  }
9722  break;
9723  }
9724  }
9725  if (res == -1) {
9726  ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
9727  ast_hangup(chan);
9728  goto quit;
9729  } else if (res < 0) {
9730  ast_debug(1, "Got hung up before digits finished\n");
9731  ast_hangup(chan);
9732  goto quit;
9733  }
9734 
9735  if (p->sig == SIG_FGC_CAMA) {
9736  char anibuf[100];
9737 
9738  if (ast_safe_sleep(chan,1000) == -1) {
9739  ast_hangup(chan);
9740  goto quit;
9741  }
9742  dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
9744  res = my_getsigstr(chan, anibuf, "#", 10000);
9745  if ((res > 0) && (strlen(anibuf) > 2)) {
9746  if (anibuf[strlen(anibuf) - 1] == '#')
9747  anibuf[strlen(anibuf) - 1] = 0;
9748  ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
9749  }
9751  }
9752 
9753  ast_copy_string(exten, dtmfbuf, sizeof(exten));
9754  if (ast_strlen_zero(exten))
9755  ast_copy_string(exten, "s", sizeof(exten));
9756  if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
9757  /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
9758  if (exten[0] == '*') {
9759  char *stringp=NULL;
9760  ast_copy_string(exten2, exten, sizeof(exten2));
9761  /* Parse out extension and callerid */
9762  stringp=exten2 +1;
9763  s1 = strsep(&stringp, "*");
9764  s2 = strsep(&stringp, "*");
9765  if (s2) {
9766  if (!ast_strlen_zero(p->cid_num))
9767  ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
9768  else
9769  ast_set_callerid(chan, s1, NULL, s1);
9770  ast_copy_string(exten, s2, sizeof(exten));
9771  } else
9772  ast_copy_string(exten, s1, sizeof(exten));
9773  } else if (p->sig == SIG_FEATD)
9774  ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
9775  }
9776  if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
9777  if (exten[0] == '*') {
9778  char *stringp=NULL;
9779  ast_copy_string(exten2, exten, sizeof(exten2));
9780  /* Parse out extension and callerid */
9781  stringp=exten2 +1;
9782  s1 = strsep(&stringp, "#");
9783  s2 = strsep(&stringp, "#");
9784  if (s2) {
9785  if (!ast_strlen_zero(p->cid_num))
9786  ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
9787  else
9788  if (*(s1 + 2))
9789  ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
9790  ast_copy_string(exten, s2 + 1, sizeof(exten));
9791  } else
9792  ast_copy_string(exten, s1 + 2, sizeof(exten));
9793  } else
9794  ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
9795  }
9796  if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
9797  if (exten[0] == '*') {
9798  char *stringp=NULL;
9799  ast_copy_string(exten2, exten, sizeof(exten2));
9800  /* Parse out extension and callerid */
9801  stringp=exten2 +1;
9802  s1 = strsep(&stringp, "#");
9803  s2 = strsep(&stringp, "#");
9804  if (s2 && (*(s2 + 1) == '0')) {
9805  if (*(s2 + 2))
9806  ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
9807  }
9808  if (s1) ast_copy_string(exten, s1, sizeof(exten));
9809  else ast_copy_string(exten, "911", sizeof(exten));
9810  } else
9811  ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
9812  }
9813  if (p->sig == SIG_FEATB) {
9814  if (exten[0] == '*') {
9815  char *stringp=NULL;
9816  ast_copy_string(exten2, exten, sizeof(exten2));
9817  /* Parse out extension and callerid */
9818  stringp=exten2 +1;
9819  s1 = strsep(&stringp, "#");
9820  ast_copy_string(exten, exten2 + 1, sizeof(exten));
9821  } else
9822  ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
9823  }
9824  if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
9825  dahdi_wink(p, idx);
9826  /* some switches require a minimum guard time between
9827  the last FGD wink and something that answers
9828  immediately. This ensures it */
9829  if (ast_safe_sleep(chan, 100)) {
9830  ast_hangup(chan);
9831  goto quit;
9832  }
9833  }
9834  dahdi_ec_enable(p);
9835  if (NEED_MFDETECT(p)) {
9836  if (p->dsp) {
9837  if (!p->hardwaredtmf)
9839  else {
9840  ast_dsp_free(p->dsp);
9841  p->dsp = NULL;
9842  }
9843  }
9844  }
9845 
9846  if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1,
9847  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
9849  if (p->dsp) ast_dsp_digitreset(p->dsp);
9850  res = ast_pbx_run(chan);
9851  if (res) {
9852  ast_log(LOG_WARNING, "PBX exited non-zero\n");
9853  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
9854  }
9855  goto quit;
9856  } else {
9857  ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, ast_channel_context(chan));
9858  sleep(2);
9859  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
9860  if (res < 0)
9861  ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
9862  else
9863  sleep(1);
9864  res = ast_streamfile(chan, "ss-noservice", ast_channel_language(chan));
9865  if (res >= 0)
9866  ast_waitstream(chan, "");
9867  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
9868  ast_hangup(chan);
9869  goto quit;
9870  }
9871  break;
9872  case SIG_FXOLS:
9873  case SIG_FXOGS:
9874  case SIG_FXOKS:
9875  /* Read the first digit */
9876  timeout = p->firstdigit_timeout;
9877  /* If starting a threeway call, never timeout on the first digit so someone
9878  can use flash-hook as a "hold" feature */
9879  if (p->subs[SUB_THREEWAY].owner)
9880  timeout = INT_MAX;
9881  while (len < AST_MAX_EXTENSION-1) {
9882  int is_exten_parking = 0;
9883 
9884  /* Read digit unless it's supposed to be immediate, in which case the
9885  only answer is 's' */
9886  if (p->immediate)
9887  res = 's';
9888  else
9889  res = ast_waitfordigit(chan, timeout);
9890  timeout = 0;
9891  if (res < 0) {
9892  ast_debug(1, "waitfordigit returned < 0...\n");
9893  res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9894  ast_hangup(chan);
9895  goto quit;
9896  } else if (res) {
9897  ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
9898  exten[len++]=res;
9899  exten[len] = '\0';
9900  }
9902  tone_zone_play_tone(p->subs[idx].dfd, -1);
9903  } else {
9904  tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
9905  }
9907  is_exten_parking = ast_parking_is_exten_park(ast_channel_context(chan), exten);
9908  }
9909  if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num) && !is_exten_parking) {
9910  if (!res || !ast_matchmore_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num)) {
9911  if (getforward) {
9912  /* Record this as the forwarding extension */
9914  ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
9915  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
9916  if (res)
9917  break;
9918  usleep(500000);
9919  res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9920  sleep(1);
9921  memset(exten, 0, sizeof(exten));
9922  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
9923  len = 0;
9924  getforward = 0;
9925  } else {
9926  res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9927  ast_channel_lock(chan);
9929  if (!ast_strlen_zero(p->cid_num)) {
9930  if (!p->hidecallerid)
9931  ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
9932  else
9933  ast_set_callerid(chan, NULL, NULL, p->cid_num);
9934  }
9935  if (!ast_strlen_zero(p->cid_name)) {
9936  if (!p->hidecallerid)
9937  ast_set_callerid(chan, NULL, p->cid_name, NULL);
9938  }
9940  ast_channel_unlock(chan);
9941  dahdi_ec_enable(p);
9942  res = ast_pbx_run(chan);
9943  if (res) {
9944  ast_log(LOG_WARNING, "PBX exited non-zero\n");
9945  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
9946  }
9947  goto quit;
9948  }
9949  } else {
9950  /* It's a match, but they just typed a digit, and there is an ambiguous match,
9951  so just set the timeout to matchdigit_timeout and wait some more */
9952  timeout = p->matchdigit_timeout;
9953  }
9954  } else if (res == 0) {
9955  ast_debug(1, "not enough digits (and no ambiguous match)...\n");
9956  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
9957  dahdi_wait_event(p->subs[idx].dfd);
9958  ast_hangup(chan);
9959  goto quit;
9960  } else if (p->callwaiting && !strcmp(exten, "*70")) {
9961  ast_verb(3, "Disabling call waiting on %s\n", ast_channel_name(chan));
9962  /* Disable call waiting if enabled */
9963  p->callwaiting = 0;
9964  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
9965  if (res) {
9966  ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
9967  ast_channel_name(chan), strerror(errno));
9968  }
9969  len = 0;
9970  ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
9971  memset(exten, 0, sizeof(exten));
9972  timeout = p->firstdigit_timeout;
9973 
9974  } else if (!strcmp(exten, pickupexten)) {
9975  /* Scan all channels and see if there are any
9976  * ringing channels that have call groups
9977  * that equal this channels pickup group
9978  */
9979  if (idx == SUB_REAL) {
9980  /* Switch us from Third call to Call Wait */
9981  if (p->subs[SUB_THREEWAY].owner) {
9982  /* If you make a threeway call and the *8# a call, it should actually
9983  look like a callwait */
9984  alloc_sub(p, SUB_CALLWAIT);
9987  }
9988  dahdi_ec_enable(p);
9989  if (ast_pickup_call(chan)) {
9990  ast_debug(1, "No call pickup possible...\n");
9991  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
9992  dahdi_wait_event(p->subs[idx].dfd);
9993  }
9994  ast_hangup(chan);
9995  goto quit;
9996  } else {
9997  ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
9998  ast_hangup(chan);
9999  goto quit;
10000  }
10001 
10002  } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10003  ast_verb(3, "Disabling Caller*ID on %s\n", ast_channel_name(chan));
10004  /* Disable Caller*ID if enabled */
10005  p->hidecallerid = 1;
10010  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10011  if (res) {
10012  ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10013  ast_channel_name(chan), strerror(errno));
10014  }
10015  len = 0;
10016  memset(exten, 0, sizeof(exten));
10017  timeout = p->firstdigit_timeout;
10018  } else if (p->callreturn && !strcmp(exten, "*69")) {
10019  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10020  break;
10021  } else if (!strcmp(exten, "*78")) {
10022  dahdi_dnd(p, 1);
10023  /* Do not disturb */
10024  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10025  getforward = 0;
10026  memset(exten, 0, sizeof(exten));
10027  len = 0;
10028  } else if (!strcmp(exten, "*79")) {
10029  dahdi_dnd(p, 0);
10030  /* Do not disturb */
10031  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10032  getforward = 0;
10033  memset(exten, 0, sizeof(exten));
10034  len = 0;
10035  } else if (p->cancallforward && !strcmp(exten, "*72")) {
10036  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10037  getforward = 1;
10038  memset(exten, 0, sizeof(exten));
10039  len = 0;
10040  } else if (p->cancallforward && !strcmp(exten, "*73")) {
10041  ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10042  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10043  memset(p->call_forward, 0, sizeof(p->call_forward));
10044  getforward = 0;
10045  memset(exten, 0, sizeof(exten));
10046  len = 0;
10047  } else if ((p->transfer || p->canpark) && is_exten_parking
10048  && p->subs[SUB_THREEWAY].owner) {
10049  struct ast_bridge_channel *bridge_channel;
10050 
10051  /*
10052  * This is a three way call, the main call being a real channel,
10053  * and we're parking the first call.
10054  */
10056  bridge_channel = ast_channel_get_bridge_channel(p->subs[SUB_THREEWAY].owner);
10058  if (bridge_channel) {
10060  /*
10061  * Swap things around between the three-way and real call so we
10062  * can hear where the channel got parked.
10063  */
10064  ast_mutex_lock(&p->lock);
10065  p->owner = p->subs[SUB_THREEWAY].owner;
10067  ast_mutex_unlock(&p->lock);
10068 
10069  ast_verb(3, "%s: Parked call\n", ast_channel_name(chan));
10070  ast_hangup(chan);
10071  ao2_ref(bridge_channel, -1);
10072  goto quit;
10073  }
10074  ao2_ref(bridge_channel, -1);
10075  }
10076  break;
10077  } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10078  ast_verb(3, "Enabling Caller*ID on %s\n", ast_channel_name(chan));
10079  /* Enable Caller*ID if enabled */
10080  p->hidecallerid = 0;
10082  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10083  if (res) {
10084  ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10085  ast_channel_name(chan), strerror(errno));
10086  }
10087  len = 0;
10088  memset(exten, 0, sizeof(exten));
10089  timeout = p->firstdigit_timeout;
10090  } else if (!strcmp(exten, "*0")) {
10091  struct ast_channel *nbridge =
10092  p->subs[SUB_THREEWAY].owner;
10093  struct dahdi_pvt *pbridge = NULL;
10094  RAII_VAR(struct ast_channel *, bridged, nbridge ? ast_channel_bridge_peer(nbridge) : NULL, ast_channel_cleanup);
10095 
10096  /* set up the private struct of the bridged one, if any */
10097  if (nbridge && bridged) {
10098  pbridge = ast_channel_tech_pvt(bridged);
10099  }
10100  if (nbridge && pbridge &&
10101  (ast_channel_tech(nbridge) == &dahdi_tech) &&
10102  (ast_channel_tech(bridged) == &dahdi_tech) &&
10103  ISTRUNK(pbridge)) {
10104  int func = DAHDI_FLASH;
10105  /* Clear out the dial buffer */
10106  p->dop.dialstr[0] = '\0';
10107  /* flash hookswitch */
10108  if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10109  ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10110  ast_channel_name(nbridge), strerror(errno));
10111  }
10114  p->owner = p->subs[SUB_REAL].owner;
10116  ast_hangup(chan);
10117  goto quit;
10118  } else {
10119  tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10120  dahdi_wait_event(p->subs[idx].dfd);
10121  tone_zone_play_tone(p->subs[idx].dfd, -1);
10124  p->owner = p->subs[SUB_REAL].owner;
10125  ast_hangup(chan);
10126  goto quit;
10127  }
10128  } else if (!ast_canmatch_extension(chan, ast_channel_context(chan), exten, 1,
10129  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))
10130  && !canmatch_featurecode(pickupexten, exten)) {
10131  ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10132  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<Unknown Caller>"),
10133  ast_channel_context(chan));
10134  break;
10135  }
10136  if (!timeout)
10137  timeout = p->interdigit_timeout;
10139  tone_zone_play_tone(p->subs[idx].dfd, -1);
10140  }
10141  break;
10142  case SIG_FXSLS:
10143  case SIG_FXSGS:
10144  case SIG_FXSKS:
10145  /* check for SMDI messages */
10146  if (p->use_smdi && p->smdi_iface) {
10148 
10149  if (smdi_msg != NULL) {
10150  ast_channel_exten_set(chan, smdi_msg->fwd_st);
10151 
10152  if (smdi_msg->type == 'B')
10153  pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10154  else if (smdi_msg->type == 'N')
10155  pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10156 
10157  ast_debug(1, "Received SMDI message on %s\n", ast_channel_name(chan));
10158  } else {
10159  ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10160  }
10161  }
10162 
10163  if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10164  number = smdi_msg->calling_st;
10165 
10166  /* If we want caller id, we're in a prering state due to a polarity reversal
10167  * and we're set to use a polarity reversal to trigger the start of caller id,
10168  * grab the caller id and wait for ringing to start... */
10169  } else if (p->use_callerid && (ast_channel_state(chan) == AST_STATE_PRERING &&
10171  /* If set to use DTMF CID signalling, listen for DTMF */
10172  if (p->cid_signalling == CID_SIG_DTMF) {
10173  int k = 0;
10174  int off_ms;
10175  struct timeval start = ast_tvnow();
10176  int ms;
10177  cs = NULL;
10178  ast_debug(1, "Receiving DTMF cid on channel %s\n", ast_channel_name(chan));
10179  dahdi_setlinear(p->subs[idx].dfd, 0);
10180  /*
10181  * We are the only party interested in the Rx stream since
10182  * we have not answered yet. We don't need or even want DTMF
10183  * emulation. The DTMF digits can come so fast that emulation
10184  * can drop some of them.
10185  */
10186  ast_channel_lock(chan);
10188  ast_channel_unlock(chan);
10189  off_ms = 4000;/* This is a typical OFF time between rings. */
10190  for (;;) {
10191  struct ast_frame *f;
10192 
10193  ms = ast_remaining_ms(start, off_ms);
10194  res = ast_waitfor(chan, ms);
10195  if (res <= 0) {
10196  /*
10197  * We do not need to restore the dahdi_setlinear()
10198  * or AST_FLAG_END_DTMF_ONLY flag settings since we
10199  * are hanging up the channel.
10200  */
10201  ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10202  "Exiting simple switch\n");
10203  ast_hangup(chan);
10204  goto quit;
10205  }
10206  f = ast_read(chan);
10207  if (!f)
10208  break;
10209  if (f->frametype == AST_FRAME_DTMF) {
10210  if (k < ARRAY_LEN(dtmfbuf) - 1) {
10211  dtmfbuf[k++] = f->subclass.integer;
10212  }
10213  ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10214  start = ast_tvnow();
10215  }
10216  ast_frfree(f);
10217  if (ast_channel_state(chan) == AST_STATE_RING ||
10219  break; /* Got ring */
10220  }
10221  ast_channel_lock(chan);
10223  ast_channel_unlock(chan);
10224  dtmfbuf[k] = '\0';
10225  dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10226  /* Got cid and ring. */
10227  ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10228  callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10229  ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10230  /* If first byte is NULL, we have no cid */
10231  if (!ast_strlen_zero(dtmfcid))
10232  number = dtmfcid;
10233  else
10234  number = NULL;
10235  /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10236  } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10237  cs = callerid_new(p->cid_signalling);
10238  if (cs) {
10239  int off_ms;
10240  struct timeval start;
10241  int ms;
10242  samples = 0;
10243 #if 1
10244  bump_gains(p);
10245 #endif
10246  /* Take out of linear mode for Caller*ID processing */
10247  dahdi_setlinear(p->subs[idx].dfd, 0);
10248 
10249  /* First we wait and listen for the Caller*ID */
10250  for (;;) {
10251  i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10252  if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10253  ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10254  callerid_free(cs);
10255  ast_hangup(chan);
10256  goto quit;
10257  }
10258  if (i & DAHDI_IOMUX_SIGEVENT) {
10259  res = dahdi_get_event(p->subs[idx].dfd);
10260  ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10261  if (res == DAHDI_EVENT_NOALARM) {
10262  p->inalarm = 0;
10263  }
10264 
10265  if (p->cid_signalling == CID_SIG_V23_JP) {
10266  if (res == DAHDI_EVENT_RINGBEGIN) {
10267  res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10268  usleep(1);
10269  }
10270  } else {
10271  res = 0;
10272  break;
10273  }
10274  } else if (i & DAHDI_IOMUX_READ) {
10275  res = read(p->subs[idx].dfd, buf, sizeof(buf));
10276  if (res < 0) {
10277  if (errno != ELAST) {
10278  ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10279  callerid_free(cs);
10280  ast_hangup(chan);
10281  goto quit;
10282  }
10283  break;
10284  }
10285  samples += res;
10286 
10287  if (p->cid_signalling == CID_SIG_V23_JP) {
10288  res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10289  } else {
10290  res = callerid_feed(cs, buf, res, AST_LAW(p));
10291  }
10292  if (res < 0) {
10293  /*
10294  * The previous diagnostic message output likely
10295  * explains why it failed.
10296  */
10298  "Failed to decode CallerID on channel '%s'\n",
10299  ast_channel_name(chan));
10300  break;
10301  } else if (res)
10302  break;
10303  else if (samples > (8000 * 10))
10304  break;
10305  }
10306  }
10307  if (res == 1) {
10308  callerid_get(cs, &name, &number, &flags);
10309  ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10310  }
10311 
10312  if (p->cid_signalling == CID_SIG_V23_JP) {
10313  res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10314  usleep(1);
10315  }
10316 
10317  /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10318  start = ast_tvnow();
10319  off_ms = 4000;/* This is a typical OFF time between rings. */
10320  for (;;) {
10321  struct ast_frame *f;
10322 
10323  ms = ast_remaining_ms(start, off_ms);
10324  res = ast_waitfor(chan, ms);
10325  if (res <= 0) {
10326  ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10327  "Exiting simple switch\n");
10328  ast_hangup(chan);
10329  goto quit;
10330  }
10331  if (!(f = ast_read(chan))) {
10332  ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10333  ast_hangup(chan);
10334  goto quit;
10335  }
10336  ast_frfree(f);
10337  if (ast_channel_state(chan) == AST_STATE_RING ||
10339  break; /* Got ring */
10340  }
10341 
10342  /* We must have a ring by now, so, if configured, lets try to listen for
10343  * distinctive ringing */
10344  if (p->usedistinctiveringdetection) {
10345  len = 0;
10346  distMatches = 0;
10347  /* Clear the current ring data array so we don't have old data in it. */
10348  for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10349  curRingData[receivedRingT] = 0;
10350  receivedRingT = 0;
10351  counter = 0;
10352  counter1 = 0;
10353  /* Check to see if context is what it should be, if not set to be. */
10354  if (strcmp(p->context,p->defcontext) != 0) {
10355  ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10357  }
10358 
10359  for (;;) {
10360  i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10361  if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10362  ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10363  callerid_free(cs);
10364  ast_hangup(chan);
10365  goto quit;
10366  }
10367  if (i & DAHDI_IOMUX_SIGEVENT) {
10368  res = dahdi_get_event(p->subs[idx].dfd);
10369  ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10370  if (res == DAHDI_EVENT_NOALARM) {
10371  p->inalarm = 0;
10372  }
10373  res = 0;
10374  /* Let us detect distinctive ring */
10375 
10376  curRingData[receivedRingT] = p->ringt;
10377 
10378  if (p->ringt < p->ringt_base/2)
10379  break;
10380  /* Increment the ringT counter so we can match it against
10381  values in chan_dahdi.conf for distinctive ring */
10382  if (++receivedRingT == ARRAY_LEN(curRingData))
10383  break;
10384  } else if (i & DAHDI_IOMUX_READ) {
10385  res = read(p->subs[idx].dfd, buf, sizeof(buf));
10386  if (res < 0) {
10387  if (errno != ELAST) {
10388  ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10389  callerid_free(cs);
10390  ast_hangup(chan);
10391  goto quit;
10392  }
10393  break;
10394  }
10395  if (p->ringt > 0) {
10396  if (!(--p->ringt)) {
10397  res = -1;
10398  break;
10399  }
10400  }
10401  }
10402  }
10403  /* this only shows up if you have n of the dring patterns filled in */
10404  ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10405  for (counter = 0; counter < 3; counter++) {
10406  /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10407  channel */
10408  distMatches = 0;
10409  for (counter1 = 0; counter1 < 3; counter1++) {
10410  ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10411  if (p->drings.ringnum[counter].ring[counter1] == -1) {
10412  ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10413  curRingData[counter1]);
10414  distMatches++;
10415  } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10416  curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10417  ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10418  (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10419  (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10420  distMatches++;
10421  }
10422  }
10423 
10424  if (distMatches == 3) {
10425  /* The ring matches, set the context to whatever is for distinctive ring.. */
10426  ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10428  ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10429  break;
10430  }
10431  }
10432  }
10433  /* Restore linear mode (if appropriate) for Caller*ID processing */
10434  dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10435 #if 1
10436  restore_gains(p);
10437 #endif
10438  } else
10439  ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10440  } else {
10441  ast_log(LOG_WARNING, "Channel %s in prering "
10442  "state, but I have nothing to do. "
10443  "Terminating simple switch, should be "
10444  "restarted by the actual ring.\n",
10445  ast_channel_name(chan));
10446  ast_hangup(chan);
10447  goto quit;
10448  }
10449  } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10450  if (p->cid_signalling == CID_SIG_DTMF) {
10451  int k = 0;
10452  int off_ms;
10453  struct timeval start;
10454  int ms;
10455  cs = NULL;
10456  dahdi_setlinear(p->subs[idx].dfd, 0);
10457  off_ms = 2000;
10458  start = ast_tvnow();
10459  for (;;) {
10460  struct ast_frame *f;
10461 
10462  ms = ast_remaining_ms(start, off_ms);
10463  res = ast_waitfor(chan, ms);
10464  if (res <= 0) {
10465  ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10466  "Exiting simple switch\n");
10467  ast_hangup(chan);
10468  goto quit;
10469  }
10470  f = ast_read(chan);
10471  if (!f) {
10472  /* Hangup received waiting for DTMFCID. Exiting simple switch. */
10473  ast_hangup(chan);
10474  goto quit;
10475  }
10476  if (f->frametype == AST_FRAME_DTMF) {
10477  dtmfbuf[k++] = f->subclass.integer;
10478  ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10479  start = ast_tvnow();
10480  }
10481  ast_frfree(f);
10482 
10483  if (p->ringt_base == p->ringt)
10484  break;
10485  }
10486  dtmfbuf[k] = '\0';
10487  dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10488  /* Got cid and ring. */
10489  callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10490  ast_debug(1, "CID is '%s', flags %d\n",
10491  dtmfcid, flags);
10492  /* If first byte is NULL, we have no cid */
10493  if (!ast_strlen_zero(dtmfcid))
10494  number = dtmfcid;
10495  else
10496  number = NULL;
10497  /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10498  } else {
10499  /* FSK Bell202 callerID */
10500  cs = callerid_new(p->cid_signalling);
10501  if (cs) {
10502 #if 1
10503  bump_gains(p);
10504 #endif
10505  samples = 0;
10506  len = 0;
10507  distMatches = 0;
10508  /* Clear the current ring data array so we don't have old data in it. */
10509  for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10510  curRingData[receivedRingT] = 0;
10511  receivedRingT = 0;
10512  counter = 0;
10513  counter1 = 0;
10514  /* Check to see if context is what it should be, if not set to be. */
10515  if (strcmp(p->context,p->defcontext) != 0) {
10516  ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10518  }
10519 
10520  /* Take out of linear mode for Caller*ID processing */
10521  dahdi_setlinear(p->subs[idx].dfd, 0);
10522  for (;;) {
10523  i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10524  if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10525  ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10526  callerid_free(cs);
10527  ast_hangup(chan);
10528  goto quit;
10529  }
10530  if (i & DAHDI_IOMUX_SIGEVENT) {
10531  res = dahdi_get_event(p->subs[idx].dfd);
10532  ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10533  if (res == DAHDI_EVENT_NOALARM) {
10534  p->inalarm = 0;
10535  }
10536  /* If we get a PR event, they hung up while processing calerid */
10537  if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10538  ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10539  p->polarity = POLARITY_IDLE;
10540  callerid_free(cs);
10541  ast_hangup(chan);
10542  goto quit;
10543  }
10544  res = 0;
10545  /* Let us detect callerid when the telco uses distinctive ring */
10546 
10547  curRingData[receivedRingT] = p->ringt;
10548 
10549  if (p->ringt < p->ringt_base/2)
10550  break;
10551  /* Increment the ringT counter so we can match it against
10552  values in chan_dahdi.conf for distinctive ring */
10553  if (++receivedRingT == ARRAY_LEN(curRingData))
10554  break;
10555  } else if (i & DAHDI_IOMUX_READ) {
10556  res = read(p->subs[idx].dfd, buf, sizeof(buf));
10557  if (res < 0) {
10558  if (errno != ELAST) {
10559  ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10560  callerid_free(cs);
10561  ast_hangup(chan);
10562  goto quit;
10563  }
10564  break;
10565  }
10566  if (p->ringt > 0) {
10567  if (!(--p->ringt)) {
10568  res = -1;
10569  break;
10570  }
10571  }
10572  samples += res;
10573  res = callerid_feed(cs, buf, res, AST_LAW(p));
10574  if (res < 0) {
10575  /*
10576  * The previous diagnostic message output likely
10577  * explains why it failed.
10578  */
10580  "Failed to decode CallerID on channel '%s'\n",
10581  ast_channel_name(chan));
10582  break;
10583  } else if (res)
10584  break;
10585  else if (samples > (8000 * 10))
10586  break;
10587  }
10588  }
10589  if (res == 1) {
10590  callerid_get(cs, &name, &number, &flags);
10591  ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10592  }
10593  if (distinctiveringaftercid == 1) {
10594  /* Clear the current ring data array so we don't have old data in it. */
10595  for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10596  curRingData[receivedRingT] = 0;
10597  }
10598  receivedRingT = 0;
10599  ast_verb(3, "Detecting post-CID distinctive ring\n");
10600  for (;;) {
10601  i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10602  if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10603  ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10604  callerid_free(cs);
10605  ast_hangup(chan);
10606  goto quit;
10607  }
10608  if (i & DAHDI_IOMUX_SIGEVENT) {
10609  res = dahdi_get_event(p->subs[idx].dfd);
10610  ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10611  if (res == DAHDI_EVENT_NOALARM) {
10612  p->inalarm = 0;
10613  }
10614  res = 0;
10615  /* Let us detect callerid when the telco uses distinctive ring */
10616 
10617  curRingData[receivedRingT] = p->ringt;
10618 
10619  if (p->ringt < p->ringt_base/2)
10620  break;
10621  /* Increment the ringT counter so we can match it against
10622  values in chan_dahdi.conf for distinctive ring */
10623  if (++receivedRingT == ARRAY_LEN(curRingData))
10624  break;
10625  } else if (i & DAHDI_IOMUX_READ) {
10626  res = read(p->subs[idx].dfd, buf, sizeof(buf));
10627  if (res < 0) {
10628  if (errno != ELAST) {
10629  ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10630  callerid_free(cs);
10631  ast_hangup(chan);
10632  goto quit;
10633  }
10634  break;
10635  }
10636  if (p->ringt > 0) {
10637  if (!(--p->ringt)) {
10638  res = -1;
10639  break;
10640  }
10641  }
10642  }
10643  }
10644  }
10645  if (p->usedistinctiveringdetection) {
10646  /* this only shows up if you have n of the dring patterns filled in */
10647  ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10648 
10649  for (counter = 0; counter < 3; counter++) {
10650  /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10651  channel */
10652  /* this only shows up if you have n of the dring patterns filled in */
10653  ast_verb(3, "Checking %d,%d,%d\n",
10654  p->drings.ringnum[counter].ring[0],
10655  p->drings.ringnum[counter].ring[1],
10656  p->drings.ringnum[counter].ring[2]);
10657  distMatches = 0;
10658  for (counter1 = 0; counter1 < 3; counter1++) {
10659  ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10660  if (p->drings.ringnum[counter].ring[counter1] == -1) {
10661  ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10662  curRingData[counter1]);
10663  distMatches++;
10664  }
10665  else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10666  curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10667  ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10668  (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10669  (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10670  distMatches++;
10671  }
10672  }
10673  if (distMatches == 3) {
10674  /* The ring matches, set the context to whatever is for distinctive ring.. */
10675  ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10677  ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10678  break;
10679  }
10680  }
10681  }
10682  /* Restore linear mode (if appropriate) for Caller*ID processing */
10683  dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10684 #if 1
10685  restore_gains(p);
10686 #endif
10687  if (res < 0) {
10688  ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", ast_channel_name(chan));
10689  }
10690  } else
10691  ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10692  }
10693  } else
10694  cs = NULL;
10695 
10696  if (number)
10699 
10700  ao2_cleanup(smdi_msg);
10701 
10702  if (cs)
10703  callerid_free(cs);
10704 
10705  my_handle_notify_message(chan, p, flags, -1);
10706 
10707  ast_channel_lock(chan);
10709  ast_channel_rings_set(chan, 1);
10710  ast_channel_unlock(chan);
10711  p->ringt = p->ringt_base;
10712  res = ast_pbx_run(chan);
10713  if (res) {
10714  ast_hangup(chan);
10715  ast_log(LOG_WARNING, "PBX exited non-zero\n");
10716  }
10717  goto quit;
10718  default:
10719  ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
10720  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10721  if (res < 0)
10722  ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10723  }
10724  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10725  if (res < 0)
10726  ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10727  ast_hangup(chan);
10728 quit:
10730  ss_thread_count--;
10733  return NULL;
10734 }
#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:695
static int restore_gains(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4944
static int unalloc_sub(struct dahdi_pvt *p, int x)
Definition: chan_dahdi.c:4239
static int dahdi_wink(struct dahdi_pvt *p, int index)
Definition: chan_dahdi.c:9449
static int dahdi_wait_event(int fd)
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition: chan_dahdi.c:714
static int canmatch_featurecode(const char *pickupexten, const char *exten)
Definition: chan_dahdi.c:9515
static int distinctiveringaftercid
Definition: chan_dahdi.c:661
static int bump_gains(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4930
#define AST_LAW(p)
Definition: chan_dahdi.c:574
static int dahdi_setlinear(int dfd, int linear)
Definition: chan_dahdi.c:4196
static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
Definition: chan_dahdi.c:3344
static int alloc_sub(struct dahdi_pvt *p, int x)
Definition: chan_dahdi.c:4202
#define NEED_MFDETECT(p)
Signaling types that need to use MF detection should be placed in this macro.
Definition: chan_dahdi.c:578
static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
Definition: chan_dahdi.c:9430
#define SMDI_MD_WAIT_TIMEOUT
Definition: chan_dahdi.c:535
static void swap_subs(struct dahdi_pvt *p, int a, int b)
Definition: chan_dahdi.c:4093
#define ISTRUNK(p)
Definition: chan_dahdi.c:643
#define POLARITY_IDLE
Definition: chan_dahdi.c:845
#define POLARITY_REV
Definition: chan_dahdi.c:846
static int ss_thread_count
Definition: chan_dahdi.c:697
#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
@ AST_FLAG_END_DTMF_ONLY
Definition: channel.h:1007
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
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:1291
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1817
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 LOG_ERROR
#define LOG_NOTICE
#define ast_cond_signal(cond)
Definition: lock.h:201
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:4762
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:4182
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:4197
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:4202
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:406
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 1163 of file chan_dahdi.c.

1164 {
1165  switch (tone) {
1166  case ANALOG_TONE_RINGTONE:
1167  return DAHDI_TONE_RINGTONE;
1168  case ANALOG_TONE_STUTTER:
1169  return DAHDI_TONE_STUTTER;
1171  return DAHDI_TONE_CONGESTION;
1172  case ANALOG_TONE_DIALTONE:
1173  return DAHDI_TONE_DIALTONE;
1175  return DAHDI_TONE_DIALRECALL;
1176  case ANALOG_TONE_INFO:
1177  return DAHDI_TONE_INFO;
1178  default:
1179  return -1;
1180  }
1181 }
@ 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 1183 of file chan_dahdi.c.

1184 {
1185  int index;
1186 
1187  switch (analogsub) {
1188  case ANALOG_SUB_REAL:
1189  index = SUB_REAL;
1190  break;
1191  case ANALOG_SUB_CALLWAIT:
1192  index = SUB_CALLWAIT;
1193  break;
1194  case ANALOG_SUB_THREEWAY:
1195  index = SUB_THREEWAY;
1196  break;
1197  default:
1198  ast_log(LOG_ERROR, "Unidentified sub!\n");
1199  index = SUB_REAL;
1200  }
1201 
1202  return index;
1203 }
@ 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 19962 of file chan_dahdi.c.

◆ attempt_transfer()

static int attempt_transfer ( struct dahdi_pvt p)
static

Definition at line 7168 of file chan_dahdi.c.

7169 {
7170  struct ast_channel *owner_real;
7171  struct ast_channel *owner_3way;
7172  enum ast_transfer_result xfer_res;
7173  int res = 0;
7174 
7175  owner_real = ast_channel_ref(p->subs[SUB_REAL].owner);
7176  owner_3way = ast_channel_ref(p->subs[SUB_THREEWAY].owner);
7177 
7178  ast_verb(3, "TRANSFERRING %s to %s\n",
7179  ast_channel_name(owner_3way), ast_channel_name(owner_real));
7180 
7181  ast_channel_unlock(owner_real);
7182  ast_channel_unlock(owner_3way);
7183  ast_mutex_unlock(&p->lock);
7184 
7185  xfer_res = ast_bridge_transfer_attended(owner_3way, owner_real);
7186  if (xfer_res != AST_BRIDGE_TRANSFER_SUCCESS) {
7187  ast_softhangup(owner_3way, AST_SOFTHANGUP_DEV);
7188  res = -1;
7189  }
7190 
7191  /* Must leave with these locked. */
7192  ast_channel_lock(owner_real);
7193  ast_mutex_lock(&p->lock);
7194 
7195  ast_channel_unref(owner_real);
7196  ast_channel_unref(owner_3way);
7197 
7198  return res;
7199 }
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 13095 of file chan_dahdi.c.

13096 {
13097  struct dahdi_pvt *p = *pvt;
13098 
13099  if (p->inalarm)
13100  return 0;
13101 
13102  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode))
13103  return analog_available(p->sig_pvt);
13104 
13105  switch (p->sig) {
13106 #if defined(HAVE_PRI)
13108  {
13109  struct sig_pri_chan *pvt_chan;
13110  int res;
13111 
13112  pvt_chan = p->sig_pvt;
13113  res = sig_pri_available(&pvt_chan, is_specific_channel);
13114  *pvt = pvt_chan->chan_pvt;
13115  return res;
13116  }
13117 #endif /* defined(HAVE_PRI) */
13118 #if defined(HAVE_SS7)
13119  case SIG_SS7:
13120  return sig_ss7_available(p->sig_pvt);
13121 #endif /* defined(HAVE_SS7) */
13122  default:
13123  break;
13124  }
13125 
13126  if (p->locallyblocked || p->remotelyblocked) {
13127  return 0;
13128  }
13129 
13130  /* If no owner definitely available */
13131  if (!p->owner) {
13132 #ifdef HAVE_OPENR2
13133  /* Trust MFC/R2 */
13134  if (p->mfcr2) {
13135  if (p->mfcr2call) {
13136  return 0;
13137  } else {
13138  return 1;
13139  }
13140  }
13141 #endif
13142  return 1;
13143  }
13144 
13145  return 0;
13146 }
#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 17700 of file chan_dahdi.c.

17701 {
17702  char *c, *chan;
17703  int x, start, finish;
17704  struct dahdi_pvt *tmp;
17705 
17706  if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
17707  ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
17708  return -1;
17709  }
17710 
17711  c = ast_strdupa(value);
17712 
17713  while ((chan = strsep(&c, ","))) {
17714  if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
17715  /* Range */
17716  } else if (sscanf(chan, "%30d", &start)) {
17717  /* Just one */
17718  finish = start;
17719  } else if (!strcasecmp(chan, "pseudo")) {
17720  finish = start = CHAN_PSEUDO;
17721  } else {
17722  ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
17723  return -1;
17724  }
17725  if (finish < start) {
17726  ast_log(LOG_WARNING, "Silliness: %d < %d\n", start, finish);
17727  x = finish;
17728  finish = start;
17729  start = x;
17730  }
17731 
17732  for (x = start; x <= finish; x++) {
17733  if (conf->wanted_channels_start &&
17734  (x < conf->wanted_channels_start ||
17735  x > conf->wanted_channels_end)
17736  ) {
17737  continue;
17738  }
17739  tmp = mkintf(x, conf, reload);
17740 
17741  if (tmp) {
17742  ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
17743  } else {
17744  ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
17745  (reload == 1) ? "reconfigure" : "register", value);
17746  return -1;
17747  }
17748  if (x == CHAN_PSEUDO) {
17749  has_pseudo = 1;
17750  }
17751  }
17752  }
17753 
17754  return 0;
17755 }
static struct dahdi_pvt * mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
Definition: chan_dahdi.c:12126
static int has_pseudo
Definition: chan_dahdi.c:620
static int reload(void)
Definition: chan_dahdi.c:19938
#define CHAN_PSEUDO
Definition: chan_dahdi.c:609
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 4930 of file chan_dahdi.c.

4931 {
4932  int res;
4933 
4934  /* Bump receive gain by value stored in cid_rxgain */
4935  res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
4936  if (res) {
4937  ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
4938  return -1;
4939  }
4940 
4941  return 0;
4942 }
static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
Definition: chan_dahdi.c:4925
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 10742 of file chan_dahdi.c.

10743 {
10744  int x;
10745  int sum = 0;
10746 
10747  if (!len)
10748  return 0;
10749 
10750  for (x = 0; x < len; x++)
10751  sum += abs(law == ast_format_ulaw ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
10752 
10753  return sum / len;
10754 }
#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 9515 of file chan_dahdi.c.

9516 {
9517  int extlen = strlen(exten);
9518 
9519  if (!extlen) {
9520  return 1;
9521  }
9522 
9523  if (extlen < strlen(pickupexten) && !strncmp(pickupexten, exten, extlen)) {
9524  return 1;
9525  }
9526  /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
9527  if (exten[0] == '*' && extlen < 3) {
9528  if (extlen == 1) {
9529  return 1;
9530  }
9531  /* "*0" should be processed before it gets here */
9532  switch (exten[1]) {
9533  case '6':
9534  case '7':
9535  case '8':
9536  return 1;
9537  }
9538  }
9539  return 0;
9540 }

References exten.

Referenced by analog_ss_thread().

◆ check_for_conference()

static int check_for_conference ( struct dahdi_pvt p)
static

Definition at line 7201 of file chan_dahdi.c.

7202 {
7203  struct dahdi_confinfo ci;
7204  /* Fine if we already have a master, etc */
7205  if (p->master || (p->confno > -1))
7206  return 0;
7207  memset(&ci, 0, sizeof(ci));
7208  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
7209  ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
7210  return 0;
7211  }
7212  /* If we have no master and don't have a confno, then
7213  if we're in a conference, it's probably a MeetMe room or
7214  some such, so don't let us 3-way out! */
7215  if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
7216  ast_verb(3, "Avoiding 3-way call when in an external conference\n");
7217  return 1;
7218  }
7219  return 0;
7220 }
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 4492 of file chan_dahdi.c.

4493 {
4494  /* If the conference already exists, and we're already in it
4495  don't bother doing anything */
4496  struct dahdi_confinfo zi;
4497 
4498  memset(&zi, 0, sizeof(zi));
4499  zi.chan = 0;
4500 
4501  if (slavechannel > 0) {
4502  /* If we have only one slave, do a digital mon */
4503  zi.confmode = DAHDI_CONF_DIGITALMON;
4504  zi.confno = slavechannel;
4505  } else {
4506  if (!idx) {
4507  /* Real-side and pseudo-side both participate in conference */
4508  zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
4509  DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
4510  } else
4511  zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
4512  zi.confno = p->confno;
4513  }
4514  if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
4515  return 0;
4516  if (c->dfd < 0)
4517  return 0;
4518  if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4519  ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
4520  return -1;
4521  }
4522  if (slavechannel < 1) {
4523  p->confno = zi.confno;
4524  }
4525  c->curconf = zi;
4526  ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4527  return 0;
4528 }

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

4542 {
4543  struct dahdi_confinfo zi;
4544  if (/* Can't delete if there's no dfd */
4545  (c->dfd < 0) ||
4546  /* Don't delete from the conference if it's not our conference */
4547  !isourconf(p, c)
4548  /* Don't delete if we don't think it's conferenced at all (implied) */
4549  ) return 0;
4550  memset(&zi, 0, sizeof(zi));
4551  if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4552  ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
4553  return -1;
4554  }
4555  ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4556  memcpy(&c->curconf, &zi, sizeof(c->curconf));
4557  return 0;
4558 }
static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
Definition: chan_dahdi.c:4530

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

9131 {
9132  struct ast_str *chan_name;
9133  int x, y;
9134 
9135  /* Create the new channel name tail. */
9136  if (!(chan_name = ast_str_create(32))) {
9137  return NULL;
9138  }
9139  if (i->channel == CHAN_PSEUDO) {
9140  ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
9141 #if defined(HAVE_PRI)
9142  } else if (i->pri) {
9143  ast_mutex_lock(&i->pri->lock);
9144  y = ++i->pri->new_chan_seq;
9145  if (is_outgoing) {
9146  ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, (unsigned)y);
9147  address[0] = '\0';
9148  } else if (ast_strlen_zero(i->cid_subaddr)) {
9149  /* Put in caller-id number only since there is no subaddress. */
9150  ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, (unsigned)y);
9151  } else {
9152  /* Put in caller-id number and subaddress. */
9153  ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
9154  i->cid_subaddr, (unsigned)y);
9155  }
9156  ast_mutex_unlock(&i->pri->lock);
9157 #endif /* defined(HAVE_PRI) */
9158  } else {
9159  y = 1;
9160  do {
9161  ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
9162  for (x = 0; x < 3; ++x) {
9163  if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
9164  ast_channel_name(i->subs[x].owner) + 6)) {
9165  break;
9166  }
9167  }
9168  ++y;
9169  } while (x < 3);
9170  }
9171  return chan_name;
9172 }
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:739
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:640
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:1091
Support for dynamic strings.
Definition: strings.h:604
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 1856 of file chan_dahdi.c.

1857 {
1858  char ch_name[23];
1859 
1860  if (p->channel < CHAN_PSEUDO) {
1861  /* No B channel */
1862  snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
1863  } else if (p->channel == CHAN_PSEUDO) {
1864  /* Pseudo channel */
1865  strcpy(ch_name, "pseudo");
1866  } else {
1867  /* Real channel */
1868  snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
1869  }
1870  publish_dahdichannel(chan, p->group, p->span, ch_name);
1871 }
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:1829
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 6432 of file chan_dahdi.c.

6433 {
6434  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
6435  int res = 0;
6436  int idx;
6437  ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
6438  ast_mutex_lock(&p->lock);
6439  idx = dahdi_get_index(ast, p, 0);
6440  if (idx < 0)
6441  idx = SUB_REAL;
6442  /* nothing to do if a radio channel */
6443  if ((p->radio || (p->oprmode < 0))) {
6444  ast_mutex_unlock(&p->lock);
6445  return 0;
6446  }
6447 
6448  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
6449  res = analog_answer(p->sig_pvt, ast);
6450  ast_mutex_unlock(&p->lock);
6451  return res;
6452  }
6453 
6454  switch (p->sig) {
6455 #if defined(HAVE_PRI)
6457  res = sig_pri_answer(p->sig_pvt, ast);
6458  break;
6459 #endif /* defined(HAVE_PRI) */
6460 #if defined(HAVE_SS7)
6461  case SIG_SS7:
6462  res = sig_ss7_answer(p->sig_pvt, ast);
6463  break;
6464 #endif /* defined(HAVE_SS7) */
6465 #ifdef HAVE_OPENR2
6466  case SIG_MFCR2:
6467  if (!p->mfcr2_call_accepted) {
6468  /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
6469  openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
6470  p->mfcr2_answer_pending = 1;
6471  if (p->mfcr2_charge_calls) {
6472  ast_debug(1, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
6473  openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
6474  } else {
6475  ast_debug(1, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
6476  openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
6477  }
6478  } else {
6479  ast_debug(1, "Answering MFC/R2 call on chan %d\n", p->channel);
6480  dahdi_r2_answer(p);
6481  }
6482  break;
6483 #endif
6484  case 0:
6485  ast_mutex_unlock(&p->lock);
6486  return 0;
6487  default:
6488  ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
6489  res = -1;
6490  break;
6491  }
6492  ast_mutex_unlock(&p->lock);
6493  return res;
6494 }
#define SIG_MFCR2
Definition: chan_dahdi.h:769
int analog_answer(struct analog_pvt *p, struct ast_channel *ast)
Definition: sig_analog.c:1463
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 5156 of file chan_dahdi.c.

5157 {
5158  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5159  int x, res, mysig;
5160  char *dest;
5162  AST_APP_ARG(group); /* channel/group token */
5163  AST_APP_ARG(ext); /* extension token */
5164  //AST_APP_ARG(opts); /* options token */
5165  AST_APP_ARG(other); /* Any remining unused arguments */
5166  );
5167 
5168  ast_mutex_lock(&p->lock);
5169  ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
5170 
5171  /* Split the dialstring */
5172  dest = ast_strdupa(rdest);
5173  AST_NONSTANDARD_APP_ARGS(args, dest, '/');
5174  if (!args.ext) {
5175  args.ext = "";
5176  }
5177 
5178 #if defined(HAVE_PRI)
5179  if (dahdi_sig_pri_lib_handles(p->sig)) {
5180  char *subaddr;
5181 
5182  sig_pri_extract_called_num_subaddr(p->sig_pvt, rdest, p->exten, sizeof(p->exten));
5183 
5184  /* Remove any subaddress for uniformity with incoming calls. */
5185  subaddr = strchr(p->exten, ':');
5186  if (subaddr) {
5187  *subaddr = '\0';
5188  }
5189  } else
5190 #endif /* defined(HAVE_PRI) */
5191  {
5192  ast_copy_string(p->exten, args.ext, sizeof(p->exten));
5193  }
5194 
5195  if ((ast_channel_state(ast) == AST_STATE_BUSY)) {
5196  p->subs[SUB_REAL].needbusy = 1;
5197  ast_mutex_unlock(&p->lock);
5198  return 0;
5199  }
5201  ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
5202  ast_mutex_unlock(&p->lock);
5203  return -1;
5204  }
5205  p->waitingfordt.tv_sec = 0;
5206  p->dialednone = 0;
5207  if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */
5208  {
5209  /* Special pseudo -- automatically up */
5210  ast_setstate(ast, AST_STATE_UP);
5211  ast_mutex_unlock(&p->lock);
5212  return 0;
5213  }
5214  x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
5215  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
5216  if (res)
5217  ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
5218  p->outgoing = 1;
5219 
5221  set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
5222  } else {
5223  set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5224  }
5225 
5226 #ifdef HAVE_PRI
5227  if (dahdi_sig_pri_lib_handles(p->sig)) {
5228  res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
5229  (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
5230  ast_mutex_unlock(&p->lock);
5231  return res;
5232  }
5233 #endif
5234 
5235 #if defined(HAVE_SS7)
5236  if (p->sig == SIG_SS7) {
5237  res = sig_ss7_call(p->sig_pvt, ast, rdest);
5238  ast_mutex_unlock(&p->lock);
5239  return res;
5240  }
5241 #endif /* defined(HAVE_SS7) */
5242 
5243  /* If this is analog signalling we can exit here */
5244  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
5245  p->callwaitrings = 0;
5246  res = analog_call(p->sig_pvt, ast, rdest, timeout);
5247  ast_mutex_unlock(&p->lock);
5248  return res;
5249  }
5250 
5251  mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
5252  switch (mysig) {
5253  case 0:
5254  /* Special pseudo -- automatically up*/
5255  ast_setstate(ast, AST_STATE_UP);
5256  break;
5257  case SIG_MFCR2:
5258  break;
5259  default:
5260  ast_debug(1, "not yet implemented\n");
5261  ast_mutex_unlock(&p->lock);
5262  return -1;
5263  }
5264 
5265 #ifdef HAVE_OPENR2
5266  if (p->mfcr2) {
5267  openr2_calling_party_category_t chancat;
5268  int callres = 0;
5269  char *c, *l;
5270 
5271  /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
5272  p->dialdest[0] = '\0';
5273 
5274  c = args.ext;
5275  if (!p->hidecallerid) {
5277  } else {
5278  l = NULL;
5279  }
5280  if (strlen(c) < p->stripmsd) {
5281  ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
5282  ast_mutex_unlock(&p->lock);
5283  return -1;
5284  }
5285  p->dialing = 1;
5286  chancat = dahdi_r2_get_channel_category(ast);
5287  callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
5288  if (-1 == callres) {
5289  ast_mutex_unlock(&p->lock);
5290  ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
5291  return -1;
5292  }
5293  p->mfcr2_call_accepted = 0;
5294  p->mfcr2_progress_sent = 0;
5296  }
5297 #endif /* HAVE_OPENR2 */
5298  ast_mutex_unlock(&p->lock);
5299  return 0;
5300 }
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 5122 of file chan_dahdi.c.

5123 {
5124  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5125 
5127  if (p->cidspill) {
5128  ast_log(LOG_WARNING, "Spill already exists?!?\n");
5129  ast_free(p->cidspill);
5130  }
5131 
5132  /*
5133  * SAS: Subscriber Alert Signal, 440Hz for 300ms
5134  * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
5135  */
5136  if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
5137  return -1;
5138  save_conference(p);
5139  /* Silence */
5140  memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
5141  if (!p->callwaitrings && p->callwaitingcallerid) {
5142  ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
5143  p->callwaitcas = 1;
5144  p->cidlen = 2400 + 680 + READ_SIZE * 4;
5145  } else {
5146  ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
5147  p->callwaitcas = 0;
5148  p->cidlen = 2400 + READ_SIZE * 4;
5149  }
5150  p->cidpos = 0;
5151  send_callerid(p);
5152 
5153  return 0;
5154 }
#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:732
static int save_conference(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5011
#define READ_SIZE
Definition: chan_dahdi.c:726
static int send_callerid(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5086
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 13764 of file chan_dahdi.c.

13765 {
13766  struct dahdi_pvt *p;
13767  struct dahdi_pvt *exitpvt;
13768  struct dahdi_starting_point start;
13769  int groupmatched = 0;
13770  int channelmatched = 0;
13771 
13773  p = determine_starting_point(dest, &start);
13774  if (!p) {
13776  return -1;
13777  }
13778  exitpvt = p;
13779  for (;;) {
13780  if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13781  /* We found a potential match. call the callback */
13782  struct ast_str *device_name;
13783  char *dash;
13784  const char *monitor_type;
13785  char dialstring[AST_CHANNEL_NAME];
13786  char full_device_name[AST_CHANNEL_NAME];
13787 
13788  switch (ast_get_cc_monitor_policy(p->cc_params)) {
13789  case AST_CC_MONITOR_NEVER:
13790  break;
13791  case AST_CC_MONITOR_NATIVE:
13792  case AST_CC_MONITOR_ALWAYS:
13794 #if defined(HAVE_PRI)
13795  if (dahdi_sig_pri_lib_handles(p->sig)) {
13796  /*
13797  * ISDN is in a trunk busy condition so we need to monitor
13798  * the span congestion device state.
13799  */
13800  snprintf(full_device_name, sizeof(full_device_name),
13801  "DAHDI/I%d/congestion", p->pri->span);
13802  } else
13803 #endif /* defined(HAVE_PRI) */
13804  {
13805 #if defined(HAVE_PRI)
13806  device_name = create_channel_name(p, 1, "");
13807 #else
13808  device_name = create_channel_name(p);
13809 #endif /* defined(HAVE_PRI) */
13810  snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13811  device_name ? ast_str_buffer(device_name) : "");
13812  ast_free(device_name);
13813  /*
13814  * The portion after the '-' in the channel name is either a random
13815  * number, a sequence number, or a subchannel number. None are
13816  * necessary so strip them off.
13817  */
13818  dash = strrchr(full_device_name, '-');
13819  if (dash) {
13820  *dash = '\0';
13821  }
13822  }
13823  snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13824 
13825  /*
13826  * Analog can only do generic monitoring.
13827  * ISDN is in a trunk busy condition and any "device" is going
13828  * to be busy until a B channel becomes available. The generic
13829  * monitor can do this task.
13830  */
13831  monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13832  callback(inbound,
13833 #if defined(HAVE_PRI)
13834  p->pri ? p->pri->cc_params : p->cc_params,
13835 #else
13836  p->cc_params,
13837 #endif /* defined(HAVE_PRI) */
13838  monitor_type, full_device_name, dialstring, NULL);
13839  break;
13840  }
13841  }
13842  p = start.backwards ? p->prev : p->next;
13843  if (!p) {
13844  p = start.backwards ? ifend : iflist;
13845  }
13846  if (p == exitpvt) {
13847  break;
13848  }
13849  }
13851  return 0;
13852 }
#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:9129
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:13062
static struct dahdi_pvt * ifend
Definition: chan_dahdi.c:855
static struct dahdi_pvt * determine_starting_point(const char *data, struct dahdi_starting_point *param)
Definition: chan_dahdi.c:13365
#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: cha