Asterisk - The Open Source Telephony Project  GIT-master-1f78ee9
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"

Go to the source code of this file.

Data Structures

struct  dahdi_chan_conf
 Channel configuration from chan_dahdi.conf . This struct is used for parsing the [channels] section of chan_dahdi.conf. Generally there is a field here for every possible configuration item. More...
 
struct  dahdi_starting_point
 
struct  mwi_thread_data
 

Macros

#define ASCII_BYTES_PER_CHAR   80
 
#define AST_LAW(p)   (((p)->law == DAHDI_LAW_ALAW) ? ast_format_alaw : ast_format_ulaw)
 
#define CALLPROGRESS_FAX   (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
 
#define CALLPROGRESS_FAX_INCOMING   4
 
#define CALLPROGRESS_FAX_OUTGOING   2
 
#define CALLPROGRESS_PROGRESS   1
 
#define CALLWAITING_REPEAT_SAMPLES   ((10000 * 8) / READ_SIZE)
 
#define CALLWAITING_SILENT_SAMPLES   ((300 * 8) / READ_SIZE)
 
#define CALLWAITING_SUPPRESS_SAMPLES   ((100 * 8) / READ_SIZE)
 
#define CANBUSYDETECT(p)   (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
 
#define CANPROGRESSDETECT(p)   (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
 
#define CHAN_PSEUDO   -2
 
#define CIDCW_EXPIRE_SAMPLES   ((500 * 8) / READ_SIZE)
 
#define DEFAULT_CIDRINGS   1
 Typically, how many rings before we should send Caller*ID. More...
 
#define DEFAULT_DIALTONE_DETECT_TIMEOUT   ((10000 * 8) / READ_SIZE)
 
#define DEFAULT_RINGT   ((8000 * 8) / READ_SIZE)
 
#define END_SILENCE_LEN   400
 
#define FORMAT   "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
 
#define FORMAT   "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
 
#define FORMAT2   "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
 
#define FORMAT2   "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
 
#define gen_pvt_field_callback(type, field)
 
#define GET_CHANNEL(p)   ((p)->channel)
 
#define HANGUP   1
 
#define HEADER_LEN   ((HEADER_MS + TRAILER_MS) * 8)
 
#define HEADER_MS   50
 
#define ISTRUNK(p)
 
#define MASK_AVAIL   (1 << 0)
 
#define MASK_INUSE   (1 << 1)
 
#define MAX_CHANLIST_LEN   80
 
#define MIN_MS_SINCE_FLASH   ((2000) )
 
#define NEED_MFDETECT(p)   (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
 Signaling types that need to use MF detection should be placed in this macro. More...
 
#define NUM_CADENCE_MAX   25
 
#define NUM_SPANS   32
 
#define POLARITY_IDLE   0
 
#define POLARITY_REV   1
 
#define PROC_DAHDI_OPT_NOCHAN   (1 << 0)
 
#define PROC_DAHDI_OPT_NOWARN   (1 << 1)
 
#define READ_SIZE   160
 
#define REPORT_CHANNEL_ALARMS   1
 
#define REPORT_SPAN_ALARMS   2
 
#define sig2str   dahdi_sig2str
 
#define SMDI_MD_WAIT_TIMEOUT   1500 /* 1.5 seconds */
 
#define TRAILER_MS   5
 
#define TRANSFER   0
 

Functions

static struct ast_frame__dahdi_exception (struct ast_channel *ast)
 
static void __reg_module (void)
 
static int __unload_module (void)
 
static void __unreg_module (void)
 
int _dahdi_get_index (struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
 
static int action_dahdidialoffhook (struct mansession *s, const struct message *m)
 
static int action_dahdidndoff (struct mansession *s, const struct message *m)
 
static int action_dahdidndon (struct mansession *s, const struct message *m)
 
static int action_dahdirestart (struct mansession *s, const struct message *m)
 
static int action_dahdishowchannels (struct mansession *s, const struct message *m)
 
static int action_transfer (struct mansession *s, const struct message *m)
 
static int action_transferhangup (struct mansession *s, const struct message *m)
 
static char * alarm2str (int alm)
 
static int alloc_sub (struct dahdi_pvt *p, int x)
 
static void * analog_ss_thread (void *data)
 
static int analog_tone_to_dahditone (enum analog_tone tone)
 
static int analogsub_to_dahdisub (enum analog_sub analogsub)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int attempt_transfer (struct dahdi_pvt *p)
 
static int available (struct dahdi_pvt **pvt, int is_specific_channel)
 
static int build_channels (struct dahdi_chan_conf *conf, const char *value, int reload, int lineno)
 
static int bump_gains (struct dahdi_pvt *p)
 
static int calc_energy (const unsigned char *buf, int len, struct ast_format *law)
 
static int canmatch_featurecode (const char *pickupexten, const char *exten)
 
static int check_for_conference (struct dahdi_pvt *p)
 
static int conf_add (struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
 
static int conf_del (struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
 
static struct ast_strcreate_channel_name (struct dahdi_pvt *i)
 
static void dahdi_ami_channel_event (struct dahdi_pvt *p, struct ast_channel *chan)
 
static int dahdi_answer (struct ast_channel *ast)
 
static int dahdi_call (struct ast_channel *ast, const char *rdest, int timeout)
 
static int dahdi_callwait (struct ast_channel *ast)
 
static int dahdi_cc_callback (struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
 Callback made when dial failed to get a channel out of dahdi_request(). More...
 
static struct dahdi_chan_conf dahdi_chan_conf_default (void)
 
static void dahdi_close (int fd)
 
static void dahdi_close_sub (struct dahdi_pvt *chan_pvt, int sub_num)
 
void dahdi_conf_update (struct dahdi_pvt *p)
 
static int dahdi_confmute (struct dahdi_pvt *p, int muted)
 
static int dahdi_create_channel_range (int start, int end)
 
static char * dahdi_create_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static void dahdi_destroy_channel_range (int start, int end)
 
static char * dahdi_destroy_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int dahdi_devicestate (const char *data)
 
static int dahdi_dial_str (struct dahdi_pvt *pvt, int operation, const char *dial_str)
 
static int dahdi_digit_begin (struct ast_channel *ast, char digit)
 
static int dahdi_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
 
static int dahdi_dnd (struct dahdi_pvt *dahdichan, int flag)
 enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel More...
 
void dahdi_dtmf_detect_disable (struct dahdi_pvt *p)
 
void dahdi_dtmf_detect_enable (struct dahdi_pvt *p)
 
void dahdi_ec_disable (struct dahdi_pvt *p)
 
void dahdi_ec_enable (struct dahdi_pvt *p)
 
static struct ast_framedahdi_exception (struct ast_channel *ast)
 
static int dahdi_fake_event (struct dahdi_pvt *p, int mode)
 
static int dahdi_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
 
static int dahdi_func_read (struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
 
static int dahdi_func_write (struct ast_channel *chan, const char *function, char *data, const char *value)
 
static int dahdi_get_event (int fd)
 Avoid the silly dahdi_getevent which ignores a bunch of events. More...
 
static void dahdi_handle_dtmf (struct ast_channel *ast, int idx, struct ast_frame **dest)
 
static struct ast_framedahdi_handle_event (struct ast_channel *ast)
 
static int dahdi_hangup (struct ast_channel *ast)
 
static void dahdi_iflist_extract (struct dahdi_pvt *pvt)
 
static void dahdi_iflist_insert (struct dahdi_pvt *pvt)
 
static int dahdi_indicate (struct ast_channel *chan, int condition, const void *data, size_t datalen)
 
static void dahdi_lock_sub_owner (struct dahdi_pvt *pvt, int sub_idx)
 
void dahdi_master_slave_link (struct dahdi_pvt *slave, struct dahdi_pvt *master)
 
void dahdi_master_slave_unlink (struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
 
static struct ast_channeldahdi_new (struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid)
 
static struct ast_channeldahdi_new_callid_clean (struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid, int callid_created)
 
static int dahdi_open (char *fn)
 
static int dahdi_queryoption (struct ast_channel *chan, int option, void *data, int *datalen)
 
static void dahdi_queue_frame (struct dahdi_pvt *p, struct ast_frame *f)
 
static struct ast_framedahdi_read (struct ast_channel *ast)
 
static struct ast_channeldahdi_request (const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
 
static int dahdi_restart (void)
 
static char * dahdi_restart_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int dahdi_ring_phone (struct dahdi_pvt *p)
 
static int dahdi_sendtext (struct ast_channel *c, const char *text)
 
static char * dahdi_set_dnd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int dahdi_set_hook (int fd, int hs)
 
static char * dahdi_set_hwgain (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * dahdi_set_swgain (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int dahdi_setlinear (int dfd, int linear)
 
static int dahdi_setoption (struct ast_channel *chan, int option, void *data, int datalen)
 
static char * dahdi_show_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * dahdi_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * dahdi_show_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * dahdi_show_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * dahdi_sig2str (int sig)
 
static void dahdi_softhangup_all (void)
 
static void dahdi_train_ec (struct dahdi_pvt *p)
 
static int dahdi_wait_event (int fd)
 Avoid the silly dahdi_waitevent which ignores a bunch of events. More...
 
static int dahdi_wink (struct dahdi_pvt *p, int index)
 
static int dahdi_write (struct ast_channel *ast, struct ast_frame *frame)
 
static struct ast_manager_event_blobdahdichannel_to_ami (struct stasis_message *msg)
 
static enum analog_event dahdievent_to_analogevent (int event)
 
static enum analog_sigtype dahdisig_to_analogsig (int sig)
 
static void deep_copy_dahdi_chan_conf (struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
 
static void destroy_all_channels (void)
 
static void destroy_channel (struct dahdi_pvt *cur, int now)
 
static void destroy_dahdi_pvt (struct dahdi_pvt *pvt)
 
static struct dahdi_pvtdetermine_starting_point (const char *data, struct dahdi_starting_point *param)
 
static int digit_to_dtmfindex (char digit)
 
static void * do_monitor (void *data)
 
static int drc_sample (int sample, float drc)
 
static struct dahdi_pvtduplicate_pseudo (struct dahdi_pvt *src)
 
static const char * event2str (int event)
 
static void fill_rxgain (struct dahdi_gains *g, float gain, float drc, int law)
 
static void fill_txgain (struct dahdi_gains *g, float gain, float drc, int law)
 
static struct dahdi_pvtfind_channel (int channel)
 
static struct dahdi_pvtfind_channel_from_str (const char *channel)
 
static struct dahdi_pvtfind_next_iface_in_span (struct dahdi_pvt *cur)
 
 gen_pvt_field_callback (int, firstdigit_timeout)
 
 gen_pvt_field_callback (int, interdigit_timeout)
 
 gen_pvt_field_callback (int, matchdigit_timeout)
 
static int get_alarms (struct dahdi_pvt *p)
 
static void handle_alarms (struct dahdi_pvt *p, int alms)
 
static void handle_clear_alarms (struct dahdi_pvt *p)
 
static char * handle_dahdi_show_cadences (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static struct dahdi_pvthandle_init_event (struct dahdi_pvt *i, int event)
 
static int has_voicemail (struct dahdi_pvt *p)
 
static int is_group_or_channel_match (struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
 
static int isourconf (struct dahdi_pvt *p, struct dahdi_subchannel *c)
 
static int isslavenative (struct dahdi_pvt *p, struct dahdi_pvt **out)
 
static int load_module (void)
 Load the module. More...
 
static struct dahdi_pvtmkintf (int channel, const struct dahdi_chan_conf *conf, int reloading)
 
static void monitor_pfds_clean (void *arg)
 
static int mwi_send_init (struct dahdi_pvt *pvt)
 
static int mwi_send_process_buffer (struct dahdi_pvt *pvt, int num_read)
 
static int mwi_send_process_event (struct dahdi_pvt *pvt, int event)
 
static void * mwi_thread (void *data)
 
static void my_all_subchannels_hungup (void *pvt)
 
static int my_allocate_sub (void *pvt, enum analog_sub analogsub)
 
static void my_answer_polarityswitch (void *pvt)
 
static int my_callwait (void *pvt)
 
static void my_cancel_cidspill (void *pvt)
 
static int my_check_confirmanswer (void *pvt)
 
static int my_check_for_conference (void *pvt)
 
static int my_check_waitingfordt (void *pvt)
 
static int my_complete_conference_update (void *pvt, int needconference)
 
static int my_conf_add (void *pvt, enum analog_sub sub)
 
static int my_conf_del (void *pvt, enum analog_sub sub)
 
static int my_confmute (void *pvt, int mute)
 
static int my_dahdi_write (struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
 
static void my_deadlock_avoidance_private (void *pvt)
 
static void my_decrease_ss_count (void)
 
static int my_dial_digits (void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
 
static int my_distinctive_ring (struct ast_channel *chan, void *pvt, int idx, int *ringdata)
 
static int my_dsp_reset_and_flush_digits (void *pvt)
 
static int my_dsp_set_digitmode (void *pvt, enum analog_dsp_digitmode mode)
 
static int my_flash (void *pvt)
 
static void my_get_and_handle_alarms (void *pvt)
 
static int my_get_callerid (void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
 
static int my_get_event (void *pvt)
 
static const char * my_get_orig_dialstring (void *pvt)
 
static void * my_get_sigpvt_bridged_channel (struct ast_channel *chan)
 
static int my_get_sub_fd (void *pvt, enum analog_sub sub)
 
static int my_getsigstr (struct ast_channel *chan, char *str, const char *term, int ms)
 
static void my_handle_dtmf (void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
 
static void my_handle_notify_message (struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
 
static void my_hangup_polarityswitch (void *pvt)
 
static int my_has_voicemail (void *pvt)
 
static int my_have_progressdetect (void *pvt)
 
static void my_increase_ss_count (void)
 
static int my_is_dialing (void *pvt, enum analog_sub sub)
 
static int my_is_off_hook (void *pvt)
 
static void my_lock_private (void *pvt)
 
static struct ast_channelmy_new_analog_ast_channel (void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
 
static int my_off_hook (void *pvt)
 
static int my_on_hook (void *pvt)
 
static int my_play_tone (void *pvt, enum analog_sub sub, enum analog_tone tone)
 
static int my_ring (void *pvt)
 
static int my_send_callerid (void *pvt, int cwcid, struct ast_party_caller *caller)
 
static void my_set_alarm (void *pvt, int in_alarm)
 
static void my_set_cadence (void *pvt, int *cid_rings, struct ast_channel *ast)
 
static void my_set_callwaiting (void *pvt, int callwaiting_enable)
 
static void my_set_confirmanswer (void *pvt, int flag)
 
static void my_set_dialing (void *pvt, int is_dialing)
 
static int my_set_echocanceller (void *pvt, int enable)
 
static void my_set_inthreeway (void *pvt, enum analog_sub sub, int inthreeway)
 
static int my_set_linear_mode (void *pvt, enum analog_sub sub, int linear_mode)
 
static void my_set_needringing (void *pvt, int value)
 
static void my_set_new_owner (void *pvt, struct ast_channel *new_owner)
 
static void my_set_outgoing (void *pvt, int is_outgoing)
 
static void my_set_polarity (void *pvt, int value)
 
static void my_set_pulsedial (void *pvt, int flag)
 
static void my_set_ringtimeout (void *pvt, int ringt)
 
static void my_set_waitingfordt (void *pvt, struct ast_channel *ast)
 
static int my_start (void *pvt)
 
static int my_start_cid_detect (void *pvt, int cid_signalling)
 
static void my_start_polarityswitch (void *pvt)
 
static int my_stop_callwait (void *pvt)
 
static int my_stop_cid_detect (void *pvt)
 
static void my_swap_subchannels (void *pvt, enum analog_sub a, struct ast_channel *ast_a, enum analog_sub b, struct ast_channel *ast_b)
 
static int my_train_echocanceller (void *pvt)
 
static int my_unallocate_sub (void *pvt, enum analog_sub analogsub)
 
static void my_unlock_private (void *pvt)
 
static int my_wait_event (void *pvt)
 
static int my_wink (void *pvt, enum analog_sub sub)
 
static void notify_message (char *mailbox, int thereornot)
 Send MWI state change. More...
 
static int parse_buffers_policy (const char *parse, int *num_buffers, int *policy)
 
static void parse_busy_pattern (struct ast_variable *v, struct ast_dsp_busy_pattern *busy_cadence)
 
static int process_dahdi (struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
 
static void process_echocancel (struct dahdi_chan_conf *confp, const char *data, unsigned int line)
 
static void publish_channel_alarm (int channel, const char *alarm_txt)
 
static void publish_channel_alarm_clear (int channel)
 
static void publish_dahdichannel (struct ast_channel *chan, ast_group_t group, int span, const char *dahdi_channel)
 Sends a DAHDIChannel channel blob used to produce DAHDIChannel AMI messages. More...
 
static void publish_dnd_state (int channel, const char *status)
 
static void publish_span_alarm (int span, const char *alarm_txt)
 
static void publish_span_alarm_clear (int span)
 
static void release_doomed_pris (void)
 
static int reload (void)
 
static int reset_conf (struct dahdi_pvt *p)
 
static int restart_monitor (void)
 
static int restore_conference (struct dahdi_pvt *p)
 
static int restore_gains (struct dahdi_pvt *p)
 
static int revert_fax_buffers (struct dahdi_pvt *p, struct ast_channel *ast)
 
static int save_conference (struct dahdi_pvt *p)
 
static int send_callerid (struct dahdi_pvt *p)
 
static int send_cwcidspill (struct dahdi_pvt *p)
 
static int set_actual_gain (int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
 
static int set_actual_rxgain (int fd, float gain, float drc, int law)
 
static int set_actual_txgain (int fd, float gain, float drc, int law)
 
static int set_hwgain (int fd, float gain, int tx_direction)
 
static int setup_dahdi (int reload)
 
static int setup_dahdi_int (int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
 
static int sigtype_to_signalling (int sigtype)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (dahdichannel_type,.to_ami=dahdichannel_to_ami,)
 
static void swap_subs (struct dahdi_pvt *p, int a, int b)
 
static int unalloc_sub (struct dahdi_pvt *p, int x)
 
static int unload_module (void)
 
static void wakeup_sub (struct dahdi_pvt *p, int a)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = tdesc , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .requires = "ccss", .optional_modules = "res_smdi", }
 
struct {
   int   alarm
 
   char *   name
 
alarms []
 
struct analog_callback analog_callbacks
 
static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}}
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct dahdi_ring_cadence cadences [NUM_CADENCE_MAX]
 
static int cidrings [NUM_CADENCE_MAX]
 cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on. More...
 
static const char config [] = "chan_dahdi.conf"
 
static struct ast_cli_entry dahdi_cli []
 
static struct ast_channel_tech dahdi_tech
 
static struct ast_jb_conf default_jbconf
 
static char defaultcic [64] = ""
 
static char defaultozz [64] = ""
 
static int distinctiveringaftercid = 0
 
static int dtmfcid_level = 256
 
static const char *const events []
 
static struct ast_jb_conf global_jbconf
 
static int has_pseudo
 
static int ifcount = 0
 
static struct dahdi_pvtifend = NULL
 
static struct dahdi_pvtiflist = NULL
 
static ast_mutex_t iflock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 Protect the interface list (of dahdi_pvt's) More...
 
static const char *const lbostr []
 
static pthread_t monitor_thread = AST_PTHREADT_NULL
 This is the thread for the monitor which checks for input on the channels which are not currently in use. More...
 
static ast_mutex_t monlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical. More...
 
static int mwilevel = 512
 
static char mwimonitornotify [PATH_MAX] = ""
 
static int mwisend_rpas = 0
 
static int num_cadence = 4
 
static int num_restart_pending = 0
 
static int numbufs = 4
 
static char progzone [10] = ""
 
static int report_alarms = REPORT_CHANNEL_ALARMS
 
static ast_mutex_t restart_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static int ringt_base = DEFAULT_RINGT
 Configured ring timeout base. More...
 
static struct dahdi_pvtround_robin [32]
 
static ast_cond_t ss_thread_complete
 
static int ss_thread_count = 0
 
static ast_mutex_t ss_thread_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
const char *const subnames []
 
static const char tdesc [] = "DAHDI Telephony"
 
static int usedistinctiveringdetection = 0
 
static int user_has_defined_cadences = 0
 

Detailed Description

DAHDI for Pseudo TDM.

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

Connects to the DAHDI telephony library as well as libpri. Libpri is optional and needed only if you are going to use ISDN connections.

You need to install libraries before you attempt to compile and install the DAHDI channel.

Todo:
Deprecate the "musiconhold" configuration option post 1.4

Definition in file chan_dahdi.c.

Macro Definition Documentation

◆ ASCII_BYTES_PER_CHAR

#define ASCII_BYTES_PER_CHAR   80

Referenced by dahdi_sendtext().

◆ AST_LAW

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

◆ CALLPROGRESS_FAX

#define CALLPROGRESS_FAX   (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)

Definition at line 561 of file chan_dahdi.c.

Referenced by dahdi_handle_dtmf(), my_handle_dtmf(), and process_dahdi().

◆ CALLPROGRESS_FAX_INCOMING

#define CALLPROGRESS_FAX_INCOMING   4

Definition at line 560 of file chan_dahdi.c.

Referenced by dahdi_new(), and process_dahdi().

◆ CALLPROGRESS_FAX_OUTGOING

#define CALLPROGRESS_FAX_OUTGOING   2

Definition at line 559 of file chan_dahdi.c.

Referenced by dahdi_new(), and process_dahdi().

◆ CALLPROGRESS_PROGRESS

#define CALLPROGRESS_PROGRESS   1

Definition at line 558 of file chan_dahdi.c.

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

◆ CALLWAITING_REPEAT_SAMPLES

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

10,000 ms

Definition at line 679 of file chan_dahdi.c.

Referenced by dahdi_callwait(), and my_callwait().

◆ CALLWAITING_SILENT_SAMPLES

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

300 ms

Definition at line 678 of file chan_dahdi.c.

◆ CALLWAITING_SUPPRESS_SAMPLES

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

100 ms

Definition at line 680 of file chan_dahdi.c.

Referenced by send_callerid().

◆ CANBUSYDETECT

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

Definition at line 593 of file chan_dahdi.c.

Referenced by dahdi_new().

◆ CANPROGRESSDETECT

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

◆ CHAN_PSEUDO

#define CHAN_PSEUDO   -2

◆ CIDCW_EXPIRE_SAMPLES

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

500 ms

Definition at line 681 of file chan_dahdi.c.

Referenced by send_callerid().

◆ DEFAULT_CIDRINGS

#define DEFAULT_CIDRINGS   1

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

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

Definition at line 519 of file chan_dahdi.c.

Referenced by dahdi_chan_conf_default().

◆ DEFAULT_DIALTONE_DETECT_TIMEOUT

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

10,000 ms

Definition at line 684 of file chan_dahdi.c.

Referenced by process_dahdi().

◆ DEFAULT_RINGT

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

8,000 ms

Definition at line 683 of file chan_dahdi.c.

◆ END_SILENCE_LEN

#define END_SILENCE_LEN   400

Referenced by dahdi_sendtext().

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

◆ GET_CHANNEL

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

Definition at line 1053 of file chan_dahdi.c.

Referenced by dahdi_conf_update(), and my_complete_conference_update().

◆ HANGUP

#define HANGUP   1

Definition at line 16235 of file chan_dahdi.c.

Referenced by action_transferhangup(), and dahdi_fake_event().

◆ HEADER_LEN

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

◆ HEADER_MS

#define HEADER_MS   50

Referenced by dahdi_sendtext().

◆ ISTRUNK

#define ISTRUNK (   p)
Value:
((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
(p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
#define SIG_PRI
Definition: chan_dahdi.h:745
#define SIG_FXSGS
Definition: chan_dahdi.h:732
#define SIG_FXSKS
Definition: chan_dahdi.h:733
#define SIG_FXSLS
Definition: chan_dahdi.h:731

Definition at line 590 of file chan_dahdi.c.

Referenced by analog_ss_thread(), and dahdi_indicate().

◆ MASK_AVAIL

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 675 of file chan_dahdi.c.

◆ MASK_INUSE

#define MASK_INUSE   (1 << 1)

Channel currently in use

Definition at line 676 of file chan_dahdi.c.

◆ MAX_CHANLIST_LEN

#define MAX_CHANLIST_LEN   80

The length of the parameters list of 'dahdichan'.

Todo:
Move definition of MAX_CHANLIST_LEN to a proper place.

Definition at line 17726 of file chan_dahdi.c.

◆ MIN_MS_SINCE_FLASH

#define MIN_MS_SINCE_FLASH   ((2000) )

2000 ms

Definition at line 682 of file chan_dahdi.c.

Referenced by dahdi_handle_event().

◆ NEED_MFDETECT

#define NEED_MFDETECT (   p)    (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))

Signaling types that need to use MF detection should be placed in this macro.

Definition at line 525 of file chan_dahdi.c.

Referenced by analog_ss_thread(), and dahdi_new().

◆ NUM_CADENCE_MAX

#define NUM_CADENCE_MAX   25

Definition at line 563 of file chan_dahdi.c.

Referenced by process_dahdi().

◆ NUM_SPANS

#define NUM_SPANS   32

◆ POLARITY_IDLE

#define POLARITY_IDLE   0

Definition at line 792 of file chan_dahdi.c.

Referenced by analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), and unalloc_sub().

◆ POLARITY_REV

#define POLARITY_REV   1

Definition at line 793 of file chan_dahdi.c.

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

◆ PROC_DAHDI_OPT_NOCHAN

#define PROC_DAHDI_OPT_NOCHAN   (1 << 0)

process_dahdi() - ignore keyword 'channel' and similar

Definition at line 17861 of file chan_dahdi.c.

Referenced by process_dahdi(), and setup_dahdi_int().

◆ PROC_DAHDI_OPT_NOWARN

#define PROC_DAHDI_OPT_NOWARN   (1 << 1)

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

Definition at line 17863 of file chan_dahdi.c.

Referenced by process_dahdi(), and setup_dahdi_int().

◆ READ_SIZE

#define READ_SIZE   160

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

Definition at line 673 of file chan_dahdi.c.

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

◆ REPORT_CHANNEL_ALARMS

#define REPORT_CHANNEL_ALARMS   1

Definition at line 615 of file chan_dahdi.c.

Referenced by handle_alarms(), handle_clear_alarms(), and process_dahdi().

◆ REPORT_SPAN_ALARMS

#define REPORT_SPAN_ALARMS   2

Definition at line 616 of file chan_dahdi.c.

Referenced by handle_alarms(), handle_clear_alarms(), and process_dahdi().

◆ sig2str

#define sig2str   dahdi_sig2str

◆ SMDI_MD_WAIT_TIMEOUT

#define SMDI_MD_WAIT_TIMEOUT   1500 /* 1.5 seconds */

Definition at line 482 of file chan_dahdi.c.

Referenced by analog_ss_thread().

◆ TRAILER_MS

#define TRAILER_MS   5

Referenced by dahdi_sendtext().

◆ TRANSFER

#define TRANSFER   0

Definition at line 16234 of file chan_dahdi.c.

Referenced by action_transfer(), and dahdi_fake_event().

Function Documentation

◆ __dahdi_exception()

static struct ast_frame* __dahdi_exception ( struct ast_channel ast)
static

Definition at line 8281 of file chan_dahdi.c.

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

8282 {
8283  int res;
8284  int idx;
8285  struct ast_frame *f;
8286  int usedindex = -1;
8287  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
8288 
8289  if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
8290  idx = SUB_REAL;
8291  }
8292 
8293  p->subs[idx].f.frametype = AST_FRAME_NULL;
8294  p->subs[idx].f.datalen = 0;
8295  p->subs[idx].f.samples = 0;
8296  p->subs[idx].f.mallocd = 0;
8297  p->subs[idx].f.offset = 0;
8298  p->subs[idx].f.subclass.integer = 0;
8299  p->subs[idx].f.delivery = ast_tv(0,0);
8300  p->subs[idx].f.src = "dahdi_exception";
8301  p->subs[idx].f.data.ptr = NULL;
8302 
8303 
8304  if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
8305  /* If nobody owns us, absorb the event appropriately, otherwise
8306  we loop indefinitely. This occurs when, during call waiting, the
8307  other end hangs up our channel so that it no longer exists, but we
8308  have neither FLASH'd nor ONHOOK'd to signify our desire to
8309  change to the other channel. */
8310  if (p->fake_event) {
8311  res = p->fake_event;
8312  p->fake_event = 0;
8313  } else
8314  res = dahdi_get_event(p->subs[SUB_REAL].dfd);
8315  /* Switch to real if there is one and this isn't something really silly... */
8316  if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
8317  (res != DAHDI_EVENT_HOOKCOMPLETE)) {
8318  ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
8319  p->owner = p->subs[SUB_REAL].owner;
8320  if (p->owner) {
8321  ast_queue_unhold(p->owner);
8322  }
8323  p->subs[SUB_REAL].needunhold = 1;
8324  }
8325  switch (res) {
8326  case DAHDI_EVENT_ONHOOK:
8327  dahdi_ec_disable(p);
8328  if (p->owner) {
8329  ast_verb(3, "Channel %s still has call, ringing phone\n", ast_channel_name(p->owner));
8330  dahdi_ring_phone(p);
8331  p->callwaitingrepeat = 0;
8332  p->cidcwexpire = 0;
8333  p->cid_suppress_expire = 0;
8334  } else
8335  ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
8336  dahdi_conf_update(p);
8337  break;
8338  case DAHDI_EVENT_RINGOFFHOOK:
8339  dahdi_ec_enable(p);
8340  dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
8341  if (p->owner && (ast_channel_state(p->owner) == AST_STATE_RINGING)) {
8342  p->subs[SUB_REAL].needanswer = 1;
8343  p->dialing = 0;
8344  }
8345  break;
8346  case DAHDI_EVENT_HOOKCOMPLETE:
8347  case DAHDI_EVENT_RINGERON:
8348  case DAHDI_EVENT_RINGEROFF:
8349  /* Do nothing */
8350  break;
8351  case DAHDI_EVENT_WINKFLASH:
8352  p->flashtime = ast_tvnow();
8353  if (p->owner) {
8354  ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, ast_channel_name(p->owner));
8355  if (ast_channel_state(p->owner) != AST_STATE_UP) {
8356  /* Answer if necessary */
8357  usedindex = dahdi_get_index(p->owner, p, 0);
8358  if (usedindex > -1) {
8359  p->subs[usedindex].needanswer = 1;
8360  }
8362  }
8363  p->callwaitingrepeat = 0;
8364  p->cidcwexpire = 0;
8365  p->cid_suppress_expire = 0;
8366  ast_queue_unhold(p->owner);
8367  p->subs[SUB_REAL].needunhold = 1;
8368  } else
8369  ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
8370  dahdi_conf_update(p);
8371  break;
8372  default:
8373  ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
8374  }
8375  f = &p->subs[idx].f;
8376  return f;
8377  }
8378  if (!(p->radio || (p->oprmode < 0)))
8379  ast_debug(1, "Exception on %d, channel %d\n", ast_channel_fd(ast, 0), p->channel);
8380  /* If it's not us, return NULL immediately */
8381  if (ast != p->owner) {
8382  if (p->owner) {
8383  ast_log(LOG_WARNING, "We're %s, not %s\n", ast_channel_name(ast), ast_channel_name(p->owner));
8384  }
8385  f = &p->subs[idx].f;
8386  return f;
8387  }
8388 
8389  f = dahdi_handle_event(ast);
8390  if (!f) {
8391  const char *name = ast_strdupa(ast_channel_name(ast));
8392 
8393  /* Tell the CDR this DAHDI device hung up */
8394  ast_mutex_unlock(&p->lock);
8395  ast_channel_unlock(ast);
8396  ast_set_hangupsource(ast, name, 0);
8397  ast_channel_lock(ast);
8398  ast_mutex_lock(&p->lock);
8399  }
8400  return f;
8401 }
#define dahdi_get_index(ast, p, nullok)
Definition: chan_dahdi.h:827
static struct ast_frame * dahdi_handle_event(struct ast_channel *ast)
Definition: chan_dahdi.c:7386
#define ast_channel_lock(chan)
Definition: channel.h:2837
unsigned int dialing
TRUE if in the process of dialing digits or sending something.
Definition: chan_dahdi.h:234
struct dahdi_subchannel subs[3]
Definition: chan_dahdi.h:131
void * ast_channel_tech_pvt(const struct ast_channel *chan)
void dahdi_ec_enable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4638
unsigned int needanswer
Definition: chan_dahdi.h:86
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
Definition: channel.c:1212
#define LOG_WARNING
Definition: logger.h:274
char * name
Definition: chan_dahdi.c:4361
struct ast_channel * owner
Definition: chan_dahdi.h:127
ast_channel_state
ast_channel states
Definition: channelstate.h:35
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
void dahdi_ec_disable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4710
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
int callwaitingrepeat
Definition: chan_dahdi.h:546
void dahdi_conf_update(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4583
struct ast_frame f
Definition: chan_dahdi.h:82
#define ast_verb(level,...)
Definition: logger.h:455
struct ast_frame_subclass subclass
int oprmode
Definition: chan_dahdi.h:150
union ast_frame::@255 data
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
static int dahdi_ring_phone(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7101
void ast_set_hangupsource(struct ast_channel *chan, const char *source, int force)
Set the source of the hangup in this channel and it&#39;s bridge.
Definition: channel.c:2479
const char * src
unsigned int needunhold
Definition: chan_dahdi.h:89
struct timeval flashtime
Definition: chan_dahdi.h:637
ast_mutex_t lock
Definition: chan_dahdi.h:125
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
struct ast_channel * owner
Definition: chan_dahdi.h:79
#define SUB_REAL
Definition: chan_dahdi.h:57
#define ast_channel_unlock(chan)
Definition: channel.h:2838
static int dahdi_set_hook(int fd, int hs)
Definition: chan_dahdi.c:4922
static int dahdi_get_event(int fd)
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition: chan_dahdi.c:652
static const char * event2str(int event)
Definition: chan_dahdi.c:4382
struct timeval delivery
int fake_event
Holding place for event injected from outside normal operation.
Definition: chan_dahdi.h:667
int ast_channel_fd(const struct ast_channel *chan, int which)
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:226
const char * ast_channel_name(const struct ast_channel *chan)
int cidcwexpire
Definition: chan_dahdi.h:547
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7325
int cid_suppress_expire
Definition: chan_dahdi.h:548
Data structure associated with a single frame of data.
enum ast_frame_type frametype
int radio
Nonzero if the signaling type is sent over a radio.
Definition: chan_dahdi.h:148
int channel
Definition: chan_dahdi.h:538
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 19922 of file chan_dahdi.c.

◆ __unload_module()

static int __unload_module ( void  )
static

Definition at line 17540 of file chan_dahdi.c.

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_native_unload(), destroy_all_channels(), iflock, sig_pri_span::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, ss_thread_complete, and STASIS_MESSAGE_TYPE_CLEANUP.

Referenced by load_module(), and unload_module().

17541 {
17542  struct dahdi_pvt *p;
17543 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17544  int i, j;
17545 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
17546 
17547 #ifdef HAVE_PRI
17548  for (i = 0; i < NUM_SPANS; i++) {
17549  if (pris[i].pri.master != AST_PTHREADT_NULL) {
17550  pthread_cancel(pris[i].pri.master);
17551  pthread_kill(pris[i].pri.master, SIGURG);
17552  }
17553  }
17554  ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
17555  ast_unregister_application(dahdi_send_keypad_facility_app);
17556 #ifdef HAVE_PRI_PROG_W_CAUSE
17557  ast_unregister_application(dahdi_send_callrerouting_facility_app);
17558 #endif
17559 #endif
17560 #if defined(HAVE_SS7)
17561  for (i = 0; i < NUM_SPANS; i++) {
17562  if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
17563  pthread_cancel(linksets[i].ss7.master);
17564  pthread_kill(linksets[i].ss7.master, SIGURG);
17565  }
17566  }
17567  ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
17568 #endif /* defined(HAVE_SS7) */
17569 #if defined(HAVE_OPENR2)
17570  dahdi_r2_destroy_links();
17571  ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
17572  ast_unregister_application(dahdi_accept_r2_call_app);
17573 #endif
17574 
17576  ast_manager_unregister("DAHDIDialOffhook");
17577  ast_manager_unregister("DAHDIHangup");
17578  ast_manager_unregister("DAHDITransfer");
17579  ast_manager_unregister("DAHDIDNDoff");
17580  ast_manager_unregister("DAHDIDNDon");
17581  ast_manager_unregister("DAHDIShowChannels");
17582  ast_manager_unregister("DAHDIRestart");
17583 #if defined(HAVE_PRI)
17584  ast_manager_unregister("PRIShowSpans");
17585  ast_manager_unregister("PRIDebugSet");
17586  ast_manager_unregister("PRIDebugFileSet");
17587  ast_manager_unregister("PRIDebugFileUnset");
17588 #endif /* defined(HAVE_PRI) */
17590 
17591  /* Hangup all interfaces if they have an owner */
17593  for (p = iflist; p; p = p->next) {
17594  if (p->owner)
17596  }
17598 
17601  pthread_cancel(monitor_thread);
17602  pthread_kill(monitor_thread, SIGURG);
17603  pthread_join(monitor_thread, NULL);
17604  }
17607 
17609 
17610 #if defined(HAVE_PRI)
17611  for (i = 0; i < NUM_SPANS; i++) {
17612  if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
17613  pthread_join(pris[i].pri.master, NULL);
17614  }
17615  for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
17616  dahdi_close_pri_fd(&(pris[i]), j);
17617  }
17618  sig_pri_stop_pri(&pris[i].pri);
17619  }
17620 #if defined(HAVE_PRI_CCSS)
17621  ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
17622  ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
17623 #endif /* defined(HAVE_PRI_CCSS) */
17624  sig_pri_unload();
17625 #endif
17626 
17627 #if defined(HAVE_SS7)
17628  for (i = 0; i < NUM_SPANS; i++) {
17629  if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
17630  pthread_join(linksets[i].ss7.master, NULL);
17631  }
17632  for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
17633  dahdi_close_ss7_fd(&(linksets[i]), j);
17634  }
17635  if (linksets[i].ss7.ss7) {
17636  ss7_destroy(linksets[i].ss7.ss7);
17637  linksets[i].ss7.ss7 = NULL;
17638  }
17639  }
17640 #endif /* defined(HAVE_SS7) */
17642 
17644 
17647  STASIS_MESSAGE_TYPE_CLEANUP(dahdichannel_type);
17648  return 0;
17649 }
void sig_pri_unload(void)
void ast_cc_agent_unregister(const struct ast_cc_agent_callbacks *callbacks)
Unregister a set of agent callbacks with the core.
Definition: ccss.c:1254
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static struct ast_cli_entry dahdi_cli[]
Definition: chan_dahdi.c:16220
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
struct dahdi_pvt * next
Definition: chan_dahdi.h:168
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:566
static struct ast_channel_tech dahdi_tech
Definition: chan_dahdi.c:1030
struct ast_channel * owner
Definition: chan_dahdi.h:127
static ast_cond_t ss_thread_complete
Definition: chan_dahdi.c:641
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1523
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
static void destroy_all_channels(void)
Definition: chan_dahdi.c:5667
static ast_mutex_t monlock
Protect the monitoring thread, so only one process can kill or start it, and not when it&#39;s doing some...
Definition: chan_dahdi.c:636
static pthread_t monitor_thread
This is the thread for the monitor which checks for input on the channels which are not currently in ...
Definition: chan_dahdi.c:640
#define AST_PTHREADT_NULL
Definition: lock.h:66
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2451
static ast_mutex_t iflock
Protect the interface list (of dahdi_pvt&#39;s)
Definition: chan_dahdi.c:625
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258
#define SIG_SS7_NUM_DCHANS
Definition: sig_ss7.h:56
#define SIG_PRI_NUM_DCHANS
Definition: sig_pri.h:241
#define ast_cond_destroy(cond)
Definition: lock.h:200
struct ast_format_cap * capabilities
Definition: channel.h:633
void dahdi_native_unload(void)
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void sig_pri_stop_pri(struct sig_pri_span *pri)
static struct dahdi_pvt * iflist
Definition: chan_dahdi.c:801
#define AST_PTHREADT_STOP
Definition: lock.h:67
void ast_cc_monitor_unregister(const struct ast_cc_monitor_callbacks *callbacks)
Unregister a set of monitor callbacks with the core.
Definition: ccss.c:1217
#define NUM_SPANS
Definition: chan_dahdi.c:553
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ __unreg_module()

static void __unreg_module ( void  )
static

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

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

3432 {
3433  int res;
3434  if (p->subs[SUB_REAL].owner == ast)
3435  res = 0;
3436  else if (p->subs[SUB_CALLWAIT].owner == ast)
3437  res = 1;
3438  else if (p->subs[SUB_THREEWAY].owner == ast)
3439  res = 2;
3440  else {
3441  res = -1;
3442  if (!nullok)
3444  "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
3445  ast ? ast_channel_name(ast) : "", p->channel, fname, line);
3446  }
3447  return res;
3448 }
struct dahdi_subchannel subs[3]
Definition: chan_dahdi.h:131
#define SUB_THREEWAY
Definition: chan_dahdi.h:59
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42
struct ast_channel * owner
Definition: chan_dahdi.h:79
#define SUB_REAL
Definition: chan_dahdi.h:57
const char * ast_channel_name(const struct ast_channel *chan)
int channel
Definition: chan_dahdi.h:538
#define SUB_CALLWAIT
Definition: chan_dahdi.h:58

◆ action_dahdidialoffhook()

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

Definition at line 16372 of file chan_dahdi.c.

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

Referenced by load_module().

16373 {
16374  struct dahdi_pvt *p;
16375  const char *channel = astman_get_header(m, "DAHDIChannel");
16376  const char *number = astman_get_header(m, "Number");
16377  int i;
16378 
16379  if (ast_strlen_zero(channel)) {
16380  astman_send_error(s, m, "No channel specified");
16381  return 0;
16382  }
16383  if (ast_strlen_zero(number)) {
16384  astman_send_error(s, m, "No number specified");
16385  return 0;
16386  }
16387  p = find_channel_from_str(channel);
16388  if (!p) {
16389  astman_send_error(s, m, "No such channel");
16390  return 0;
16391  }
16392  if (!p->owner) {
16393  astman_send_error(s, m, "Channel does not have it's owner");
16394  return 0;
16395  }
16396  for (i = 0; i < strlen(number); i++) {
16397  struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16398  dahdi_queue_frame(p, &f);
16399  }
16400  astman_send_ack(s, m, "DAHDIDialOffhook");
16401  return 0;
16402 }
struct ast_channel * owner
Definition: chan_dahdi.h:127
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
Definition: muted.c:95
static struct dahdi_pvt * find_channel_from_str(const char *channel)
Definition: chan_dahdi.c:16276
#define AST_FRAME_DTMF
static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
Definition: chan_dahdi.c:3490
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
Number structure.
Definition: app_followme.c:154
#define ast_strlen_zero(a)
Definition: muted.c:73
Data structure associated with a single frame of data.
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159

◆ action_dahdidndoff()

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

Definition at line 16307 of file chan_dahdi.c.

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

Referenced by load_module().

16308 {
16309  struct dahdi_pvt *p;
16310  const char *channel = astman_get_header(m, "DAHDIChannel");
16311 
16312  if (ast_strlen_zero(channel)) {
16313  astman_send_error(s, m, "No channel specified");
16314  return 0;
16315  }
16316  p = find_channel_from_str(channel);
16317  if (!p) {
16318  astman_send_error(s, m, "No such channel");
16319  return 0;
16320  }
16321  dahdi_dnd(p, 0);
16322  astman_send_ack(s, m, "DND Disabled");
16323  return 0;
16324 }
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
Definition: muted.c:95
static struct dahdi_pvt * find_channel_from_str(const char *channel)
Definition: chan_dahdi.c:16276
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
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:9466
#define ast_strlen_zero(a)
Definition: muted.c:73
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159

◆ action_dahdidndon()

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

Definition at line 16288 of file chan_dahdi.c.

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

Referenced by load_module().

16289 {
16290  struct dahdi_pvt *p;
16291  const char *channel = astman_get_header(m, "DAHDIChannel");
16292 
16293  if (ast_strlen_zero(channel)) {
16294  astman_send_error(s, m, "No channel specified");
16295  return 0;
16296  }
16297  p = find_channel_from_str(channel);
16298  if (!p) {
16299  astman_send_error(s, m, "No such channel");
16300  return 0;
16301  }
16302  dahdi_dnd(p, 1);
16303  astman_send_ack(s, m, "DND Enabled");
16304  return 0;
16305 }
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
Definition: muted.c:95
static struct dahdi_pvt * find_channel_from_str(const char *channel)
Definition: chan_dahdi.c:16276
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
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:9466
#define ast_strlen_zero(a)
Definition: muted.c:73
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159

◆ action_dahdirestart()

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

Definition at line 15562 of file chan_dahdi.c.

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

Referenced by load_module().

15563 {
15564  if (dahdi_restart() != 0) {
15565  astman_send_error(s, m, "Failed rereading DAHDI configuration");
15566  return 1;
15567  }
15568  astman_send_ack(s, m, "DAHDIRestart: Success");
15569  return 0;
15570 }
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
static int dahdi_restart(void)
Definition: chan_dahdi.c:15424
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159

◆ action_dahdishowchannels()

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

Definition at line 16404 of file chan_dahdi.c.

References alarm2str(), ast_cli_args::argc, ast_cli_args::argv, ARRAY_LEN, ast_assert, ast_channel_accountcode(), ast_channel_name(), ast_channel_tech(), ast_channel_tech_pvt(), ast_channel_uniqueid(), ast_cli(), AST_CLI_DEFINE, ast_log, ast_module_ref, ast_module_unref, ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, ast_strlen_zero, astman_append(), astman_get_header(), astman_send_list_complete_end(), astman_send_list_complete_start(), astman_send_listack(), sig_ss7_linkset::called_nai, sig_ss7_linkset::calling_nai, sig_ss7_chan::chan_pvt, sig_ss7_chan::channel, dahdi_pvt::channel, sig_ss7_chan::cic, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_pvt::context, dahdi_dnd(), dahdi_sig_pri_lib_handles(), dahdi_pvt::description, sig_ss7_chan::dpc, errno, ast_cli_args::fd, sig_ss7_linkset::flags, FORMAT, FORMAT2, get_alarms(), iflock, dahdi_pvt::inservice, sig_ss7_linkset::internationalprefix, sig_ss7_linkset::LINKSET_STATE_UP, dahdi_pvt::locallyblocked, LOG_ERROR, sig_ss7_linkset::nationalprefix, sig_ss7_linkset::networkroutedprefix, dahdi_pvt::next, NULL, NUM_SPANS, sig_ss7_linkset::numchans, dahdi_pvt::owner, sig_ss7_chan::owner, sig_ss7_linkset::pvts, dahdi_pvt::remotelyblocked, ast_module_info::self, dahdi_pvt::sig, sig2str, sig_pri_ami_show_spans(), sig_pri_cc_agent_callee_available(), sig_pri_cc_agent_destructor(), sig_pri_cc_agent_init(), sig_pri_cc_agent_party_b_free(), sig_pri_cc_agent_req_rsp(), sig_pri_cc_agent_start_monitoring(), sig_pri_cc_agent_start_offer_timer(), sig_pri_cc_agent_status_req(), sig_pri_cc_agent_stop_offer_timer(), sig_pri_cc_agent_stop_ringing(), sig_pri_cc_monitor_cancel_available_timer(), sig_pri_cc_monitor_destructor(), sig_pri_cc_monitor_req_cc(), sig_pri_cc_monitor_status_rsp(), sig_pri_cc_monitor_suspend(), sig_pri_cc_monitor_unsuspend(), dahdi_pvt::sig_pvt, sig_ss7_add_sigchan(), sig_ss7_cic_blocking(), sig_ss7_cli_show_channels(), sig_ss7_cli_show_channels_header(), SIG_SS7_DEBUG, sig_ss7_find_cic(), sig_ss7_find_cic_range(), sig_ss7_group_blocking(), SIG_SS7_NUM_DCHANS, sig_ss7_reset_cic(), sig_ss7_reset_group(), sig_ss7_linkset::ss7, SS7_BLOCKED_HARDWARE, SS7_BLOCKED_MAINTENANCE, sig_ss7_chan::ss7call, sig_ss7_linkset::state, state, sig_ss7_linkset::subscriberprefix, tmp(), type, ast_cc_monitor_callbacks::type, ast_cc_agent_callbacks::type, sig_ss7_linkset::unknownprefix, and ast_cli_entry::usage.

Referenced by load_module().

16405 {
16406  struct dahdi_pvt *tmp = NULL;
16407  const char *id = astman_get_header(m, "ActionID");
16408  const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16409  char idText[256];
16410  int channels = 0;
16411  int dahdichanquery;
16412 
16413  if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16414  /* Not numeric string. */
16415  dahdichanquery = -1;
16416  }
16417 
16418  idText[0] = '\0';
16419  if (!ast_strlen_zero(id)) {
16420  snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16421  }
16422 
16423  astman_send_listack(s, m, "DAHDI channel status will follow", "start");
16424 
16426 
16427  for (tmp = iflist; tmp; tmp = tmp->next) {
16428  if (tmp->channel > 0) {
16429  int alm;
16430 
16431  /* If a specific channel is queried for, only deliver status for that channel */
16432  if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16433  continue;
16434 
16435  alm = get_alarms(tmp);
16436  channels++;
16437  if (tmp->owner) {
16438  /* Add data if we have a current call */
16439  astman_append(s,
16440  "Event: DAHDIShowChannels\r\n"
16441  "DAHDIChannel: %d\r\n"
16442  "Channel: %s\r\n"
16443  "Uniqueid: %s\r\n"
16444  "AccountCode: %s\r\n"
16445  "Signalling: %s\r\n"
16446  "SignallingCode: %d\r\n"
16447  "Context: %s\r\n"
16448  "DND: %s\r\n"
16449  "Alarm: %s\r\n"
16450  "Description: %s\r\n"
16451  "%s"
16452  "\r\n",
16453  tmp->channel,
16454  ast_channel_name(tmp->owner),
16457  sig2str(tmp->sig),
16458  tmp->sig,
16459  tmp->context,
16460  dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16461  alarm2str(alm),
16462  tmp->description, idText);
16463  } else {
16464  astman_append(s,
16465  "Event: DAHDIShowChannels\r\n"
16466  "DAHDIChannel: %d\r\n"
16467  "Signalling: %s\r\n"
16468  "SignallingCode: %d\r\n"
16469  "Context: %s\r\n"
16470  "DND: %s\r\n"
16471  "Alarm: %s\r\n"
16472  "Description: %s\r\n"
16473  "%s"
16474  "\r\n",
16475  tmp->channel, sig2str(tmp->sig), tmp->sig,
16476  tmp->context,
16477  dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16478  alarm2str(alm),
16479  tmp->description, idText);
16480  }
16481  }
16482  }
16483 
16485 
16486  astman_send_list_complete_start(s, m, "DAHDIShowChannelsComplete", channels);
16487  astman_append(s, "Items: %d\r\n", channels);
16489  return 0;
16490 }
char description[32]
A description for the channel configuration.
Definition: chan_dahdi.h:449
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
struct dahdi_pvt * next
Definition: chan_dahdi.h:168
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:3237
struct ast_channel * owner
Definition: chan_dahdi.h:127
static int tmp()
Definition: bt_open.c:389
static char * alarm2str(int alm)
Definition: chan_dahdi.c:4372
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
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:9466
const char * ast_channel_accountcode(const struct ast_channel *chan)
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3245
static ast_mutex_t iflock
Protect the interface list (of dahdi_pvt&#39;s)
Definition: chan_dahdi.c:625
static struct channel_usage channels
const char * ast_channel_uniqueid(const struct ast_channel *chan)
#define ast_strlen_zero(a)
Definition: muted.c:73
static int get_alarms(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7204
char context[AST_MAX_CONTEXT]
The configured context for incoming calls.
Definition: chan_dahdi.h:444
static struct dahdi_pvt * iflist
Definition: chan_dahdi.c:801
const char * ast_channel_name(const struct ast_channel *chan)
#define sig2str
Definition: chan_dahdi.c:4455
int channel
Definition: chan_dahdi.h:538
#define ast_mutex_unlock(a)
Definition: lock.h:188
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:3201

◆ action_transfer()

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

Definition at line 16326 of file chan_dahdi.c.

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

Referenced by load_module().

16327 {
16328  struct dahdi_pvt *p;
16329  const char *channel = astman_get_header(m, "DAHDIChannel");
16330 
16331  if (ast_strlen_zero(channel)) {
16332  astman_send_error(s, m, "No channel specified");
16333  return 0;
16334  }
16335  p = find_channel_from_str(channel);
16336  if (!p) {
16337  astman_send_error(s, m, "No such channel");
16338  return 0;
16339  }
16340  if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16341  astman_send_error(s, m, "Channel signaling is not analog");
16342  return 0;
16343  }
16345  astman_send_ack(s, m, "DAHDITransfer");
16346  return 0;
16347 }
static int dahdi_analog_lib_handles(int signalling, int radio, int oprmode)
Definition: chan_dahdi.h:786
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
Definition: muted.c:95
static struct dahdi_pvt * find_channel_from_str(const char *channel)
Definition: chan_dahdi.c:16276
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define TRANSFER
Definition: chan_dahdi.c:16234
static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
Definition: chan_dahdi.c:16237
#define ast_strlen_zero(a)
Definition: muted.c:73
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159

◆ action_transferhangup()

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

Definition at line 16349 of file chan_dahdi.c.

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

Referenced by load_module().

16350 {
16351  struct dahdi_pvt *p;
16352  const char *channel = astman_get_header(m, "DAHDIChannel");
16353 
16354  if (ast_strlen_zero(channel)) {
16355  astman_send_error(s, m, "No channel specified");
16356  return 0;
16357  }
16358  p = find_channel_from_str(channel);
16359  if (!p) {
16360  astman_send_error(s, m, "No such channel");
16361  return 0;
16362  }
16363  if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16364  astman_send_error(s, m, "Channel signaling is not analog");
16365  return 0;
16366  }
16368  astman_send_ack(s, m, "DAHDIHangup");
16369  return 0;
16370 }
static int dahdi_analog_lib_handles(int signalling, int radio, int oprmode)
Definition: chan_dahdi.h:786
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
Definition: muted.c:95
static struct dahdi_pvt * find_channel_from_str(const char *channel)
Definition: chan_dahdi.c:16276
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
Definition: chan_dahdi.c:16237
#define HANGUP
Definition: chan_dahdi.c:16235
#define ast_strlen_zero(a)
Definition: muted.c:73
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159

◆ alarm2str()

static char* alarm2str ( int  alm)
static

Definition at line 4372 of file chan_dahdi.c.

References alarm, alarms, and ARRAY_LEN.

Referenced by action_dahdishowchannels(), and handle_alarms().

4373 {
4374  int x;
4375  for (x = 0; x < ARRAY_LEN(alarms); x++) {
4376  if (alarms[x].alarm & alm)
4377  return alarms[x].name;
4378  }
4379  return alm ? "Unknown Alarm" : "No Alarm";
4380 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int alarm
Definition: chan_dahdi.c:4360
static struct @106 alarms[]

◆ alloc_sub()

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

Definition at line 4167 of file chan_dahdi.c.

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

Referenced by analog_ss_thread(), dahdi_handle_event(), my_allocate_sub(), and my_unallocate_sub().

4168 {
4169  struct dahdi_bufferinfo bi;
4170  int res;
4171  if (p->subs[x].dfd >= 0) {
4172  ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
4173  return -1;
4174  }
4175 
4176  p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
4177  if (p->subs[x].dfd <= -1) {
4178  ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
4179  return -1;
4180  }
4181 
4182  res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
4183  if (!res) {
4184  bi.txbufpolicy = p->buf_policy;
4185  bi.rxbufpolicy = p->buf_policy;
4186  bi.numbufs = p->buf_no;
4187  res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
4188  if (res < 0) {
4189  ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
4190  }
4191  } else
4192  ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
4193 
4194  if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
4195  ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
4196  dahdi_close_sub(p, x);
4197  p->subs[x].dfd = -1;
4198  return -1;
4199  }
4200  ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
4201  return 0;
4202 }
struct dahdi_subchannel subs[3]
Definition: chan_dahdi.h:131
#define LOG_WARNING
Definition: logger.h:274
int buf_no
Definition: chan_dahdi.h:139
static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
Definition: chan_dahdi.c:4139
const char *const subnames[]
Definition: chan_dahdi.c:795
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
static int dahdi_open(char *fn)
Definition: chan_dahdi.c:4086
int errno
int buf_policy
Definition: chan_dahdi.h:140
int channel
Definition: chan_dahdi.h:538

◆ analog_ss_thread()

static void * analog_ss_thread ( void *  data)
static

Definition at line 9512 of file chan_dahdi.c.

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, 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_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::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, 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(), timeout, 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(), dahdi_ring_phone(), do_monitor(), handle_init_event(), and mwi_thread().

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

◆ analog_tone_to_dahditone()

static int analog_tone_to_dahditone ( enum analog_tone  tone)
static

Definition at line 1106 of file chan_dahdi.c.

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

Referenced by my_play_tone().

1107 {
1108  switch (tone) {
1109  case ANALOG_TONE_RINGTONE:
1110  return DAHDI_TONE_RINGTONE;
1111  case ANALOG_TONE_STUTTER:
1112  return DAHDI_TONE_STUTTER;
1114  return DAHDI_TONE_CONGESTION;
1115  case ANALOG_TONE_DIALTONE:
1116  return DAHDI_TONE_DIALTONE;
1118  return DAHDI_TONE_DIALRECALL;
1119  case ANALOG_TONE_INFO:
1120  return DAHDI_TONE_INFO;
1121  default:
1122  return -1;
1123  }
1124 }

◆ analogsub_to_dahdisub()

static int analogsub_to_dahdisub ( enum analog_sub  analogsub)
static

Definition at line 1126 of file chan_dahdi.c.

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

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

1127 {
1128  int index;
1129 
1130  switch (analogsub) {
1131  case ANALOG_SUB_REAL:
1132  index = SUB_REAL;
1133  break;
1134  case ANALOG_SUB_CALLWAIT:
1135  index = SUB_CALLWAIT;
1136  break;
1137  case ANALOG_SUB_THREEWAY:
1138  index = SUB_THREEWAY;
1139  break;
1140  default:
1141  ast_log(LOG_ERROR, "Unidentified sub!\n");
1142  index = SUB_REAL;
1143  }
1144 
1145  return index;
1146 }
#define SUB_THREEWAY
Definition: chan_dahdi.h:59
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
#define SUB_REAL
Definition: chan_dahdi.h:57
#define SUB_CALLWAIT
Definition: chan_dahdi.h:58

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 19922 of file chan_dahdi.c.

◆ attempt_transfer()

static int attempt_transfer ( struct dahdi_pvt p)
static

Definition at line 7145 of file chan_dahdi.c.

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

7146 {
7147  struct ast_channel *owner_real;
7148  struct ast_channel *owner_3way;
7149  enum ast_transfer_result xfer_res;
7150  int res = 0;
7151 
7152  owner_real = ast_channel_ref(p->subs[SUB_REAL].owner);
7153  owner_3way = ast_channel_ref(p->subs[SUB_THREEWAY].owner);
7154 
7155  ast_verb(3, "TRANSFERRING %s to %s\n",
7156  ast_channel_name(owner_3way), ast_channel_name(owner_real));
7157 
7158  ast_channel_unlock(owner_real);
7159  ast_channel_unlock(owner_3way);
7160  ast_mutex_unlock(&p->lock);
7161 
7162  xfer_res = ast_bridge_transfer_attended(owner_3way, owner_real);
7163  if (xfer_res != AST_BRIDGE_TRANSFER_SUCCESS) {
7164  ast_softhangup(owner_3way, AST_SOFTHANGUP_DEV);
7165  res = -1;
7166  }
7167 
7168  /* Must leave with these locked. */
7169  ast_channel_lock(owner_real);
7170  ast_mutex_lock(&p->lock);
7171 
7172  ast_channel_unref(owner_real);
7173  ast_channel_unref(owner_3way);
7174 
7175  return res;
7176 }
#define ast_channel_lock(chan)
Definition: channel.h:2837
Main Channel structure associated with a channel.
enum ast_transfer_result ast_bridge_transfer_attended(struct ast_channel *to_transferee, struct ast_channel *to_transfer_target)
Attended transfer.
Definition: bridge.c:4709
struct dahdi_subchannel subs[3]
Definition: chan_dahdi.h:131
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2873
#define SUB_THREEWAY
Definition: chan_dahdi.h:59
#define ast_mutex_lock(a)
Definition: lock.h:187
ast_transfer_result
Definition: bridge.h:1101
#define ast_verb(level,...)
Definition: logger.h:455
ast_mutex_t lock
Definition: chan_dahdi.h:125
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2451
struct ast_channel * owner
Definition: chan_dahdi.h:79
#define SUB_REAL
Definition: chan_dahdi.h:57
#define ast_channel_unlock(chan)
Definition: channel.h:2838
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2862
const char * ast_channel_name(const struct ast_channel *chan)
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ available()

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

Definition at line 13058 of file chan_dahdi.c.

References analog_available(), ARRAY_LEN, ast_calloc, ast_cc_config_params_init, ast_copy_string(), ast_free, ast_log, ast_mutex_init, dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::bufsize, dahdi_pvt::cc_params, CHAN_PSEUDO, sig_pri_chan::chan_pvt, sig_pri_chan::channel, dahdi_pvt::channel, dahdi_pvt::context, dahdi_analog_lib_handles(), dahdi_open(), destroy_dahdi_pvt(), dahdi_subchannel::dfd, errno, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pvt::immediate, dahdi_pvt::inalarm, dahdi_pvt::law_default, dahdi_pvt::locallyblocked, dahdi_pvt::lock, LOG_ERROR, LOG_WARNING, dahdi_pvt::mohinterpret, sig_pri_chan::no_b_channel, NULL, sig_pri_span::numchans, dahdi_pvt::oprmode, dahdi_pvt::outsigmod, dahdi_pvt::owner, dahdi_pvt::priexclusive, dahdi_pvt::priindication_oob, sig_pri_span::pvts, dahdi_pvt::radio, dahdi_pvt::remotelyblocked, dahdi_pvt::sig, sig_pri_span::sig, sig_pri_available(), sig_pri_chan_new(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, sig_ss7_available(), dahdi_pvt::span, sig_pri_span::span, dahdi_pvt::stripmsd, SUB_REAL, dahdi_pvt::subs, dahdi_pvt::use_callerid, and dahdi_pvt::use_callingpres.

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

13059 {
13060  struct dahdi_pvt *p = *pvt;
13061 
13062  if (p->inalarm)
13063  return 0;
13064 
13065  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode))
13066  return analog_available(p->sig_pvt);
13067 
13068  switch (p->sig) {
13069 #if defined(HAVE_PRI)
13071  {
13072  struct sig_pri_chan *pvt_chan;
13073  int res;
13074 
13075  pvt_chan = p->sig_pvt;
13076  res = sig_pri_available(&pvt_chan, is_specific_channel);
13077  *pvt = pvt_chan->chan_pvt;
13078  return res;
13079  }
13080 #endif /* defined(HAVE_PRI) */
13081 #if defined(HAVE_SS7)
13082  case SIG_SS7:
13083  return sig_ss7_available(p->sig_pvt);
13084 #endif /* defined(HAVE_SS7) */
13085  default:
13086  break;
13087  }
13088 
13089  if (p->locallyblocked || p->remotelyblocked) {
13090  return 0;
13091  }
13092 
13093  /* If no owner definitely available */
13094  if (!p->owner) {
13095 #ifdef HAVE_OPENR2
13096  /* Trust MFC/R2 */
13097  if (p->mfcr2) {
13098  if (p->mfcr2call) {
13099  return 0;
13100  } else {
13101  return 1;
13102  }
13103  }
13104 #endif
13105  return 1;
13106  }
13107 
13108  return 0;
13109 }
int sig_pri_available(struct sig_pri_chan **pvt, int is_specific_channel)
int sig_ss7_available(struct sig_ss7_chan *p)
static int dahdi_analog_lib_handles(int signalling, int radio, int oprmode)
Definition: chan_dahdi.h:786
unsigned int locallyblocked
Bitmask for the channel being locally blocked.
Definition: chan_dahdi.h:404
struct ast_channel * owner
Definition: chan_dahdi.h:127
void * sig_pvt
Definition: chan_dahdi.h:709
void * chan_pvt
Definition: sig_pri.h:376
int oprmode
Definition: chan_dahdi.h:150
int analog_available(struct analog_pvt *p)
Definition: sig_analog.c:795
#define SIG_SS7
Definition: chan_dahdi.h:750
#define SIG_PRI_LIB_HANDLE_CASES
Definition: chan_dahdi.h:756
unsigned int remotelyblocked
Bitmask for the channel being remotely blocked. 1 maintenance, 2 blocked in hardware.
Definition: chan_dahdi.h:413
int radio
Nonzero if the signaling type is sent over a radio.
Definition: chan_dahdi.h:148
unsigned int inalarm
TRUE if in an alarm condition.
Definition: chan_dahdi.h:286

◆ build_channels()

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

Definition at line 17667 of file chan_dahdi.c.

References ast_log, ast_strdupa, ast_verb, c, dahdi_chan_conf::chan, CHAN_PSEUDO, has_pseudo, dahdi_chan_conf::is_sig_auto, LOG_ERROR, LOG_WARNING, mkintf(), dahdi_pvt::sig, sig2str, strsep(), tmp(), dahdi_chan_conf::wanted_channels_end, and dahdi_chan_conf::wanted_channels_start.

Referenced by process_dahdi().

17668 {
17669  char *c, *chan;
17670  int x, start, finish;
17671  struct dahdi_pvt *tmp;
17672 
17673  if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
17674  ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
17675  return -1;
17676  }
17677 
17678  c = ast_strdupa(value);
17679 
17680  while ((chan = strsep(&c, ","))) {
17681  if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
17682  /* Range */
17683  } else if (sscanf(chan, "%30d", &start)) {
17684  /* Just one */
17685  finish = start;
17686  } else if (!strcasecmp(chan, "pseudo")) {
17687  finish = start = CHAN_PSEUDO;
17688  } else {
17689  ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
17690  return -1;
17691  }
17692  if (finish < start) {
17693  ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
17694  x = finish;
17695  finish = start;
17696  start = x;
17697  }
17698 
17699  for (x = start; x <= finish; x++) {
17700  if (conf->wanted_channels_start &&
17701  (x < conf->wanted_channels_start ||
17702  x > conf->wanted_channels_end)
17703  ) {
17704  continue;
17705  }
17706  tmp = mkintf(x, conf, reload);
17707 
17708  if (tmp) {
17709  ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
17710  } else {
17711  ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
17712  (reload == 1) ? "reconfigure" : "register", value);
17713  return -1;
17714  }
17715  if (x == CHAN_PSEUDO) {
17716  has_pseudo = 1;
17717  }
17718  }
17719  }
17720 
17721  return 0;
17722 }
#define LOG_WARNING
Definition: logger.h:274
static int tmp()
Definition: bt_open.c:389
#define CHAN_PSEUDO
Definition: chan_dahdi.c:556
static struct test_val c
int value
Definition: syslog.c:37
#define ast_verb(level,...)
Definition: logger.h:455
#define ast_log
Definition: astobj2.c:42
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static int reload(void)
Definition: chan_dahdi.c:19898
#define LOG_ERROR
Definition: logger.h:285
static int has_pseudo
Definition: chan_dahdi.c:567
int wanted_channels_start
Don&#39;t create channels below this number.
Definition: chan_dahdi.c:859
int wanted_channels_end
Don&#39;t create channels above this number (infinity by default)
Definition: chan_dahdi.c:865
char * strsep(char **str, const char *delims)
struct dahdi_pvt chan
Definition: chan_dahdi.c:832
static struct dahdi_pvt * mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
Definition: chan_dahdi.c:12095
#define sig2str
Definition: chan_dahdi.c:4455

◆ bump_gains()

static int bump_gains ( struct dahdi_pvt p)
static

Definition at line 4895 of file chan_dahdi.c.

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(), dahdi_dial_str(), mwi_thread(), and my_start_cid_detect().

4896 {
4897  int res;
4898 
4899  /* Bump receive gain by value stored in cid_rxgain */
4900  res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
4901  if (res) {
4902  ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
4903  return -1;
4904  }
4905 
4906  return 0;
4907 }
struct dahdi_subchannel subs[3]
Definition: chan_dahdi.h:131
#define LOG_WARNING
Definition: logger.h:274
float txdrc
Definition: chan_dahdi.h:163
float cid_rxgain
Amount of gain to increase during caller id.
Definition: chan_dahdi.h:157
int law
Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW.
Definition: chan_dahdi.h:509
float txgain
Software Tx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:161
#define ast_log
Definition: astobj2.c:42
float rxdrc
Definition: chan_dahdi.h:164
int errno
#define SUB_REAL
Definition: chan_dahdi.h:57
static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
Definition: chan_dahdi.c:4890
float rxgain
Software Rx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:159

◆ calc_energy()

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

Definition at line 10712 of file chan_dahdi.c.

References abs, AST_ALAW, ast_format_ulaw, AST_MULAW, and len().

Referenced by do_monitor(), and mwi_thread().

10713 {
10714  int x;
10715  int sum = 0;
10716 
10717  if (!len)
10718  return 0;
10719 
10720  for (x = 0; x < len; x++)
10721  sum += abs(law == ast_format_ulaw ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
10722 
10723  return sum / len;
10724 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
#define AST_ALAW(a)
Definition: alaw.h:84
#define AST_MULAW(a)
Definition: ulaw.h:85
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define abs(x)
Definition: f2c.h:195

◆ canmatch_featurecode()

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

Definition at line 9485 of file chan_dahdi.c.

Referenced by analog_ss_thread().

9486 {
9487  int extlen = strlen(exten);
9488 
9489  if (!extlen) {
9490  return 1;
9491  }
9492 
9493  if (extlen < strlen(pickupexten) && !strncmp(pickupexten, exten, extlen)) {
9494  return 1;
9495  }
9496  /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
9497  if (exten[0] == '*' && extlen < 3) {
9498  if (extlen == 1) {
9499  return 1;
9500  }
9501  /* "*0" should be processed before it gets here */
9502  switch (exten[1]) {
9503  case '6':
9504  case '7':
9505  case '8':
9506  return 1;
9507  }
9508  }
9509  return 0;
9510 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118

◆ check_for_conference()

static int check_for_conference ( struct dahdi_pvt p)
static

Definition at line 7178 of file chan_dahdi.c.

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(), my_check_for_conference(), and my_complete_conference_update().

7179 {
7180  struct dahdi_confinfo ci;
7181  /* Fine if we already have a master, etc */
7182  if (p->master || (p->confno > -1))
7183  return 0;
7184  memset(&ci, 0, sizeof(ci));
7185  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
7186  ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
7187  return 0;
7188  }
7189  /* If we have no master and don't have a confno, then
7190  if we're in a conference, it's probably a MeetMe room or
7191  some such, so don't let us 3-way out! */
7192  if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
7193  ast_verb(3, "Avoiding 3-way call when in an external conference\n");
7194  return 1;
7195  }
7196  return 0;
7197 }
struct dahdi_subchannel subs[3]
Definition: chan_dahdi.h:131
struct dahdi_pvt * master
Definition: chan_dahdi.h:135
#define LOG_WARNING
Definition: logger.h:274
#define ast_verb(level,...)
Definition: logger.h:455
#define ast_log
Definition: astobj2.c:42
int errno
#define SUB_REAL
Definition: chan_dahdi.h:57
int confno
Definition: chan_dahdi.h:510
int channel
Definition: chan_dahdi.h:538
struct dahdi_confinfo curconf
Definition: chan_dahdi.h:92

◆ conf_add()

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

Definition at line 4457 of file chan_dahdi.c.

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

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

4458 {
4459  /* If the conference already exists, and we're already in it
4460  don't bother doing anything */
4461  struct dahdi_confinfo zi;
4462 
4463  memset(&zi, 0, sizeof(zi));
4464  zi.chan = 0;
4465 
4466  if (slavechannel > 0) {
4467  /* If we have only one slave, do a digital mon */
4468  zi.confmode = DAHDI_CONF_DIGITALMON;
4469  zi.confno = slavechannel;
4470  } else {
4471  if (!idx) {
4472  /* Real-side and pseudo-side both participate in conference */
4473  zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
4474  DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
4475  } else
4476  zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
4477  zi.confno = p->confno;
4478  }
4479  if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
4480  return 0;
4481  if (c->dfd < 0)
4482  return 0;
4483  if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4484  ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
4485  return -1;
4486  }
4487  if (slavechannel < 1) {
4488  p->confno = zi.confno;
4489  }
4490  c->curconf = zi;
4491  ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4492  return 0;
4493 }
#define LOG_WARNING
Definition: logger.h:274
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
int errno
int confno
Definition: chan_dahdi.h:510
struct dahdi_confinfo curconf
Definition: chan_dahdi.h:92

◆ conf_del()

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

Definition at line 4506 of file chan_dahdi.c.

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

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

4507 {
4508  struct dahdi_confinfo zi;
4509  if (/* Can't delete if there's no dfd */
4510  (c->dfd < 0) ||
4511  /* Don't delete from the conference if it's not our conference */
4512  !isourconf(p, c)
4513  /* Don't delete if we don't think it's conferenced at all (implied) */
4514  ) return 0;
4515  memset(&zi, 0, sizeof(zi));
4516  if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4517  ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
4518  return -1;
4519  }
4520  ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4521  memcpy(&c->curconf, &zi, sizeof(c->curconf));
4522  return 0;
4523 }
#define LOG_WARNING
Definition: logger.h:274
static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
Definition: chan_dahdi.c:4495
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
int errno
struct dahdi_confinfo curconf
Definition: chan_dahdi.h:92

◆ create_channel_name()

static struct ast_str* create_channel_name ( struct dahdi_pvt i)
static

Definition at line 9099 of file chan_dahdi.c.

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(), dahdi_indicate(), and dahdi_new().

9101 {
9102  struct ast_str *chan_name;
9103  int x, y;
9104 
9105  /* Create the new channel name tail. */
9106  if (!(chan_name = ast_str_create(32))) {
9107  return NULL;
9108  }
9109  if (i->channel == CHAN_PSEUDO) {
9110  ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
9111 #if defined(HAVE_PRI)
9112  } else if (i->pri) {
9113  ast_mutex_lock(&i->pri->lock);
9114  y = ++i->pri->new_chan_seq;
9115  if (is_outgoing) {
9116  ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, (unsigned)y);
9117  address[0] = '\0';
9118  } else if (ast_strlen_zero(i->cid_subaddr)) {
9119  /* Put in caller-id number only since there is no subaddress. */
9120  ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, (unsigned)y);
9121  } else {
9122  /* Put in caller-id number and subaddress. */
9123  ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
9124  i->cid_subaddr, (unsigned)y);
9125  }
9126  ast_mutex_unlock(&i->pri->lock);
9127 #endif /* defined(HAVE_PRI) */
9128  } else {
9129  y = 1;
9130  do {
9131  ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
9132  for (x = 0; x < 3; ++x) {
9133  if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
9134  ast_channel_name(i->subs[x].owner) + 6)) {
9135  break;
9136  }
9137  }
9138  ++y;
9139  } while (x < 3);
9140  }
9141  return chan_name;
9142 }
char cid_subaddr[AST_MAX_EXTENSION]
Caller ID subaddress from an incoming call.
Definition: chan_dahdi.h:490
struct dahdi_subchannel subs[3]
Definition: chan_dahdi.h:131
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:714
#define CHAN_PSEUDO
Definition: chan_dahdi.c:556
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
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:1065
ast_mutex_t lock
Definition: chan_dahdi.h:125
long int ast_random(void)
Definition: main/utils.c:1934
struct ast_channel * owner
Definition: chan_dahdi.h:79
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
char cid_num[AST_MAX_EXTENSION]
Caller ID number from an incoming call.
Definition: chan_dahdi.h:479
#define ast_strlen_zero(a)
Definition: muted.c:73
const char * ast_channel_name(const struct ast_channel *chan)
int channel
Definition: chan_dahdi.h:538
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ dahdi_ami_channel_event()

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

Definition at line 1801 of file chan_dahdi.c.

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

Referenced by dahdi_new().

1802 {
1803  char ch_name[23];
1804 
1805  if (p->channel < CHAN_PSEUDO) {
1806  /* No B channel */
1807  snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
1808  } else if (p->channel == CHAN_PSEUDO) {
1809  /* Pseudo channel */
1810  strcpy(ch_name, "pseudo");
1811  } else {
1812  /* Real channel */
1813  snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
1814  }
1815  publish_dahdichannel(chan, p->group, p->span, ch_name);
1816 }
#define CHAN_PSEUDO
Definition: chan_dahdi.c:556
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:1772
ast_group_t group
Bitmapped groups this belongs to.
Definition: chan_dahdi.h:505
int channel
Definition: chan_dahdi.h:538

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

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.

Referenced by dahdi_chan_conf_default().

6410 {
6411  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
6412  int res = 0;
6413  int idx;
6414  ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
6415  ast_mutex_lock(&p->lock);
6416  idx = dahdi_get_index(ast, p, 0);
6417  if (idx < 0)
6418  idx = SUB_REAL;
6419  /* nothing to do if a radio channel */
6420  if ((p->radio || (p->oprmode < 0))) {
6421  ast_mutex_unlock(&p->lock);
6422  return 0;
6423  }
6424 
6425  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
6426  res = analog_answer(p->sig_pvt, ast);
6427  ast_mutex_unlock(&p->lock);
6428  return res;
6429  }
6430 
6431  switch (p->sig) {
6432 #if defined(HAVE_PRI)
6434  res = sig_pri_answer(p->sig_pvt, ast);
6435  break;
6436 #endif /* defined(HAVE_PRI) */
6437 #if defined(HAVE_SS7)
6438  case SIG_SS7:
6439  res = sig_ss7_answer(p->sig_pvt, ast);
6440  break;
6441 #endif /* defined(HAVE_SS7) */
6442 #ifdef HAVE_OPENR2
6443  case SIG_MFCR2:
6444  if (!p->mfcr2_call_accepted) {
6445  /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
6446  openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
6447  p->mfcr2_answer_pending = 1;
6448  if (p->mfcr2_charge_calls) {
6449  ast_debug(1, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
6450  openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
6451  } else {
6452  ast_debug(1, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
6453  openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
6454  }
6455  } else {
6456  ast_debug(1, "Answering MFC/R2 call on chan %d\n", p->channel);
6457  dahdi_r2_answer(p);
6458  }
6459  break;
6460 #endif
6461  case 0:
6462  ast_mutex_unlock(&p->lock);
6463  return 0;
6464  default:
6465  ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
6466  res = -1;
6467  break;
6468  }
6469  ast_mutex_unlock(&p->lock);
6470  return res;
6471 }
#define dahdi_get_index(ast, p, nullok)
Definition: chan_dahdi.h:827
void * ast_channel_tech_pvt(const struct ast_channel *chan)
static int dahdi_analog_lib_handles(int signalling, int radio, int oprmode)
Definition: chan_dahdi.h:786
#define LOG_WARNING
Definition: logger.h:274
void * sig_pvt
Definition: chan_dahdi.h:709
#define ast_mutex_lock(a)
Definition: lock.h:187
int oprmode
Definition: chan_dahdi.h:150
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
ast_mutex_t lock
Definition: chan_dahdi.h:125
#define SIG_SS7
Definition: chan_dahdi.h:750
int analog_answer(struct analog_pvt *p, struct ast_channel *ast)
Definition: sig_analog.c:1461
#define SUB_REAL
Definition: chan_dahdi.h:57
#define SIG_PRI_LIB_HANDLE_CASES
Definition: chan_dahdi.h:756
#define SIG_MFCR2
Definition: chan_dahdi.h:753
int sig_pri_answer(struct sig_pri_chan *p, struct ast_channel *ast)
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7325
int sig_ss7_answer(struct sig_ss7_chan *p, struct ast_channel *ast)
int radio
Nonzero if the signaling type is sent over a radio.
Definition: chan_dahdi.h:148
int channel
Definition: chan_dahdi.h:538
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ dahdi_call()

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

Definition at line 5121 of file chan_dahdi.c.

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.

Referenced by dahdi_chan_conf_default().

5122 {
5123  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5124  int x, res, mysig;
5125  char *dest;
5127  AST_APP_ARG(group); /* channel/group token */
5128  AST_APP_ARG(ext); /* extension token */
5129  //AST_APP_ARG(opts); /* options token */
5130  AST_APP_ARG(other); /* Any remining unused arguments */
5131  );
5132 
5133  ast_mutex_lock(&p->lock);
5134  ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
5135 
5136  /* Split the dialstring */
5137  dest = ast_strdupa(rdest);
5138  AST_NONSTANDARD_APP_ARGS(args, dest, '/');
5139  if (!args.ext) {
5140  args.ext = "";
5141  }
5142 
5143 #if defined(HAVE_PRI)
5144  if (dahdi_sig_pri_lib_handles(p->sig)) {
5145  char *subaddr;
5146 
5147  sig_pri_extract_called_num_subaddr(p->sig_pvt, rdest, p->exten, sizeof(p->exten));
5148 
5149  /* Remove any subaddress for uniformity with incoming calls. */
5150  subaddr = strchr(p->exten, ':');
5151  if (subaddr) {
5152  *subaddr = '\0';
5153  }
5154  } else
5155 #endif /* defined(HAVE_PRI) */
5156  {
5157  ast_copy_string(p->exten, args.ext, sizeof(p->exten));
5158  }
5159 
5160  if ((ast_channel_state(ast) == AST_STATE_BUSY)) {
5161  p->subs[SUB_REAL].needbusy = 1;
5162  ast_mutex_unlock(&p->lock);
5163  return 0;
5164  }
5165  if ((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) !=