chan_dahdi.c File Reference

DAHDI for Pseudo TDM. More...

#include "asterisk.h"
#include <sys/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/app.h"
#include "asterisk/dsp.h"
#include "asterisk/astdb.h"
#include "asterisk/manager.h"
#include "asterisk/causes.h"
#include "asterisk/term.h"
#include "asterisk/utils.h"
#include "asterisk/transcap.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/smdi.h"
#include "asterisk/devicestate.h"
#include "asterisk/paths.h"
#include "asterisk/ccss.h"
#include "asterisk/data.h"
#include "asterisk/features_config.h"
#include "asterisk/bridge.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/parking.h"
#include "asterisk/format_cache.h"
#include "chan_dahdi.h"
#include "dahdi/bridge_native_dahdi.h"

Include dependency graph for chan_dahdi.c:

Go to the source code of this file.

Data Structures

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

Defines

#define ASCII_BYTES_PER_CHAR   80
#define AST_LAW(p)   (((p)->law == DAHDI_LAW_ALAW) ? ast_format_alaw : ast_format_ulaw)
#define CALLPROGRESS_FAX   (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
#define CALLPROGRESS_FAX_INCOMING   4
#define CALLPROGRESS_FAX_OUTGOING   2
#define CALLPROGRESS_PROGRESS   1
#define CALLWAITING_REPEAT_SAMPLES   ((10000 * 8) / READ_SIZE)
#define CALLWAITING_SILENT_SAMPLES   ((300 * 8) / READ_SIZE)
#define CALLWAITING_SUPPRESS_SAMPLES   ((100 * 8) / READ_SIZE)
#define CANBUSYDETECT(p)   (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
#define CANPROGRESSDETECT(p)   (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
#define CHAN_PSEUDO   -2
#define CIDCW_EXPIRE_SAMPLES   ((500 * 8) / READ_SIZE)
#define DATA_EXPORT_DAHDI_PVT(MEMBER)
#define DEFAULT_CIDRINGS   1
 Typically, how many rings before we should send Caller*ID.
#define DEFAULT_DIALTONE_DETECT_TIMEOUT   ((10000 * 8) / READ_SIZE)
#define DEFAULT_RINGT   ((8000 * 8) / READ_SIZE)
#define END_SILENCE_LEN   400
#define FORMAT   "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
#define FORMAT   "%7s %-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 FORMAT2   "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
#define GET_CHANNEL(p)   ((p)->channel)
#define HANGUP   1
#define HEADER_LEN   ((HEADER_MS + TRAILER_MS) * 8)
#define HEADER_MS   50
#define ISTRUNK(p)
#define MASK_AVAIL   (1 << 0)
#define MASK_INUSE   (1 << 1)
#define MAX_CHANLIST_LEN   80
#define MIN_MS_SINCE_FLASH   ((2000) )
#define NEED_MFDETECT(p)   (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
 Signaling types that need to use MF detection should be placed in this macro.
#define NUM_CADENCE_MAX   25
#define NUM_SPANS   32
#define POLARITY_IDLE   0
#define POLARITY_REV   1
#define PROC_DAHDI_OPT_NOCHAN   (1 << 0)
#define PROC_DAHDI_OPT_NOWARN   (1 << 1)
#define READ_SIZE   160
#define REPORT_CHANNEL_ALARMS   1
#define REPORT_SPAN_ALARMS   2
#define sig2str   dahdi_sig2str
#define SMDI_MD_WAIT_TIMEOUT   1500
#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)
 AST_DATA_STRUCTURE (dahdi_pvt, DATA_EXPORT_DAHDI_PVT)
static int attempt_transfer (struct dahdi_pvt *p)
static int available (struct dahdi_pvt **pvt, int is_specific_channel)
static int build_channels (struct dahdi_chan_conf *conf, const char *value, int reload, int lineno)
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().
static struct dahdi_chan_conf dahdi_chan_conf_default (void)
static int dahdi_channels_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
static void dahdi_close (int fd)
static void dahdi_close_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
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.
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 int dahdi_status_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
static void dahdi_train_ec (struct dahdi_pvt *p)
static int dahdi_version_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
static int dahdi_wait_event (int fd)
 Avoid the silly dahdi_waitevent which ignores a bunch of events.
static int dahdi_wink (struct dahdi_pvt *p, int index)
static int dahdi_write (struct ast_channel *ast, struct ast_frame *frame)
static struct
ast_manager_event_blob
dahdichannel_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 device2chan (const char *subdir, int channel, char *path, int pathlen)
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)
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.
static struct dahdi_pvtmkintf (int channel, const struct dahdi_chan_conf *conf, int reloading)
static void monitor_pfds_clean (void *arg)
static void mwi_event_cb (void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
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.
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 char * parse_spanchan (char *chanstr, char **subdir)
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, int span, const char *dahdi_channel)
 Sends a DAHDIChannel channel blob used to produce DAHDIChannel AMI messages.
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)
 Start the channel monitor thread.
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 string_replace (char *str, int char1, int char2)
static void swap_subs (struct dahdi_pvt *p, int a, int b)
static int unalloc_sub (struct dahdi_pvt *p, int x)
static int unload_module (void)
static 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, .nonoptreq = "res_smdi", }
struct {
   int   alarm
   char *   name
alarms []
struct analog_callback analog_callbacks
static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}}
static struct ast_module_infoast_module_info = &__mod_info
static struct dahdi_ring_cadence cadences [NUM_CADENCE_MAX]
static int cidrings [NUM_CADENCE_MAX]
 cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on.
static const char config [] = "chan_dahdi.conf"
static struct ast_data_handler dahdi_channels_data_provider
static struct ast_cli_entry dahdi_cli []
static struct ast_data_entry dahdi_data_providers []
static struct ast_data_handler dahdi_status_data_provider
static struct ast_channel_tech dahdi_tech
static struct ast_data_handler dahdi_version_data_provider
static struct ast_jb_conf default_jbconf
static char defaultcic [64] = ""
static char defaultozz [64] = ""
static int distinctiveringaftercid = 0
static int dtmfcid_level = 256
static const char *const events []
static int firstdigittimeout = 16000
 Wait up to 16 seconds for first digit (FXO logic).
static int gendigittimeout = 8000
 How long to wait for following digits (FXO logic).
static struct ast_jb_conf global_jbconf
static int has_pseudo
static int ifcount = 0
static struct dahdi_pvtifend = NULL
static struct dahdi_pvtiflist = NULL
static ast_mutex_t iflock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
 Protect the interface list (of dahdi_pvt's).
static const char *const lbostr []
static int matchdigittimeout = 3000
 How long to wait for an extra digit, if there is an ambiguous match.
static pthread_t monitor_thread = AST_PTHREADT_NULL
 This is the thread for the monitor which checks for input on the channels which are not currently in use.
static ast_mutex_t monlock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
 Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
static int mwilevel = 512
static char mwimonitornotify [PATH_MAX] = ""
static int 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_MUTEX_INITIALIZER , NULL, 1 }
static int ringt_base = DEFAULT_RINGT
 Configured ring timeout base.
static struct dahdi_pvtround_robin [32]
static ast_cond_t ss_thread_complete
static int ss_thread_count = 0
static ast_mutex_t ss_thread_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
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 <markster@digium.com>
Connects to the DAHDI telephony library as well as libpri. Libpri is optional and needed only if you are going to use ISDN connections.

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

Todo:
Deprecate the "musiconhold" configuration option post 1.4

Definition in file chan_dahdi.c.


Define Documentation

#define ASCII_BYTES_PER_CHAR   80

Referenced by dahdi_sendtext().

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

#define CALLPROGRESS_FAX   (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)

Definition at line 504 of file chan_dahdi.c.

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

#define CALLPROGRESS_FAX_INCOMING   4

Definition at line 503 of file chan_dahdi.c.

Referenced by dahdi_new(), and process_dahdi().

#define CALLPROGRESS_FAX_OUTGOING   2

Definition at line 502 of file chan_dahdi.c.

Referenced by dahdi_new(), and process_dahdi().

#define CALLPROGRESS_PROGRESS   1

Definition at line 501 of file chan_dahdi.c.

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

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

10,000 ms

Definition at line 639 of file chan_dahdi.c.

Referenced by dahdi_callwait(), and my_callwait().

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

300 ms

Definition at line 638 of file chan_dahdi.c.

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

100 ms

Definition at line 640 of file chan_dahdi.c.

Referenced by send_callerid().

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

Definition at line 536 of file chan_dahdi.c.

Referenced by dahdi_new().

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

#define CHAN_PSEUDO   -2

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

500 ms

Definition at line 641 of file chan_dahdi.c.

Referenced by send_callerid().

#define DATA_EXPORT_DAHDI_PVT ( MEMBER   ) 

Definition at line 752 of file chan_dahdi.c.

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

Referenced by dahdi_chan_conf_default().

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

10,000 ms

Definition at line 644 of file chan_dahdi.c.

Referenced by process_dahdi().

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

8,000 ms

Definition at line 643 of file chan_dahdi.c.

#define END_SILENCE_LEN   400

Referenced by dahdi_sendtext().

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

#define FORMAT   "%7s %-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 FORMAT2   "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"

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

Definition at line 1073 of file chan_dahdi.c.

Referenced by dahdi_conf_update(), and my_complete_conference_update().

#define HANGUP   1

Definition at line 15907 of file chan_dahdi.c.

Referenced by action_transferhangup(), and dahdi_fake_event().

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

#define HEADER_MS   50

Referenced by dahdi_sendtext().

#define ISTRUNK (  ) 

Value:

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

Definition at line 533 of file chan_dahdi.c.

Referenced by __analog_ss_thread(), analog_ss_thread(), and dahdi_indicate().

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 635 of file chan_dahdi.c.

#define MASK_INUSE   (1 << 1)

Channel currently in use

Definition at line 636 of file chan_dahdi.c.

#define MAX_CHANLIST_LEN   80

The length of the parameters list of 'dahdichan'.

Todo:
Move definition of MAX_CHANLIST_LEN to a proper place.

Definition at line 17441 of file chan_dahdi.c.

#define MIN_MS_SINCE_FLASH   ((2000) )

2000 ms

Definition at line 642 of file chan_dahdi.c.

Referenced by __analog_handle_event(), and dahdi_handle_event().

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

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

Definition at line 468 of file chan_dahdi.c.

Referenced by analog_ss_thread(), and dahdi_new().

#define NUM_CADENCE_MAX   25

Definition at line 506 of file chan_dahdi.c.

Referenced by process_dahdi().

#define NUM_SPANS   32

Definition at line 496 of file chan_dahdi.c.

#define POLARITY_IDLE   0

#define POLARITY_REV   1

#define PROC_DAHDI_OPT_NOCHAN   (1 << 0)

process_dahdi() - ignore keyword 'channel' and similar

Definition at line 17576 of file chan_dahdi.c.

Referenced by process_dahdi(), and setup_dahdi_int().

#define PROC_DAHDI_OPT_NOWARN   (1 << 1)

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

Definition at line 17578 of file chan_dahdi.c.

Referenced by process_dahdi(), and setup_dahdi_int().

#define READ_SIZE   160

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

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

#define REPORT_CHANNEL_ALARMS   1

Definition at line 558 of file chan_dahdi.c.

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

#define REPORT_SPAN_ALARMS   2

Definition at line 559 of file chan_dahdi.c.

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

#define sig2str   dahdi_sig2str

#define SMDI_MD_WAIT_TIMEOUT   1500

Definition at line 425 of file chan_dahdi.c.

Referenced by analog_ss_thread().

#define TRAILER_MS   5

Referenced by dahdi_sendtext().

#define TRANSFER   0


Function Documentation

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

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

08178 {
08179    int res;
08180    int idx;
08181    struct ast_frame *f;
08182    int usedindex = -1;
08183    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
08184 
08185    if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
08186       idx = SUB_REAL;
08187    }
08188 
08189    p->subs[idx].f.frametype = AST_FRAME_NULL;
08190    p->subs[idx].f.datalen = 0;
08191    p->subs[idx].f.samples = 0;
08192    p->subs[idx].f.mallocd = 0;
08193    p->subs[idx].f.offset = 0;
08194    p->subs[idx].f.subclass.integer = 0;
08195    p->subs[idx].f.delivery = ast_tv(0,0);
08196    p->subs[idx].f.src = "dahdi_exception";
08197    p->subs[idx].f.data.ptr = NULL;
08198 
08199 
08200    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08201       /* If nobody owns us, absorb the event appropriately, otherwise
08202          we loop indefinitely.  This occurs when, during call waiting, the
08203          other end hangs up our channel so that it no longer exists, but we
08204          have neither FLASH'd nor ONHOOK'd to signify our desire to
08205          change to the other channel. */
08206       if (p->fake_event) {
08207          res = p->fake_event;
08208          p->fake_event = 0;
08209       } else
08210          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08211       /* Switch to real if there is one and this isn't something really silly... */
08212       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08213          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08214          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08215          p->owner = p->subs[SUB_REAL].owner;
08216          if (p->owner) {
08217             ast_queue_unhold(p->owner);
08218          }
08219          p->subs[SUB_REAL].needunhold = 1;
08220       }
08221       switch (res) {
08222       case DAHDI_EVENT_ONHOOK:
08223          dahdi_ec_disable(p);
08224          if (p->owner) {
08225             ast_verb(3, "Channel %s still has call, ringing phone\n", ast_channel_name(p->owner));
08226             dahdi_ring_phone(p);
08227             p->callwaitingrepeat = 0;
08228             p->cidcwexpire = 0;
08229             p->cid_suppress_expire = 0;
08230          } else
08231             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08232          dahdi_conf_update(p);
08233          break;
08234       case DAHDI_EVENT_RINGOFFHOOK:
08235          dahdi_ec_enable(p);
08236          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08237          if (p->owner && (ast_channel_state(p->owner) == AST_STATE_RINGING)) {
08238             p->subs[SUB_REAL].needanswer = 1;
08239             p->dialing = 0;
08240          }
08241          break;
08242       case DAHDI_EVENT_HOOKCOMPLETE:
08243       case DAHDI_EVENT_RINGERON:
08244       case DAHDI_EVENT_RINGEROFF:
08245          /* Do nothing */
08246          break;
08247       case DAHDI_EVENT_WINKFLASH:
08248          p->flashtime = ast_tvnow();
08249          if (p->owner) {
08250             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, ast_channel_name(p->owner));
08251             if (ast_channel_state(p->owner) != AST_STATE_UP) {
08252                /* Answer if necessary */
08253                usedindex = dahdi_get_index(p->owner, p, 0);
08254                if (usedindex > -1) {
08255                   p->subs[usedindex].needanswer = 1;
08256                }
08257                ast_setstate(p->owner, AST_STATE_UP);
08258             }
08259             p->callwaitingrepeat = 0;
08260             p->cidcwexpire = 0;
08261             p->cid_suppress_expire = 0;
08262             ast_queue_unhold(p->owner);
08263             p->subs[SUB_REAL].needunhold = 1;
08264          } else
08265             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08266          dahdi_conf_update(p);
08267          break;
08268       default:
08269          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08270       }
08271       f = &p->subs[idx].f;
08272       return f;
08273    }
08274    if (!(p->radio || (p->oprmode < 0)))
08275       ast_debug(1, "Exception on %d, channel %d\n", ast_channel_fd(ast, 0), p->channel);
08276    /* If it's not us, return NULL immediately */
08277    if (ast != p->owner) {
08278       if (p->owner) {
08279          ast_log(LOG_WARNING, "We're %s, not %s\n", ast_channel_name(ast), ast_channel_name(p->owner));
08280       }
08281       f = &p->subs[idx].f;
08282       return f;
08283    }
08284 
08285    f = dahdi_handle_event(ast);
08286    if (!f) {
08287       const char *name = ast_strdupa(ast_channel_name(ast));
08288 
08289       /* Tell the CDR this DAHDI device hung up */
08290       ast_mutex_unlock(&p->lock);
08291       ast_channel_unlock(ast);
08292       ast_set_hangupsource(ast, name, 0);
08293       ast_channel_lock(ast);
08294       ast_mutex_lock(&p->lock);
08295    }
08296    return f;
08297 }

static void __reg_module ( void   )  [static]

Definition at line 19753 of file chan_dahdi.c.

static int __unload_module ( void   )  [static]

Definition at line 17212 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_data_unregister, ast_manager_unregister(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_unregister_application(), ast_channel_tech::capabilities, dahdi_native_unload(), destroy_all_channels(), iflock, sig_ss7_linkset::master, sig_pri_span::master, monlock, dahdi_pvt::next, NULL, dahdi_pvt::owner, sig_pri_stop_pri(), sig_pri_unload(), SIG_SS7_NUM_DCHANS, sig_ss7_linkset::ss7, and STASIS_MESSAGE_TYPE_CLEANUP.

Referenced by load_module(), and unload_module().

17213 {
17214    struct dahdi_pvt *p;
17215 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17216    int i, j;
17217 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
17218 
17219 #ifdef HAVE_PRI
17220    for (i = 0; i < NUM_SPANS; i++) {
17221       if (pris[i].pri.master != AST_PTHREADT_NULL) {
17222          pthread_cancel(pris[i].pri.master);
17223          pthread_kill(pris[i].pri.master, SIGURG);
17224       }
17225    }
17226    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
17227    ast_unregister_application(dahdi_send_keypad_facility_app);
17228 #ifdef HAVE_PRI_PROG_W_CAUSE
17229    ast_unregister_application(dahdi_send_callrerouting_facility_app);
17230 #endif
17231 #endif
17232 #if defined(HAVE_SS7)
17233    for (i = 0; i < NUM_SPANS; i++) {
17234       if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
17235          pthread_cancel(linksets[i].ss7.master);
17236          pthread_kill(linksets[i].ss7.master, SIGURG);
17237       }
17238    }
17239    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
17240 #endif   /* defined(HAVE_SS7) */
17241 #if defined(HAVE_OPENR2)
17242    dahdi_r2_destroy_links();
17243    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
17244    ast_unregister_application(dahdi_accept_r2_call_app);
17245 #endif
17246 
17247    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
17248    ast_manager_unregister("DAHDIDialOffhook");
17249    ast_manager_unregister("DAHDIHangup");
17250    ast_manager_unregister("DAHDITransfer");
17251    ast_manager_unregister("DAHDIDNDoff");
17252    ast_manager_unregister("DAHDIDNDon");
17253    ast_manager_unregister("DAHDIShowChannels");
17254    ast_manager_unregister("DAHDIRestart");
17255 #if defined(HAVE_PRI)
17256    ast_manager_unregister("PRIShowSpans");
17257    ast_manager_unregister("PRIDebugSet");
17258    ast_manager_unregister("PRIDebugFileSet");
17259    ast_manager_unregister("PRIDebugFileUnset");
17260 #endif   /* defined(HAVE_PRI) */
17261    ast_data_unregister(NULL);
17262    ast_channel_unregister(&dahdi_tech);
17263 
17264    /* Hangup all interfaces if they have an owner */
17265    ast_mutex_lock(&iflock);
17266    for (p = iflist; p; p = p->next) {
17267       if (p->owner)
17268          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
17269    }
17270    ast_mutex_unlock(&iflock);
17271 
17272    ast_mutex_lock(&monlock);
17273    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
17274       pthread_cancel(monitor_thread);
17275       pthread_kill(monitor_thread, SIGURG);
17276       pthread_join(monitor_thread, NULL);
17277    }
17278    monitor_thread = AST_PTHREADT_STOP;
17279    ast_mutex_unlock(&monlock);
17280 
17281    destroy_all_channels();
17282 
17283 #if defined(HAVE_PRI)
17284    for (i = 0; i < NUM_SPANS; i++) {
17285       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
17286          pthread_join(pris[i].pri.master, NULL);
17287       }
17288       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
17289          dahdi_close_pri_fd(&(pris[i]), j);
17290       }
17291       sig_pri_stop_pri(&pris[i].pri);
17292    }
17293 #if defined(HAVE_PRI_CCSS)
17294    ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
17295    ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
17296 #endif   /* defined(HAVE_PRI_CCSS) */
17297    sig_pri_unload();
17298 #endif
17299 
17300 #if defined(HAVE_SS7)
17301    for (i = 0; i < NUM_SPANS; i++) {
17302       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
17303          pthread_join(linksets[i].ss7.master, NULL);
17304       }
17305       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
17306          dahdi_close_ss7_fd(&(linksets[i]), j);
17307       }
17308       if (linksets[i].ss7.ss7) {
17309          ss7_destroy(linksets[i].ss7.ss7);
17310          linksets[i].ss7.ss7 = NULL;
17311       }
17312    }
17313 #endif   /* defined(HAVE_SS7) */
17314    ast_cond_destroy(&ss_thread_complete);
17315 
17316    dahdi_native_unload();
17317 
17318    ao2_cleanup(dahdi_tech.capabilities);
17319    dahdi_tech.capabilities = NULL;
17320    STASIS_MESSAGE_TYPE_CLEANUP(dahdichannel_type);
17321    return 0;
17322 }

static void __unreg_module ( void   )  [static]

Definition at line 19753 of file chan_dahdi.c.

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

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

03431 {
03432    int res;
03433    if (p->subs[SUB_REAL].owner == ast)
03434       res = 0;
03435    else if (p->subs[SUB_CALLWAIT].owner == ast)
03436       res = 1;
03437    else if (p->subs[SUB_THREEWAY].owner == ast)
03438       res = 2;
03439    else {
03440       res = -1;
03441       if (!nullok)
03442          ast_log(LOG_WARNING,
03443             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03444             ast ? ast_channel_name(ast) : "", p->channel, fname, line);
03445    }
03446    return res;
03447 }

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

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

16045 {
16046    struct dahdi_pvt *p;
16047    const char *channel = astman_get_header(m, "DAHDIChannel");
16048    const char *number = astman_get_header(m, "Number");
16049    int i;
16050 
16051    if (ast_strlen_zero(channel)) {
16052       astman_send_error(s, m, "No channel specified");
16053       return 0;
16054    }
16055    if (ast_strlen_zero(number)) {
16056       astman_send_error(s, m, "No number specified");
16057       return 0;
16058    }
16059    p = find_channel_from_str(channel);
16060    if (!p) {
16061       astman_send_error(s, m, "No such channel");
16062       return 0;
16063    }
16064    if (!p->owner) {
16065       astman_send_error(s, m, "Channel does not have it's owner");
16066       return 0;
16067    }
16068    for (i = 0; i < strlen(number); i++) {
16069       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16070       dahdi_queue_frame(p, &f);
16071    }
16072    astman_send_ack(s, m, "DAHDIDialOffhook");
16073    return 0;
16074 }

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

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

15980 {
15981    struct dahdi_pvt *p;
15982    const char *channel = astman_get_header(m, "DAHDIChannel");
15983 
15984    if (ast_strlen_zero(channel)) {
15985       astman_send_error(s, m, "No channel specified");
15986       return 0;
15987    }
15988    p = find_channel_from_str(channel);
15989    if (!p) {
15990       astman_send_error(s, m, "No such channel");
15991       return 0;
15992    }
15993    dahdi_dnd(p, 0);
15994    astman_send_ack(s, m, "DND Disabled");
15995    return 0;
15996 }

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

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

15961 {
15962    struct dahdi_pvt *p;
15963    const char *channel = astman_get_header(m, "DAHDIChannel");
15964 
15965    if (ast_strlen_zero(channel)) {
15966       astman_send_error(s, m, "No channel specified");
15967       return 0;
15968    }
15969    p = find_channel_from_str(channel);
15970    if (!p) {
15971       astman_send_error(s, m, "No such channel");
15972       return 0;
15973    }
15974    dahdi_dnd(p, 1);
15975    astman_send_ack(s, m, "DND Enabled");
15976    return 0;
15977 }

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

Definition at line 15234 of file chan_dahdi.c.

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

Referenced by load_module().

15235 {
15236    if (dahdi_restart() != 0) {
15237       astman_send_error(s, m, "Failed rereading DAHDI configuration");
15238       return 1;
15239    }
15240    astman_send_ack(s, m, "DAHDIRestart: Success");
15241    return 0;
15242 }

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

Definition at line 16076 of file chan_dahdi.c.

References alarm2str(), ast_channel_accountcode(), ast_channel_name(), ast_channel_uniqueid(), ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero, astman_append(), astman_get_header(), astman_send_list_complete_end(), astman_send_list_complete_start(), astman_send_listack(), dahdi_pvt::channel, dahdi_pvt::context, dahdi_dnd(), dahdi_pvt::description, get_alarms(), iflock, dahdi_pvt::next, NULL, dahdi_pvt::owner, dahdi_pvt::sig, and sig2str.

Referenced by load_module().

16077 {
16078    struct dahdi_pvt *tmp = NULL;
16079    const char *id = astman_get_header(m, "ActionID");
16080    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16081    char idText[256];
16082    int channels = 0;
16083    int dahdichanquery;
16084 
16085    if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16086       /* Not numeric string. */
16087       dahdichanquery = -1;
16088    }
16089 
16090    idText[0] = '\0';
16091    if (!ast_strlen_zero(id)) {
16092       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16093    }
16094 
16095    astman_send_listack(s, m, "DAHDI channel status will follow", "start");
16096 
16097    ast_mutex_lock(&iflock);
16098 
16099    for (tmp = iflist; tmp; tmp = tmp->next) {
16100       if (tmp->channel > 0) {
16101          int alm;
16102 
16103          /* If a specific channel is queried for, only deliver status for that channel */
16104          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16105             continue;
16106 
16107          alm = get_alarms(tmp);
16108          channels++;
16109          if (tmp->owner) {
16110             /* Add data if we have a current call */
16111             astman_append(s,
16112                "Event: DAHDIShowChannels\r\n"
16113                "DAHDIChannel: %d\r\n"
16114                "Channel: %s\r\n"
16115                "Uniqueid: %s\r\n"
16116                "AccountCode: %s\r\n"
16117                "Signalling: %s\r\n"
16118                "SignallingCode: %d\r\n"
16119                "Context: %s\r\n"
16120                "DND: %s\r\n"
16121                "Alarm: %s\r\n"
16122                "Description: %s\r\n"
16123                "%s"
16124                "\r\n",
16125                tmp->channel,
16126                ast_channel_name(tmp->owner),
16127                ast_channel_uniqueid(tmp->owner),
16128                ast_channel_accountcode(tmp->owner),
16129                sig2str(tmp->sig),
16130                tmp->sig,
16131                tmp->context,
16132                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16133                alarm2str(alm),
16134                tmp->description, idText);
16135          } else {
16136             astman_append(s,
16137                "Event: DAHDIShowChannels\r\n"
16138                "DAHDIChannel: %d\r\n"
16139                "Signalling: %s\r\n"
16140                "SignallingCode: %d\r\n"
16141                "Context: %s\r\n"
16142                "DND: %s\r\n"
16143                "Alarm: %s\r\n"
16144                "Description: %s\r\n"
16145                "%s"
16146                "\r\n",
16147                tmp->channel, sig2str(tmp->sig), tmp->sig,
16148                tmp->context,
16149                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16150                alarm2str(alm),
16151                tmp->description, idText);
16152          }
16153       }
16154    }
16155 
16156    ast_mutex_unlock(&iflock);
16157 
16158    astman_send_list_complete_start(s, m, "DAHDIShowChannelsComplete", channels);
16159    astman_append(s, "Items: %d\r\n", channels);
16160    astman_send_list_complete_end(s);
16161    return 0;
16162 }

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

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

15999 {
16000    struct dahdi_pvt *p;
16001    const char *channel = astman_get_header(m, "DAHDIChannel");
16002 
16003    if (ast_strlen_zero(channel)) {
16004       astman_send_error(s, m, "No channel specified");
16005       return 0;
16006    }
16007    p = find_channel_from_str(channel);
16008    if (!p) {
16009       astman_send_error(s, m, "No such channel");
16010       return 0;
16011    }
16012    if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16013       astman_send_error(s, m, "Channel signaling is not analog");
16014       return 0;
16015    }
16016    dahdi_fake_event(p,TRANSFER);
16017    astman_send_ack(s, m, "DAHDITransfer");
16018    return 0;
16019 }

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

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

16022 {
16023    struct dahdi_pvt *p;
16024    const char *channel = astman_get_header(m, "DAHDIChannel");
16025 
16026    if (ast_strlen_zero(channel)) {
16027       astman_send_error(s, m, "No channel specified");
16028       return 0;
16029    }
16030    p = find_channel_from_str(channel);
16031    if (!p) {
16032       astman_send_error(s, m, "No such channel");
16033       return 0;
16034    }
16035    if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16036       astman_send_error(s, m, "Channel signaling is not analog");
16037       return 0;
16038    }
16039    dahdi_fake_event(p,HANGUP);
16040    astman_send_ack(s, m, "DAHDIHangup");
16041    return 0;
16042 }

static char* alarm2str ( int  alm  )  [static]

Definition at line 4328 of file chan_dahdi.c.

References alarms, and ARRAY_LEN.

Referenced by action_dahdishowchannels(), and handle_alarms().

04329 {
04330    int x;
04331    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04332       if (alarms[x].alarm & alm)
04333          return alarms[x].name;
04334    }
04335    return alm ? "Unknown Alarm" : "No Alarm";
04336 }

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

Definition at line 4135 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, and dahdi_pvt::subs.

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

04136 {
04137    struct dahdi_bufferinfo bi;
04138    int res;
04139    if (p->subs[x].dfd >= 0) {
04140       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04141       return -1;
04142    }
04143 
04144    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04145    if (p->subs[x].dfd <= -1) {
04146       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04147       return -1;
04148    }
04149 
04150    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04151    if (!res) {
04152       bi.txbufpolicy = p->buf_policy;
04153       bi.rxbufpolicy = p->buf_policy;
04154       bi.numbufs = p->buf_no;
04155       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04156       if (res < 0) {
04157          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04158       }
04159    } else
04160       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04161 
04162    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04163       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04164       dahdi_close_sub(p, x);
04165       p->subs[x].dfd = -1;
04166       return -1;
04167    }
04168    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04169    return 0;
04170 }

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

Definition at line 9384 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(), 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(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, dahdi_pvt::dop, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, errno, event2str(), ast_frame::frametype, func, 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, ISTRUNK, len(), dahdi_subchannel::linear, dahdi_pvt::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, my_getsigstr(), my_handle_notify_message(), name, NEED_MFDETECT, NULL, dahdi_pvt::owner, dahdi_subchannel::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_lock, strsep(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, ast_frame::subclass, dahdi_pvt::subs, swap_subs(), dahdi_pvt::transfer, ast_smdi_md_message::type, unalloc_sub(), dahdi_pvt::use_callerid, dahdi_pvt::use_smdi, and dahdi_pvt::usedistinctiveringdetection.

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

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

static int analog_tone_to_dahditone ( enum analog_tone  tone  )  [static]

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

01127 {
01128    switch (tone) {
01129    case ANALOG_TONE_RINGTONE:
01130       return DAHDI_TONE_RINGTONE;
01131    case ANALOG_TONE_STUTTER:
01132       return DAHDI_TONE_STUTTER;
01133    case ANALOG_TONE_CONGESTION:
01134       return DAHDI_TONE_CONGESTION;
01135    case ANALOG_TONE_DIALTONE:
01136       return DAHDI_TONE_DIALTONE;
01137    case ANALOG_TONE_DIALRECALL:
01138       return DAHDI_TONE_DIALRECALL;
01139    case ANALOG_TONE_INFO:
01140       return DAHDI_TONE_INFO;
01141    default:
01142       return -1;
01143    }
01144 }

static int analogsub_to_dahdisub ( enum analog_sub  analogsub  )  [static]

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

01147 {
01148    int index;
01149 
01150    switch (analogsub) {
01151    case ANALOG_SUB_REAL:
01152       index = SUB_REAL;
01153       break;
01154    case ANALOG_SUB_CALLWAIT:
01155       index = SUB_CALLWAIT;
01156       break;
01157    case ANALOG_SUB_THREEWAY:
01158       index = SUB_THREEWAY;
01159       break;
01160    default:
01161       ast_log(LOG_ERROR, "Unidentified sub!\n");
01162       index = SUB_REAL;
01163    }
01164 
01165    return index;
01166 }

AST_DATA_STRUCTURE ( dahdi_pvt  ,
DATA_EXPORT_DAHDI_PVT   
)

static int attempt_transfer ( struct dahdi_pvt p  )  [static]

Definition at line 7051 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 close_call(), dahdi_handle_event(), and handle_request().

07052 {
07053    struct ast_channel *owner_real;
07054    struct ast_channel *owner_3way;
07055    enum ast_transfer_result xfer_res;
07056    int res = 0;
07057 
07058    owner_real = ast_channel_ref(p->subs[SUB_REAL].owner);
07059    owner_3way = ast_channel_ref(p->subs[SUB_THREEWAY].owner);
07060 
07061    ast_verb(3, "TRANSFERRING %s to %s\n",
07062       ast_channel_name(owner_3way), ast_channel_name(owner_real));
07063 
07064    ast_channel_unlock(owner_real);
07065    ast_channel_unlock(owner_3way);
07066    ast_mutex_unlock(&p->lock);
07067 
07068    xfer_res = ast_bridge_transfer_attended(owner_3way, owner_real);
07069    if (xfer_res != AST_BRIDGE_TRANSFER_SUCCESS) {
07070       ast_softhangup(owner_3way, AST_SOFTHANGUP_DEV);
07071       res = -1;
07072    }
07073 
07074    /* Must leave with these locked. */
07075    ast_channel_lock(owner_real);
07076    ast_mutex_lock(&p->lock);
07077 
07078    ast_channel_unref(owner_real);
07079    ast_channel_unref(owner_3way);
07080 
07081    return res;
07082 }

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

Definition at line 12898 of file chan_dahdi.c.

References analog_available(), sig_pri_chan::chan_pvt, dahdi_analog_lib_handles(), dahdi_pvt::inalarm, dahdi_pvt::locallyblocked, dahdi_pvt::oprmode, dahdi_pvt::owner, dahdi_pvt::radio, dahdi_pvt::remotelyblocked, dahdi_pvt::sig, sig_pri_available(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, and sig_ss7_available().

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

12899 {
12900    struct dahdi_pvt *p = *pvt;
12901 
12902    if (p->inalarm)
12903       return 0;
12904 
12905    if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode))
12906       return analog_available(p->sig_pvt);
12907 
12908    switch (p->sig) {
12909 #if defined(HAVE_PRI)
12910    case SIG_PRI_LIB_HANDLE_CASES:
12911       {
12912          struct sig_pri_chan *pvt_chan;
12913          int res;
12914 
12915          pvt_chan = p->sig_pvt;
12916          res = sig_pri_available(&pvt_chan, is_specific_channel);
12917          *pvt = pvt_chan->chan_pvt;
12918          return res;
12919       }
12920 #endif   /* defined(HAVE_PRI) */
12921 #if defined(HAVE_SS7)
12922    case SIG_SS7:
12923       return sig_ss7_available(p->sig_pvt);
12924 #endif   /* defined(HAVE_SS7) */
12925    default:
12926       break;
12927    }
12928 
12929    if (p->locallyblocked || p->remotelyblocked) {
12930       return 0;
12931    }
12932 
12933    /* If no owner definitely available */
12934    if (!p->owner) {
12935 #ifdef HAVE_OPENR2
12936       /* Trust MFC/R2 */
12937       if (p->mfcr2) {
12938          if (p->mfcr2call) {
12939             return 0;
12940          } else {
12941             return 1;
12942          }
12943       }
12944 #endif
12945       return 1;
12946    }
12947 
12948    return 0;
12949 }

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

Definition at line 17363 of file chan_dahdi.c.

References ast_log, ast_strdupa, ast_strlen_zero, ast_verb, dahdi_chan_conf::chan, CHAN_PSEUDO, device2chan(), dahdi_chan_conf::ignore_failed_channels, dahdi_chan_conf::is_sig_auto, LOG_ERROR, LOG_WARNING, mkintf(), parse_spanchan(), dahdi_pvt::sig, sig2str, strsep(), dahdi_chan_conf::wanted_channels_end, and dahdi_chan_conf::wanted_channels_start.

Referenced by process_dahdi().

17364 {
17365    char *c, *chan;
17366    char *subdir;
17367    int x, start, finish;
17368    struct dahdi_pvt *tmp;
17369 
17370    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
17371       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
17372       return -1;
17373    }
17374 
17375    c = ast_strdupa(value);
17376    c = parse_spanchan(c, &subdir);
17377 
17378    while ((chan = strsep(&c, ","))) {
17379       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
17380          /* Range */
17381       } else if (sscanf(chan, "%30d", &start)) {
17382          /* Just one */
17383          finish = start;
17384       } else if (!strcasecmp(chan, "pseudo")) {
17385          finish = start = CHAN_PSEUDO;
17386       } else {
17387          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
17388          return -1;
17389       }
17390       if (finish < start) {
17391          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
17392          x = finish;
17393          finish = start;
17394          start = x;
17395       }
17396 
17397       for (x = start; x <= finish; x++) {
17398          char fn[PATH_MAX];
17399          int real_channel = x;
17400 
17401          if (!ast_strlen_zero(subdir)) {
17402             real_channel = device2chan(subdir, x, fn, sizeof(fn));
17403             if (real_channel < 0) {
17404                if (conf->ignore_failed_channels) {
17405                   ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
17406                         subdir, x, real_channel);
17407                   continue;
17408                } else {
17409                   ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
17410                         subdir, x, real_channel);
17411                   return -1;
17412                }
17413             }
17414          }
17415          if (conf->wanted_channels_start &&
17416             (real_channel < conf->wanted_channels_start ||
17417              real_channel > conf->wanted_channels_end)
17418             ) {
17419             continue;
17420          }
17421          tmp = mkintf(real_channel, conf, reload);
17422 
17423          if (tmp) {
17424             ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
17425          } else {
17426             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
17427                   (reload == 1) ? "reconfigure" : "register", value);
17428             return -1;
17429          }
17430          if (real_channel == CHAN_PSEUDO) {
17431             has_pseudo = 1;
17432          }
17433       }
17434    }
17435 
17436    return 0;
17437 }

static int bump_gains ( struct dahdi_pvt p  )  [static]

Definition at line 4851 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(), mwi_thread(), and my_start_cid_detect().

04852 {
04853    int res;
04854 
04855    /* Bump receive gain by value stored in cid_rxgain */
04856    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
04857    if (res) {
04858       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
04859       return -1;
04860    }
04861 
04862    return 0;
04863 }

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

Definition at line 10580 of file chan_dahdi.c.

References abs, AST_ALAW, ast_format_ulaw, and AST_MULAW.

Referenced by do_monitor(), and mwi_thread().

10581 {
10582    int x;
10583    int sum = 0;
10584 
10585    if (!len)
10586       return 0;
10587 
10588    for (x = 0; x < len; x++)
10589       sum += abs(law == ast_format_ulaw ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
10590 
10591    return sum / len;
10592 }

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

Definition at line 9357 of file chan_dahdi.c.

Referenced by analog_ss_thread().

09358 {
09359    int extlen = strlen(exten);
09360 
09361    if (!extlen) {
09362       return 1;
09363    }
09364 
09365    if (extlen < strlen(pickupexten) && !strncmp(pickupexten, exten, extlen)) {
09366       return 1;
09367    }
09368    /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
09369    if (exten[0] == '*' && extlen < 3) {
09370       if (extlen == 1) {
09371          return 1;
09372       }
09373       /* "*0" should be processed before it gets here */
09374       switch (exten[1]) {
09375       case '6':
09376       case '7':
09377       case '8':
09378          return 1;
09379       }
09380    }
09381    return 0;
09382 }

static int check_for_conference ( struct dahdi_pvt p  )  [static]

Definition at line 7084 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(), and my_check_for_conference().

07085 {
07086    struct dahdi_confinfo ci;
07087    /* Fine if we already have a master, etc */
07088    if (p->master || (p->confno > -1))
07089       return 0;
07090    memset(&ci, 0, sizeof(ci));
07091    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07092       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07093       return 0;
07094    }
07095    /* If we have no master and don't have a confno, then
07096       if we're in a conference, it's probably a MeetMe room or
07097       some such, so don't let us 3-way out! */
07098    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07099       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07100       return 1;
07101    }
07102    return 0;
07103 }

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

Definition at line 4413 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(), and my_conf_add().

04414 {
04415    /* If the conference already exists, and we're already in it
04416       don't bother doing anything */
04417    struct dahdi_confinfo zi;
04418 
04419    memset(&zi, 0, sizeof(zi));
04420    zi.chan = 0;
04421 
04422    if (slavechannel > 0) {
04423       /* If we have only one slave, do a digital mon */
04424       zi.confmode = DAHDI_CONF_DIGITALMON;
04425       zi.confno = slavechannel;
04426    } else {
04427       if (!idx) {
04428          /* Real-side and pseudo-side both participate in conference */
04429          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04430             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04431       } else
04432          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04433       zi.confno = p->confno;
04434    }
04435    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04436       return 0;
04437    if (c->dfd < 0)
04438       return 0;
04439    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04440       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04441       return -1;
04442    }
04443    if (slavechannel < 1) {
04444       p->confno = zi.confno;
04445    }
04446    c->curconf = zi;
04447    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04448    return 0;
04449 }

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

Definition at line 4462 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(), and my_conf_del().

04463 {
04464    struct dahdi_confinfo zi;
04465    if (/* Can't delete if there's no dfd */
04466       (c->dfd < 0) ||
04467       /* Don't delete from the conference if it's not our conference */
04468       !isourconf(p, c)
04469       /* Don't delete if we don't think it's conferenced at all (implied) */
04470       ) return 0;
04471    memset(&zi, 0, sizeof(zi));
04472    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04473       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04474       return -1;
04475    }
04476    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04477    memcpy(&c->curconf, &zi, sizeof(c->curconf));
04478    return 0;
04479 }

static struct ast_str* create_channel_name ( struct dahdi_pvt i  )  [static, read]

Definition at line 8971 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(), and dahdi_new().

08973 {
08974    struct ast_str *chan_name;
08975    int x, y;
08976 
08977    /* Create the new channel name tail. */
08978    if (!(chan_name = ast_str_create(32))) {
08979       return NULL;
08980    }
08981    if (i->channel == CHAN_PSEUDO) {
08982       ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
08983 #if defined(HAVE_PRI)
08984    } else if (i->pri) {
08985       ast_mutex_lock(&i->pri->lock);
08986       y = ++i->pri->new_chan_seq;
08987       if (is_outgoing) {
08988          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, (unsigned)y);
08989          address[0] = '\0';
08990       } else if (ast_strlen_zero(i->cid_subaddr)) {
08991          /* Put in caller-id number only since there is no subaddress. */
08992          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, (unsigned)y);
08993       } else {
08994          /* Put in caller-id number and subaddress. */
08995          ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
08996             i->cid_subaddr, (unsigned)y);
08997       }
08998       ast_mutex_unlock(&i->pri->lock);
08999 #endif   /* defined(HAVE_PRI) */
09000    } else {
09001       y = 1;
09002       do {
09003          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09004          for (x = 0; x < 3; ++x) {
09005             if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09006                ast_channel_name(i->subs[x].owner) + 6)) {
09007                break;
09008             }
09009          }
09010          ++y;
09011       } while (x < 3);
09012    }
09013    return chan_name;
09014 }

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

Definition at line 1815 of file chan_dahdi.c.

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

Referenced by dahdi_new().

01816 {
01817    char ch_name[20];
01818 
01819    if (p->channel < CHAN_PSEUDO) {
01820       /* No B channel */
01821       snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
01822    } else if (p->channel == CHAN_PSEUDO) {
01823       /* Pseudo channel */
01824       strcpy(ch_name, "pseudo");
01825    } else {
01826       /* Real channel */
01827       snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
01828    }
01829    publish_dahdichannel(chan, p->span, ch_name);
01830 }

static int dahdi_answer ( struct ast_channel ast  )  [static]

Todo:
XXX this is redundantly set by the analog and PRI submodules!

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

06320 {
06321    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
06322    int res = 0;
06323    int idx;
06324    ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
06325    ast_mutex_lock(&p->lock);
06326    idx = dahdi_get_index(ast, p, 0);
06327    if (idx < 0)
06328       idx = SUB_REAL;
06329    /* nothing to do if a radio channel */
06330    if ((p->radio || (p->oprmode < 0))) {
06331       ast_mutex_unlock(&p->lock);
06332       return 0;
06333    }
06334 
06335    if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06336       res = analog_answer(p->sig_pvt, ast);
06337       ast_mutex_unlock(&p->lock);
06338       return res;
06339    }
06340 
06341    switch (p->sig) {
06342 #if defined(HAVE_PRI)
06343    case SIG_PRI_LIB_HANDLE_CASES:
06344       res = sig_pri_answer(p->sig_pvt, ast);
06345       break;
06346 #endif   /* defined(HAVE_PRI) */
06347 #if defined(HAVE_SS7)
06348    case SIG_SS7:
06349       res = sig_ss7_answer(p->sig_pvt, ast);
06350       break;
06351 #endif   /* defined(HAVE_SS7) */
06352 #ifdef HAVE_OPENR2
06353    case SIG_MFCR2:
06354       if (!p->mfcr2_call_accepted) {
06355          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
06356             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
06357          p->mfcr2_answer_pending = 1;
06358          if (p->mfcr2_charge_calls) {
06359             ast_debug(1, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06360             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06361          } else {
06362             ast_debug(1, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06363             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06364          }
06365       } else {
06366          ast_debug(1, "Answering MFC/R2 call on chan %d\n", p->channel);
06367          dahdi_r2_answer(p);
06368       }
06369       break;
06370 #endif
06371    case 0:
06372       ast_mutex_unlock(&p->lock);
06373       return 0;
06374    default:
06375       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06376       res = -1;
06377       break;
06378    }
06379    ast_mutex_unlock(&p->lock);
06380    return res;
06381 }

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

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

05078 {
05079    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
05080    int x, res, mysig;
05081    char *dest;
05082    AST_DECLARE_APP_ARGS(args,
05083       AST_APP_ARG(group);  /* channel/group token */
05084       AST_APP_ARG(ext); /* extension token */
05085       //AST_APP_ARG(opts); /* options token */
05086       AST_APP_ARG(other);  /* Any remining unused arguments */
05087    );
05088 
05089    ast_mutex_lock(&p->lock);
05090    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05091 
05092    /* Split the dialstring */
05093    dest = ast_strdupa(rdest);
05094    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
05095    if (!args.ext) {
05096       args.ext = "";
05097    }
05098 
05099 #if defined(HAVE_PRI)
05100    if (dahdi_sig_pri_lib_handles(p->sig)) {
05101       char *subaddr;
05102 
05103       sig_pri_extract_called_num_subaddr(p->sig_pvt, rdest, p->exten, sizeof(p->exten));
05104 
05105       /* Remove any subaddress for uniformity with incoming calls. */
05106       subaddr = strchr(p->exten, ':');
05107       if (subaddr) {
05108          *subaddr = '\0';
05109       }
05110    } else
05111 #endif   /* defined(HAVE_PRI) */
05112    {
05113       ast_copy_string(p->exten, args.ext, sizeof(p->exten));
05114    }
05115 
05116    if ((ast_channel_state(ast) == AST_STATE_BUSY)) {
05117       p->subs[SUB_REAL].needbusy = 1;
05118       ast_mutex_unlock(&p->lock);
05119       return 0;
05120    }
05121    if ((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) {
05122       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
05123       ast_mutex_unlock(&p->lock);
05124       return -1;
05125    }
05126    p->waitingfordt.tv_sec = 0;
05127    p->dialednone = 0;
05128    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
05129    {
05130       /* Special pseudo -- automatically up */
05131       ast_setstate(ast, AST_STATE_UP);
05132       ast_mutex_unlock(&p->lock);
05133       return 0;
05134    }
05135    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05136    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05137    if (res)
05138       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05139    p->outgoing = 1;
05140 
05141    if (IS_DIGITAL(ast_channel_transfercapability(ast))){
05142       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05143    } else {
05144       set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05145    }
05146 
05147 #ifdef HAVE_PRI
05148    if (dahdi_sig_pri_lib_handles(p->sig)) {
05149       res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05150          (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05151       ast_mutex_unlock(&p->lock);
05152       return res;
05153    }
05154 #endif
05155 
05156 #if defined(HAVE_SS7)
05157    if (p->sig == SIG_SS7) {
05158       res = sig_ss7_call(p->sig_pvt, ast, rdest);
05159       ast_mutex_unlock(&p->lock);
05160       return res;
05161    }
05162 #endif   /* defined(HAVE_SS7) */
05163 
05164    /* If this is analog signalling we can exit here */
05165    if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05166       p->callwaitrings = 0;
05167       res = analog_call(p->sig_pvt, ast, rdest, timeout);
05168       ast_mutex_unlock(&p->lock);
05169       return res;
05170    }
05171 
05172    mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05173    switch (mysig) {
05174    case 0:
05175       /* Special pseudo -- automatically up*/
05176       ast_setstate(ast, AST_STATE_UP);
05177       break;
05178    case SIG_MFCR2:
05179       break;
05180    default:
05181       ast_debug(1, "not yet implemented\n");
05182       ast_mutex_unlock(&p->lock);
05183       return -1;
05184    }
05185 
05186 #ifdef HAVE_OPENR2
05187    if (p->mfcr2) {
05188       openr2_calling_party_category_t chancat;
05189       int callres = 0;
05190       char *c, *l;
05191 
05192       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
05193       p->dialdest[0] = '\0';
05194 
05195       c = args.ext;
05196       if (!p->hidecallerid) {
05197          l = ast_channel_connected(ast)->id.number.valid ? ast_channel_connected(ast)->id.number.str : NULL;
05198       } else {
05199          l = NULL;
05200       }
05201       if (strlen(c) < p->stripmsd) {
05202          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05203          ast_mutex_unlock(&p->lock);
05204          return -1;
05205       }
05206       p->dialing = 1;
05207       chancat = dahdi_r2_get_channel_category(ast);
05208       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05209       if (-1 == callres) {
05210          ast_mutex_unlock(&p->lock);
05211          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05212          return -1;
05213       }
05214       p->mfcr2_call_accepted = 0;
05215       p->mfcr2_progress_sent = 0;
05216       ast_setstate(ast, AST_STATE_DIALING);
05217    }
05218 #endif /* HAVE_OPENR2 */
05219    ast_mutex_unlock(&p->lock);
05220    return 0;
05221 }

static int dahdi_callwait ( struct ast_channel ast  )  [static]

Definition at line 5043 of file chan_dahdi.c.

References ast_channel_tech_pvt(), ast_free, ast_gen_cas(), AST_LAW, ast_log, ast_malloc, dahdi_pvt::callwaitcas, CALLWAITING_REPEAT_SAMPLES, dahdi_pvt::callwaitingcallerid, dahdi_pvt::callwaitingrepeat, dahdi_pvt::callwaitrings, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, LOG_WARNING, READ_SIZE, save_conference(), and send_callerid().

Referenced by dahdi_read().

05044 {
05045    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
05046 
05047    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05048    if (p->cidspill) {
05049       ast_log(LOG_WARNING, "Spill already exists?!?\n");
05050       ast_free(p->cidspill);
05051    }
05052 
05053    /*
05054     * SAS: Subscriber Alert Signal, 440Hz for 300ms
05055     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
05056     */
05057    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
05058       return -1;
05059    save_conference(p);
05060    /* Silence */
05061    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05062    if (!p->callwaitrings && p->callwaitingcallerid) {
05063       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05064       p->callwaitcas = 1;
05065       p->cidlen = 2400 + 680 + READ_SIZE * 4;
05066    } else {
05067       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05068       p->callwaitcas = 0;
05069       p->cidlen = 2400 + READ_SIZE * 4;
05070    }
05071    p->cidpos = 0;
05072    send_callerid(p);
05073 
05074    return 0;
05075 }

static int dahdi_cc_callback ( struct ast_channel inbound,
const char *  dest,
ast_cc_callback_fn  callback 
) [static]

Callback made when dial failed to get a channel out of dahdi_request().

Since:
1.8
Parameters:
inbound Incoming asterisk channel.
dest Same dial string passed to dahdi_request().
callback Callback into CC core to announce a busy channel available for CC.
This callback acts like a forked dial with all prongs of the fork busy. Essentially, for each channel that could have taken the call, indicate that it is busy.

Return values:
0 on success.
-1 on error.

Definition at line 13569 of file chan_dahdi.c.

References AST_CC_GENERIC_MONITOR_TYPE, AST_CC_MONITOR_ALWAYS, AST_CC_MONITOR_GENERIC, AST_CC_MONITOR_NATIVE, AST_CC_MONITOR_NEVER, AST_CHANNEL_NAME, ast_free, ast_get_cc_monitor_policy(), ast_mutex_lock, ast_mutex_unlock, ast_str_buffer(), dahdi_starting_point::backwards, dahdi_pvt::cc_params, dahdi_starting_point::channelmatch, create_channel_name(), dahdi_sig_pri_lib_handles(), determine_starting_point(), dahdi_starting_point::groupmatch, iflock, is_group_or_channel_match(), dahdi_pvt::next, NULL, dahdi_pvt::prev, dahdi_pvt::sig, dahdi_pvt::span, and dahdi_starting_point::span.

13570 {
13571    struct dahdi_pvt *p;
13572    struct dahdi_pvt *exitpvt;
13573    struct dahdi_starting_point start;
13574    int groupmatched = 0;
13575    int channelmatched = 0;
13576 
13577    ast_mutex_lock(&iflock);
13578    p = determine_starting_point(dest, &start);
13579    if (!p) {
13580       ast_mutex_unlock(&iflock);
13581       return -1;
13582    }
13583    exitpvt = p;
13584    for (;;) {
13585       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13586          /* We found a potential match. call the callback */
13587          struct ast_str *device_name;
13588          char *dash;
13589          const char *monitor_type;
13590          char dialstring[AST_CHANNEL_NAME];
13591          char full_device_name[AST_CHANNEL_NAME];
13592 
13593          switch (ast_get_cc_monitor_policy(p->cc_params)) {
13594          case AST_CC_MONITOR_NEVER:
13595             break;
13596          case AST_CC_MONITOR_NATIVE:
13597          case AST_CC_MONITOR_ALWAYS:
13598          case AST_CC_MONITOR_GENERIC:
13599 #if defined(HAVE_PRI)
13600             if (dahdi_sig_pri_lib_handles(p->sig)) {
13601                /*
13602                 * ISDN is in a trunk busy condition so we need to monitor
13603                 * the span congestion device state.
13604                 */
13605                snprintf(full_device_name, sizeof(full_device_name),
13606                   "DAHDI/I%d/congestion", p->pri->span);
13607             } else
13608 #endif   /* defined(HAVE_PRI) */
13609             {
13610 #if defined(HAVE_PRI)
13611                device_name = create_channel_name(p, 1, "");
13612 #else
13613                device_name = create_channel_name(p);
13614 #endif   /* defined(HAVE_PRI) */
13615                snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13616                   device_name ? ast_str_buffer(device_name) : "");
13617                ast_free(device_name);
13618                /*
13619                 * The portion after the '-' in the channel name is either a random
13620                 * number, a sequence number, or a subchannel number. None are
13621                 * necessary so strip them off.
13622                 */
13623                dash = strrchr(full_device_name, '-');
13624                if (dash) {
13625                   *dash = '\0';
13626                }
13627             }
13628             snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13629 
13630             /*
13631              * Analog can only do generic monitoring.
13632              * ISDN is in a trunk busy condition and any "device" is going
13633              * to be busy until a B channel becomes available.  The generic
13634              * monitor can do this task.
13635              */
13636             monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13637             callback(inbound,
13638 #if defined(HAVE_PRI)
13639                p->pri ? p->pri->cc_params : p->cc_params,
13640 #else
13641                p->cc_params,
13642 #endif   /* defined(HAVE_PRI) */
13643                monitor_type, full_device_name, dialstring, NULL);
13644             break;
13645          }
13646       }
13647       p = start.backwards ? p->prev : p->next;
13648       if (!p) {
13649          p = start.backwards ? ifend : iflist;
13650       }
13651       if (p == exitpvt) {
13652          break;
13653       }
13654    }
13655    ast_mutex_unlock(&iflock);
13656    return 0;
13657 }

static struct dahdi_chan_conf dahdi_chan_conf_default ( void   )  [static, read]

returns a new dahdi_chan_conf with default values (by-value)

Definition at line 892 of file chan_dahdi.c.

References ast_cc_config_params_init, CID_SIG_BELL, CID_START_RING, DAHDI_CHAN_MAPPING_PHYSICAL, DEFAULT_CIDRINGS, and SIG_PRI_COLP_UPDATE.

Referenced by dahdi_create_channel_range(), process_dahdi(), and setup_dahdi().

00893 {
00894    /* recall that if a field is not included here it is initialized
00895     * to 0 or equivalent
00896     */
00897    struct dahdi_chan_conf conf = {
00898 #ifdef HAVE_PRI
00899       .pri.pri = {
00900          .nsf = PRI_NSF_NONE,
00901          .switchtype = PRI_SWITCH_NI2,
00902          .dialplan = PRI_UNKNOWN + 1,
00903          .localdialplan = PRI_NATIONAL_ISDN + 1,
00904          .nodetype = PRI_CPE,
00905          .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
00906 
00907 #if defined(HAVE_PRI_CCSS)
00908          .cc_ptmp_recall_mode = 1,/* specificRecall */
00909          .cc_qsig_signaling_link_req = 1,/* retain */
00910          .cc_qsig_signaling_link_rsp = 1,/* retain */
00911 #endif   /* defined(HAVE_PRI_CCSS) */
00912 
00913          .minunused = 2,
00914          .idleext = "",
00915          .idledial = "",
00916          .internationalprefix = "",
00917          .nationalprefix = "",
00918          .localprefix = "",
00919          .privateprefix = "",
00920          .unknownprefix = "",
00921          .colp_send = SIG_PRI_COLP_UPDATE,
00922          .resetinterval = -1,
00923       },
00924 #endif
00925 #if defined(HAVE_SS7)
00926       .ss7.ss7 = {
00927          .called_nai = SS7_NAI_NATIONAL,
00928          .calling_nai = SS7_NAI_NATIONAL,
00929          .internationalprefix = "",
00930          .nationalprefix = "",
00931          .subscriberprefix = "",
00932          .unknownprefix = "",
00933          .networkroutedprefix = ""
00934       },
00935 #endif   /* defined(HAVE_SS7) */
00936 #ifdef HAVE_OPENR2
00937       .mfcr2 = {
00938          .variant = OR2_VAR_ITU,
00939          .mfback_timeout = -1,
00940          .metering_pulse_timeout = -1,
00941          .max_ani = 10,
00942          .max_dnis = 4,
00943          .get_ani_first = -1,
00944 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00945          .skip_category_request = -1,
00946 #endif
00947          .call_files = 0,
00948          .allow_collect_calls = 0,
00949          .charge_calls = 1,
00950          .accept_on_offer = 1,
00951          .forced_release = 0,
00952          .double_answer = 0,
00953          .immediate_accept = -1,
00954 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
00955          .dtmf_dialing = -1,
00956          .dtmf_detection = -1,
00957          .dtmf_time_on = OR2_DEFAULT_DTMF_ON,
00958          .dtmf_time_off = OR2_DEFAULT_DTMF_OFF,
00959 #endif
00960 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
00961          .dtmf_end_timeout = -1,
00962 #endif
00963          .logdir = "",
00964          .r2proto_file = "",
00965          .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
00966          .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
00967       },
00968 #endif
00969       .chan = {
00970          .context = "default",
00971          .cid_num = "",
00972          .cid_name = "",
00973          .cid_tag = "",
00974          .mohinterpret = "default",
00975          .mohsuggest = "",
00976          .parkinglot = "",
00977          .transfertobusy = 1,
00978 
00979          .cid_signalling = CID_SIG_BELL,
00980          .cid_start = CID_START_RING,
00981          .dahditrcallerid = 0,
00982          .use_callerid = 1,
00983          .sig = -1,
00984          .outsigmod = -1,
00985 
00986          .cid_rxgain = +5.0,
00987 
00988          .tonezone = -1,
00989 
00990          .echocancel.head.tap_length = 1,
00991 
00992          .busycount = 3,
00993 
00994          .accountcode = "",
00995 
00996          .mailbox = "",
00997 
00998 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
00999          .mwisend_fsk = 1,
01000 #endif
01001          .polarityonanswerdelay = 600,
01002 
01003          .sendcalleridafter = DEFAULT_CIDRINGS,
01004 
01005          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01006          .buf_no = numbufs,
01007          .usefaxbuffers = 0,
01008          .cc_params = ast_cc_config_params_init(),
01009       },
01010       .timing = {
01011          .prewinktime = -1,
01012          .preflashtime = -1,
01013          .winktime = -1,
01014          .flashtime = -1,
01015          .starttime = -1,
01016          .rxwinktime = -1,
01017          .rxflashtime = -1,
01018          .debouncetime = -1
01019       },
01020       .is_sig_auto = 1,
01021       .ignore_failed_channels = 1,
01022       .smdi_port = "/dev/ttyS0",
01023    };
01024 
01025    return conf;
01026 }

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

Definition at line 19412 of file chan_dahdi.c.

References ast_data_add_node(), ast_data_add_structure, ast_data_remove_node(), ast_data_search_match(), ast_mutex_lock, ast_mutex_unlock, iflock, and dahdi_pvt::next.

19414 {
19415    struct dahdi_pvt *tmp;
19416    struct ast_data *data_channel;
19417 
19418    ast_mutex_lock(&iflock);
19419    for (tmp = iflist; tmp; tmp = tmp->next) {
19420       data_channel = ast_data_add_node(data_root, "channel");
19421       if (!data_channel) {
19422          continue;
19423       }
19424 
19425       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
19426 
19427       /* if this channel doesn't match remove it. */
19428       if (!ast_data_search_match(search, data_channel)) {
19429          ast_data_remove_node(data_root, data_channel);
19430       }
19431    }
19432    ast_mutex_unlock(&iflock);
19433 
19434    return 0;
19435 }

static void dahdi_close ( int  fd  )  [static]

Definition at line 4101 of file chan_dahdi.c.

Referenced by dahdi_close_sub().

04102 {
04103    if (fd > 0)
04104       close(fd);
04105 }

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

Definition at line 4107 of file chan_dahdi.c.

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

Referenced by alloc_sub(), destroy_dahdi_pvt(), and unalloc_sub().

04108 {
04109    dahdi_close(chan_pvt->subs[sub_num].dfd);
04110    chan_pvt->subs[sub_num].dfd = -1;
04111 }

void dahdi_conf_update ( struct dahdi_pvt p  ) 

Definition at line 4539 of file chan_dahdi.c.

References ast_debug, dahdi_pvt::channel, conf_add(), conf_del(), dahdi_pvt::confno, dahdi_subchannel::dfd, GET_CHANNEL, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, isslavenative(), dahdi_pvt::master, MAX_SLAVES, NULL, dahdi_pvt::slaves, SUB_REAL, and dahdi_pvt::subs.

Referenced by __dahdi_exception(), dahdi_fixup(), dahdi_handle_event(), dahdi_hangup(), dahdi_master_slave_unlink(), mkintf(), and native_start().

04540 {
04541    int needconf = 0;
04542    int x;
04543    int useslavenative;
04544    struct dahdi_pvt *slave = NULL;
04545 
04546    useslavenative = isslavenative(p, &slave);
04547    /* Start with the obvious, general stuff */
04548    for (x = 0; x < 3; x++) {
04549       /* Look for three way calls */
04550       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04551          conf_add(p, &p->subs[x], x, 0);
04552          needconf++;
04553       } else {
04554          conf_del(p, &p->subs[x], x);
04555       }
04556    }
04557    /* If we have a slave, add him to our conference now. or DAX
04558       if this is slave native */
04559    for (x = 0; x < MAX_SLAVES; x++) {
04560       if (p->slaves[x]) {
04561          if (useslavenative)
04562             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04563          else {
04564             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04565             needconf++;
04566          }
04567       }
04568    }
04569    /* If we're supposed to be in there, do so now */
04570    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04571       if (useslavenative)
04572          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04573       else {
04574          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04575          needconf++;
04576       }
04577    }
04578    /* If we have a master, add ourselves to his conference */
04579    if (p->master) {
04580       if (isslavenative(p->master, NULL)) {
04581          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04582       } else {
04583          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04584       }
04585    }
04586    if (!needconf) {
04587       /* Nobody is left (or should be left) in our conference.
04588          Kill it. */
04589       p->confno = -1;
04590    }
04591    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04592 }

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

Definition at line 4895 of file chan_dahdi.c.

References ast_log, dahdi_pvt::channel, dahdi_subchannel::dfd, errno, LOG_WARNING, dahdi_pvt::sig, SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_handle_dtmf(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_read(), my_confmute(), and my_handle_dtmf().

04896 {
04897    int x, res;
04898 
04899    x = muted;
04900 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04901    switch (p->sig) {
04902 #if defined(HAVE_PRI)
04903    case SIG_PRI_LIB_HANDLE_CASES:
04904       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04905          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
04906          break;
04907       }
04908       /* Fall through */
04909 #endif   /* defined(HAVE_PRI) */
04910 #if defined(HAVE_SS7)
04911    case SIG_SS7:
04912 #endif   /* defined(HAVE_SS7) */
04913       {
04914          int y = 1;
04915 
04916          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
04917          if (res)
04918             ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
04919                p->channel, strerror(errno));
04920       }
04921       break;
04922    default:
04923       break;
04924    }
04925 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
04926    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
04927    if (res < 0)
04928       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
04929    return res;
04930 }

static int dahdi_create_channel_range ( int  start,
int  end 
) [static]

Definition at line 10984 of file chan_dahdi.c.

References ast_cc_config_params_destroy(), ast_debug, ast_log, ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::cc_params, dahdi_chan_conf::chan, dahdi_pvt::channel, dahdi_chan_conf_default(), iflock, LOG_ERROR, dahdi_pvt::next, out, RESULT_FAILURE, RESULT_SUCCESS, setup_dahdi_int(), SIG_PRI_NUM_DCHANS, dahdi_chan_conf::wanted_channels_end, and dahdi_chan_conf::wanted_channels_start.

Referenced by dahdi_create_channels().

10985 {
10986    struct dahdi_pvt *cur;
10987    struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
10988    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
10989    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
10990    int ret = RESULT_FAILURE; /* be pessimistic */
10991 
10992    ast_debug(1, "channel range caps: %d - %d\n", start, end);
10993    ast_mutex_lock(&iflock);
10994    for (cur = iflist; cur; cur = cur->next) {
10995       if (cur->channel >= start && cur->channel <= end) {
10996          ast_log(LOG_ERROR,
10997             "channel range %d-%d is occupied\n",
10998             start, end);
10999          goto out;
11000       }
11001    }
11002 #ifdef HAVE_PRI
11003    {
11004       int i, x;
11005       for (x = 0; x < NUM_SPANS; x++) {
11006          struct dahdi_pri *pri = pris + x;
11007 
11008          if (!pris[x].pri.pvts[0]) {
11009             break;
11010          }
11011          for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
11012             int channo = pri->dchannels[i];
11013 
11014             if (!channo) {
11015                break;
11016             }
11017             if (!pri->pri.fds[i]) {
11018                break;
11019             }
11020             if (channo >= start && channo <= end) {
11021                ast_log(LOG_ERROR,
11022                      "channel range %d-%d is occupied by span %d\n",
11023                      start, end, x + 1);
11024                goto out;
11025             }
11026          }
11027       }
11028    }
11029 #endif
11030    if (!default_conf.chan.cc_params || !base_conf.chan.cc_params ||
11031       !conf.chan.cc_params) {
11032       goto out;
11033    }
11034    default_conf.wanted_channels_start = start;
11035    base_conf.wanted_channels_start = start;
11036    conf.wanted_channels_start = start;
11037    default_conf.wanted_channels_end = end;
11038    base_conf.wanted_channels_end = end;
11039    conf.wanted_channels_end = end;
11040    if (setup_dahdi_int(0, &default_conf, &base_conf, &conf) == 0) {
11041       ret = RESULT_SUCCESS;
11042    }
11043 out:
11044    ast_cc_config_params_destroy(default_conf.chan.cc_params);
11045    ast_cc_config_params_destroy(base_conf.chan.cc_params);
11046    ast_cc_config_params_destroy(conf.chan.cc_params);
11047    ast_mutex_unlock(&iflock);
11048    return ret;
11049 }

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

Definition at line 15019 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_create_channel_range(), end, ast_cli_args::fd, NULL, RESULT_SUCCESS, and ast_cli_entry::usage.

15020 {
15021    int start;
15022    int end;
15023    int ret;
15024 
15025    switch (cmd) {
15026    case CLI_INIT:
15027       e->command = "dahdi create channels";
15028       e->usage = "Usage: dahdi create channels <from> [<to>] - a range of channels\n"
15029             "       dahdi create channels new           - add channels not yet created\n"
15030             "For ISDN  and SS7 the range should include complete spans.\n";
15031       return NULL;
15032    case CLI_GENERATE:
15033       return NULL;
15034    }
15035    if ((a->argc < 4) || a->argc > 5) {
15036       return CLI_SHOWUSAGE;
15037    }
15038    if (a->argc == 4 && !strcmp(a->argv[3], "new")) {
15039       ret = dahdi_create_channel_range(0, 0);
15040       return (RESULT_SUCCESS == ret) ? CLI_SUCCESS : CLI_FAILURE;
15041    }
15042    start = atoi(a->argv[3]);
15043    if (start <= 0) {
15044       ast_cli(a->fd, "Invalid starting channel number '%s'.\n",
15045             a->argv[3]);
15046       return CLI_FAILURE;
15047    }
15048    if (a->argc == 5) {
15049       end = atoi(a->argv[4]);
15050       if (end <= 0) {
15051          ast_cli(a->fd, "Invalid ending channel number '%s'.\n",
15052                a->argv[4]);
15053          return CLI_FAILURE;
15054       }
15055    } else {
15056       end = start;
15057    }
15058    if (end < start) {
15059       ast_cli(a->fd,
15060          "range end (%d) is smaller than range start (%d)\n",
15061          end, start);
15062       return CLI_FAILURE;
15063    }
15064    ret = dahdi_create_channel_range(start, end);
15065    return (RESULT_SUCCESS == ret) ? CLI_SUCCESS : CLI_FAILURE;
15066 }

static void dahdi_destroy_channel_range ( int  start,
int  end 
) [static]

Definition at line 10936 of file chan_dahdi.c.

References ast_debug, ast_module_unref, ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::channel, destroy_channel(), dahdi_subchannel::dfd, iflock, dahdi_pvt::next, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_destroy_channels(), and do_monitor().

10937 {
10938    struct dahdi_pvt *cur;
10939    struct dahdi_pvt *next;
10940    int destroyed_first = 0;
10941    int destroyed_last = 0;
10942 
10943    ast_mutex_lock(&iflock);
10944    ast_debug(1, "range: %d-%d\n", start, end);
10945    for (cur = iflist; cur; cur = next) {
10946       next = cur->next;
10947       if (cur->channel >= start && cur->channel <= end) {
10948          int x = DAHDI_FLASH;
10949 
10950          if (cur->channel > destroyed_last) {
10951             destroyed_last = cur->channel;
10952          }
10953          if (destroyed_first < 1 || cur->channel < destroyed_first) {
10954             destroyed_first = cur->channel;
10955          }
10956          ast_debug(3, "Destroying %d\n", cur->channel);
10957          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
10958          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
10959 
10960          destroy_channel(cur, 1);
10961          ast_module_unref(ast_module_info->self);
10962       }
10963    }
10964    ast_mutex_unlock(&iflock);
10965    if (destroyed_first > start || destroyed_last < end) {
10966       ast_debug(1, "Asked to destroy %d-%d, destroyed %d-%d,\n",
10967          start, end, destroyed_first, destroyed_last);
10968    }
10969 }

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

Definition at line 14975 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_destroy_channel_range(), end, ast_cli_args::fd, NULL, and ast_cli_entry::usage.

14976 {
14977    int start;
14978    int end;
14979    switch (cmd) {
14980    case CLI_INIT:
14981       e->command = "dahdi destroy channels";
14982       e->usage =
14983          "Usage: dahdi destroy channels <from_channel> [<to_channel>]\n"
14984          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
14985       return NULL;
14986    case CLI_GENERATE:
14987       return NULL;
14988    }
14989    if ((a->argc < 4) || a->argc > 5) {
14990       return CLI_SHOWUSAGE;
14991    }
14992    start = atoi(a->argv[3]);
14993    if (start < 1) {
14994       ast_cli(a->fd, "Invalid starting channel number %s.\n",
14995             a->argv[4]);
14996       return CLI_FAILURE;
14997    }
14998    if (a->argc == 5) {
14999       end = atoi(a->argv[4]);
15000       if (end < 1) {
15001          ast_cli(a->fd, "Invalid ending channel number %s.\n",
15002                a->argv[4]);
15003          return CLI_FAILURE;
15004       }
15005    } else {
15006       end = start;
15007    }
15008 
15009    if (end < start) {
15010       ast_cli(a->fd,
15011          "range end (%d) is smaller than range start (%d)\n",
15012          end, start);
15013       return CLI_FAILURE;
15014    }
15015    dahdi_destroy_channel_range(start, end);
15016    return CLI_SUCCESS;
15017 }

static int dahdi_devicestate ( const char *  data  )  [static]

Definition at line 13507 of file chan_dahdi.c.

References AST_DEVICE_UNKNOWN.

13508 {
13509 #if defined(HAVE_PRI)
13510    const char *device;
13511    unsigned span;
13512    int res;
13513 
13514    device = data;
13515 
13516    if (*device != 'I') {
13517       /* The request is not for an ISDN span device. */
13518       return AST_DEVICE_UNKNOWN;
13519    }
13520    res = sscanf(device, "I%30u", &span);
13521    if (res != 1 || !span || NUM_SPANS < span) {
13522       /* Bad format for ISDN span device name. */
13523       return AST_DEVICE_UNKNOWN;
13524    }
13525    device = strchr(device, '/');
13526    if (!device) {
13527       /* Bad format for ISDN span device name. */
13528       return AST_DEVICE_UNKNOWN;
13529    }
13530 
13531    /*
13532     * Since there are currently no other span devstate's defined,
13533     * it must be congestion.
13534     */
13535 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13536    ++device;
13537    if (!strcmp(device, "congestion"))
13538 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13539    {
13540       return pris[span - 1].pri.congestion_devstate;
13541    }
13542 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13543    else if (!strcmp(device, "threshold")) {
13544       return pris[span - 1].pri.threshold_devstate;
13545    }
13546    return AST_DEVICE_UNKNOWN;
13547 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13548 #else
13549    return AST_DEVICE_UNKNOWN;
13550 #endif   /* defined(HAVE_PRI) */
13551 }

static int dahdi_dial_str ( struct dahdi_pvt pvt,
int  operation,
const char *  dial_str 
) [static]

Definition at line 1243 of file chan_dahdi.c.

References ast_debug, ast_log, dahdi_pvt::channel, dahdi_subchannel::dfd, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_digit_begin(), dahdi_handle_event(), dahdi_read(), and my_dial_digits().

01244 {
01245    int res;
01246    int offset;
01247    const char *pos;
01248    struct dahdi_dialoperation zo = {
01249       .op = operation,
01250    };
01251 
01252    /* Convert the W's to ww. */
01253    pos = dial_str;
01254    for (offset = 0; offset < sizeof(zo.dialstr) - 1; ++offset) {
01255       if (!*pos) {
01256          break;
01257       }
01258       if (*pos == 'W') {
01259          /* Convert 'W' to "ww" */
01260          ++pos;
01261          if (offset >= sizeof(zo.dialstr) - 3) {
01262             /* No room to expand */
01263             break;
01264          }
01265          zo.dialstr[offset] = 'w';
01266          ++offset;
01267          zo.dialstr[offset] = 'w';
01268          continue;
01269       }
01270       zo.dialstr[offset] = *pos++;
01271    }
01272    /* The zo initialization has already terminated the dialstr. */
01273 
01274    ast_debug(1, "Channel %d: Dial str '%s' expanded to '%s' sent to DAHDI_DIAL.\n",
01275       pvt->channel, dial_str, zo.dialstr);
01276    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
01277    if (res) {
01278       ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
01279          pvt->channel, dial_str, strerror(errno));
01280    }
01281 
01282    return res;
01283 }

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

Definition at line 4205 of file chan_dahdi.c.

References ast_channel_name(), ast_channel_tech_pvt(), ast_debug, ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::begindigit, dahdi_dial_str(), dahdi_get_index, dahdi_subchannel::dfd, dahdi_pvt::dialing, digit_to_dtmfindex(), dahdi_pvt::lock, out, dahdi_pvt::owner, dahdi_pvt::pulse, dahdi_pvt::sig, sig_pri_digit_begin(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SUB_REAL, and dahdi_pvt::subs.

04206 {
04207    struct dahdi_pvt *pvt;
04208    int idx;
04209    int dtmf = -1;
04210    int res;
04211 
04212    pvt = ast_channel_tech_pvt(chan);
04213 
04214    ast_mutex_lock(&pvt->lock);
04215 
04216    idx = dahdi_get_index(chan, pvt, 0);
04217 
04218    if ((idx != SUB_REAL) || !pvt->owner)
04219       goto out;
04220 
04221 #ifdef HAVE_PRI
04222    switch (pvt->sig) {
04223    case SIG_PRI_LIB_HANDLE_CASES:
04224       res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04225       if (!res)
04226          goto out;
04227       break;
04228    default:
04229       break;
04230    }
04231 #endif
04232    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04233       goto out;
04234 
04235    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04236       char dial_str[] = { 'T', digit, '\0' };
04237 
04238       res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
04239       if (!res) {
04240          pvt->dialing = 1;
04241       }
04242    } else {
04243       ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04244          ast_channel_name(chan), digit);
04245       pvt->dialing = 1;
04246       pvt->begindigit = digit;
04247    }
04248 
04249 out:
04250    ast_mutex_unlock(&pvt->lock);
04251 
04252    return 0;
04253 }

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

Definition at line 4255 of file chan_dahdi.c.

References ast_channel_name(), ast_channel_tech_pvt(), ast_debug, ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::begindigit, dahdi_get_index, dahdi_sig_pri_lib_handles(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::lock, out, dahdi_pvt::owner, dahdi_pvt::pulse, dahdi_pvt::sig, SUB_REAL, and dahdi_pvt::subs.

04256 {
04257    struct dahdi_pvt *pvt;
04258    int res = 0;
04259    int idx;
04260    int x;
04261 
04262    pvt = ast_channel_tech_pvt(chan);
04263 
04264    ast_mutex_lock(&pvt->lock);
04265 
04266    idx = dahdi_get_index(chan, pvt, 0);
04267 
04268    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04269       goto out;
04270 
04271 #ifdef HAVE_PRI
04272    /* This means that the digit was already sent via PRI signalling */
04273    if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04274       goto out;
04275    }
04276 #endif
04277 
04278    if (pvt->begindigit) {
04279       x = -1;
04280       ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04281          ast_channel_name(chan), digit);
04282       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04283       pvt->dialing = 0;
04284       pvt->begindigit = 0;
04285    }
04286 
04287 out:
04288    ast_mutex_unlock(&pvt->lock);
04289 
04290    return res;
04291 }

static int dahdi_dnd ( struct dahdi_pvt dahdichan,
int  flag 
) [static]

enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel

Parameters:
dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
flag on 1 to enable, 0 to disable, -1 return dnd value
chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical DAHDI channel). Use this to enable or disable it.

Bug:
the use of the word "channel" for those dahdichans is really confusing.

Definition at line 9338 of file chan_dahdi.c.

References analog_dnd(), ast_verb, dahdi_pvt::channel, dahdi_analog_lib_handles(), dahdi_pvt::dnd, dahdi_pvt::oprmode, publish_dnd_state(), dahdi_pvt::radio, dahdi_pvt::sig, and dahdi_pvt::sig_pvt.

Referenced by action_dahdidndoff(), action_dahdidndon(), action_dahdishowchannels(), analog_ss_thread(), dahdi_set_dnd(), and dahdi_show_channel().

09339 {
09340    if (dahdi_analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09341       return analog_dnd(dahdichan->sig_pvt, flag);
09342    }
09343 
09344    if (flag == -1) {
09345       return dahdichan->dnd;
09346    }
09347 
09348    /* Do not disturb */
09349    dahdichan->dnd = flag;
09350    ast_verb(3, "%s DND on channel %d\n",
09351          flag? "Enabled" : "Disabled",
09352          dahdichan->channel);
09353    publish_dnd_state(dahdichan->channel, flag ? "enabled" : "disabled");
09354    return 0;
09355 }

void dahdi_dtmf_detect_disable ( struct dahdi_pvt p  ) 

Definition at line 6383 of file chan_dahdi.c.

References ast_dsp_set_features(), dahdi_subchannel::dfd, dahdi_pvt::dsp, DSP_FEATURE_DIGIT_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::hardwaredtmf, dahdi_pvt::ignoredtmf, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_setoption(), and native_start().

06384 {
06385    int val = 0;
06386 
06387    p->ignoredtmf = 1;
06388 
06389    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06390 
06391    if (!p->hardwaredtmf && p->dsp) {
06392       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06393       ast_dsp_set_features(p->dsp, p->dsp_features);
06394    }
06395 }

void dahdi_dtmf_detect_enable ( struct dahdi_pvt p  ) 

Definition at line 6397 of file chan_dahdi.c.

References ast_dsp_set_features(), CHAN_PSEUDO, dahdi_pvt::channel, dahdi_subchannel::dfd, dahdi_pvt::dsp, DSP_FEATURE_DIGIT_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::hardwaredtmf, dahdi_pvt::ignoredtmf, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_setoption(), and native_stop().

06398 {
06399    int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06400 
06401    if (p->channel == CHAN_PSEUDO)
06402       return;
06403 
06404    p->ignoredtmf = 0;
06405 
06406    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06407 
06408    if (!p->hardwaredtmf && p->dsp) {
06409       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06410       ast_dsp_set_features(p->dsp, p->dsp_features);
06411    }
06412 }

void dahdi_ec_disable ( struct dahdi_pvt p  ) 

Definition at line 4666 of file chan_dahdi.c.

References ast_debug, ast_log, dahdi_pvt::channel, dahdi_subchannel::dfd, dahdi_pvt::echocanon, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.

Referenced by __dahdi_exception(), dahdi_func_write(), dahdi_handle_event(), dahdi_hangup(), dahdi_setoption(), handle_init_event(), my_set_echocanceller(), and native_start().

04667 {
04668    int res;
04669 
04670    if (p->echocanon) {
04671       struct dahdi_echocanparams ecp = { .tap_length = 0 };
04672 
04673       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04674 
04675       if (res)
04676          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04677       else
04678          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04679    }
04680 
04681    p->echocanon = 0;
04682 }

void dahdi_ec_enable ( struct dahdi_pvt p  ) 

Definition at line 4594 of file chan_dahdi.c.

References ast_debug, ast_log, dahdi_pvt::channel, dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, dahdi_pvt::head, LOG_WARNING, dahdi_pvt::sig, SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, SUB_REAL, and dahdi_pvt::subs.

Referenced by __dahdi_exception(), analog_ss_thread(), dahdi_func_write(), dahdi_handle_event(), dahdi_setoption(), handle_init_event(), my_set_echocanceller(), and native_stop().

04595 {
04596    int res;
04597    if (!p)
04598       return;
04599    if (p->echocanon) {
04600       ast_debug(1, "Echo cancellation already on\n");
04601       return;
04602    }
04603    if (p->digital) {
04604       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04605       return;
04606    }
04607    if (p->echocancel.head.tap_length) {
04608 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04609       switch (p->sig) {
04610 #if defined(HAVE_PRI)
04611       case SIG_PRI_LIB_HANDLE_CASES:
04612          if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04613             /*
04614              * PRI nobch pseudo channel.  Does not need ec anyway.
04615              * Does not handle ioctl(DAHDI_AUDIOMODE)
04616              */
04617             return;
04618          }
04619          /* Fall through */
04620 #endif   /* defined(HAVE_PRI) */
04621 #if defined(HAVE_SS7)
04622       case SIG_SS7:
04623 #endif   /* defined(HAVE_SS7) */
04624          {
04625             int x = 1;
04626 
04627             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04628             if (res)
04629                ast_log(LOG_WARNING,
04630                   "Unable to enable audio mode on channel %d (%s)\n",
04631                   p->channel, strerror(errno));
04632          }
04633          break;
04634       default:
04635          break;
04636       }
04637 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
04638       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04639       if (res) {
04640          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04641       } else {
04642          p->echocanon = 1;
04643          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04644       }
04645    } else
04646       ast_debug(1, "No echo cancellation requested\n");
04647 }

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

Definition at line 8299 of file chan_dahdi.c.

References __dahdi_exception(), analog_exception(), ast_channel_tech_pvt(), ast_mutex_lock, ast_mutex_unlock, dahdi_analog_lib_handles(), dahdi_pvt::lock, dahdi_pvt::oprmode, dahdi_pvt::radio, dahdi_pvt::sig, and dahdi_pvt::sig_pvt.

08300 {
08301    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
08302    struct ast_frame *f;
08303    ast_mutex_lock(&p->lock);
08304    if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08305       struct analog_pvt *analog_p = p->sig_pvt;
08306       f = analog_exception(analog_p, ast);
08307    } else {
08308       f = __dahdi_exception(ast);
08309    }
08310    ast_mutex_unlock(&p->lock);
08311    return f;
08312 }

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

Definition at line 15909 of file chan_dahdi.c.

References ast_channel_name(), ast_log, dahdi_pvt::fake_event, HANGUP, LOG_WARNING, dahdi_pvt::owner, and TRANSFER.

Referenced by action_transfer(), and action_transferhangup().

15910 {
15911    if (p) {
15912       switch (mode) {
15913       case TRANSFER:
15914          p->fake_event = DAHDI_EVENT_WINKFLASH;
15915          break;
15916       case HANGUP:
15917          p->fake_event = DAHDI_EVENT_ONHOOK;
15918          break;
15919       default:
15920          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, ast_channel_name(p->owner));
15921       }
15922    }
15923    return 0;
15924 }

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

Definition at line 6967 of file chan_dahdi.c.

References analog_fixup(), ast_channel_name(), ast_channel_tech_pvt(), AST_CONTROL_RINGING, ast_debug, ast_mutex_lock, ast_mutex_unlock, AST_STATE_RINGING, dahdi_pvt::channel, dahdi_analog_lib_handles(), dahdi_conf_update(), dahdi_indicate(), dahdi_master_slave_unlink(), dahdi_sig_pri_lib_handles(), dahdi_pvt::lock, NULL, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::radio, dahdi_pvt::sig, sig_pri_fixup(), dahdi_pvt::sig_pvt, SIG_SS7, sig_ss7_fixup(), and dahdi_pvt::subs.

06968 {
06969    struct dahdi_pvt *p = ast_channel_tech_pvt(newchan);
06970    int x;
06971 
06972    ast_mutex_lock(&p->lock);
06973 
06974    ast_debug(1, "New owner for channel %d is %s\n", p->channel, ast_channel_name(newchan));
06975    if (p->owner == oldchan) {
06976       p->owner = newchan;
06977    }
06978    for (x = 0; x < 3; x++) {
06979       if (p->subs[x].owner == oldchan) {
06980          if (!x) {
06981             dahdi_master_slave_unlink(NULL, p, 0);
06982          }
06983          p->subs[x].owner = newchan;
06984       }
06985    }
06986    if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06987       analog_fixup(oldchan, newchan, p->sig_pvt);
06988 #if defined(HAVE_PRI)
06989    } else if (dahdi_sig_pri_lib_handles(p->sig)) {
06990       sig_pri_fixup(oldchan, newchan, p->sig_pvt);
06991 #endif   /* defined(HAVE_PRI) */
06992 #if defined(HAVE_SS7)
06993    } else if (p->sig == SIG_SS7) {
06994       sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
06995 #endif   /* defined(HAVE_SS7) */
06996    }
06997    dahdi_conf_update(p);
06998 
06999    ast_mutex_unlock(&p->lock);
07000 
07001    if (ast_channel_state(newchan) == AST_STATE_RINGING) {
07002       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07003    }
07004    return 0;
07005 }

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

Definition at line 6674 of file chan_dahdi.c.

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

06675 {
06676    struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
06677    int res = 0;
06678 
06679    if (!p) {
06680       /* No private structure! */
06681       *buf = '\0';
06682       return -1;
06683    }
06684 
06685    if (!strcasecmp(data, "rxgain")) {
06686       ast_mutex_lock(&p->lock);
06687       snprintf(buf, len, "%f", p->rxgain);
06688       ast_mutex_unlock(&p->lock);
06689    } else if (!strcasecmp(data, "txgain")) {
06690       ast_mutex_lock(&p->lock);
06691       snprintf(buf, len, "%f", p->txgain);
06692       ast_mutex_unlock(&p->lock);
06693    } else if (!strcasecmp(data, "dahdi_channel")) {
06694       ast_mutex_lock(&p->lock);
06695       snprintf(buf, len, "%d", p->channel);
06696       ast_mutex_unlock(&p->lock);
06697    } else if (!strcasecmp(data, "dahdi_span")) {
06698       ast_mutex_lock(&p->lock);
06699       snprintf(buf, len, "%d", p->span);
06700       ast_mutex_unlock(&p->lock);
06701    } else if (!strcasecmp(data, "dahdi_type")) {
06702       ast_mutex_lock(&p->lock);
06703       switch (p->sig) {
06704 #if defined(HAVE_OPENR2)
06705       case SIG_MFCR2:
06706          ast_copy_string(buf, "mfc/r2", len);
06707          break;
06708 #endif   /* defined(HAVE_OPENR2) */
06709 #if defined(HAVE_PRI)
06710       case SIG_PRI_LIB_HANDLE_CASES:
06711          ast_copy_string(buf, "pri", len);
06712          break;
06713 #endif   /* defined(HAVE_PRI) */
06714       case 0:
06715          ast_copy_string(buf, "pseudo", len);
06716          break;
06717 #if defined(HAVE_SS7)
06718       case SIG_SS7:
06719          ast_copy_string(buf, "ss7", len);
06720          break;
06721 #endif   /* defined(HAVE_SS7) */
06722       default:
06723          /* The only thing left is analog ports. */
06724          ast_copy_string(buf, "analog", len);
06725          break;
06726       }
06727       ast_mutex_unlock(&p->lock);
06728 #if defined(HAVE_PRI)
06729 #if defined(HAVE_PRI_REVERSE_CHARGE)
06730    } else if (!strcasecmp(data, "reversecharge")) {
06731       ast_mutex_lock(&p->lock);
06732       switch (p->sig) {
06733       case SIG_PRI_LIB_HANDLE_CASES:
06734          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
06735          break;
06736       default:
06737          *buf = '\0';
06738          res = -1;
06739          break;
06740       }
06741       ast_mutex_unlock(&p->lock);
06742 #endif
06743 #if defined(HAVE_PRI_SETUP_KEYPAD)
06744    } else if (!strcasecmp(data, "keypad_digits")) {
06745       ast_mutex_lock(&p->lock);
06746       switch (p->sig) {
06747       case SIG_PRI_LIB_HANDLE_CASES:
06748          ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
06749             len);
06750          break;
06751       default:
06752          *buf = '\0';
06753          res = -1;
06754          break;
06755       }
06756       ast_mutex_unlock(&p->lock);
06757 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
06758    } else if (!strcasecmp(data, "no_media_path")) {
06759       ast_mutex_lock(&p->lock);
06760       switch (p->sig) {
06761       case SIG_PRI_LIB_HANDLE_CASES:
06762          /*
06763           * TRUE if the call is on hold or is call waiting because
06764           * there is no media path available.
06765           */
06766          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
06767          break;
06768       default:
06769          *buf = '\0';
06770          res = -1;
06771          break;
06772       }
06773       ast_mutex_unlock(&p->lock);
06774 #endif   /* defined(HAVE_PRI) */
06775    } else {
06776       *buf = '\0';
06777       res = -1;
06778    }
06779 
06780    return res;
06781 }

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

Definition at line 6813 of file chan_dahdi.c.

References ast_channel_tech_pvt(), ast_log, ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, dahdi_pvt::channel, dahdi_ec_disable(), dahdi_ec_enable(), dahdi_subchannel::dfd, dahdi_pvt::echocanon, errno, dahdi_pvt::lock, LOG_WARNING, parse_buffers_policy(), SUB_REAL, and dahdi_pvt::subs.

06814 {
06815    struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
06816    int res = 0;
06817 
06818    if (!p) {
06819       /* No private structure! */
06820       return -1;
06821    }
06822 
06823    if (!strcasecmp(data, "buffers")) {
06824       int num_bufs, policy;
06825 
06826       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
06827          struct dahdi_bufferinfo bi = {
06828             .txbufpolicy = policy,
06829             .rxbufpolicy = policy,
06830             .bufsize = p->bufsize,
06831             .numbufs = num_bufs,
06832          };
06833          int bpres;
06834 
06835          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06836             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
06837          } else {
06838             p->bufferoverrideinuse = 1;
06839          }
06840       } else {
06841          res = -1;
06842       }
06843    } else if (!strcasecmp(data, "echocan_mode")) {
06844       if (!strcasecmp(value, "on")) {
06845          ast_mutex_lock(&p->lock);
06846          dahdi_ec_enable(p);
06847          ast_mutex_unlock(&p->lock);
06848       } else if (!strcasecmp(value, "off")) {
06849          ast_mutex_lock(&p->lock);
06850          dahdi_ec_disable(p);
06851          ast_mutex_unlock(&p->lock);
06852 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
06853       } else if (!strcasecmp(value, "fax")) {
06854          int blah = 1;
06855 
06856          ast_mutex_lock(&p->lock);
06857          if (!p->echocanon) {
06858             dahdi_ec_enable(p);
06859          }
06860          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
06861             ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
06862          }
06863          ast_mutex_unlock(&p->lock);
06864       } else if (!strcasecmp(value, "voice")) {
06865          int blah = 0;
06866 
06867          ast_mutex_lock(&p->lock);
06868          if (!p->echocanon) {
06869             dahdi_ec_enable(p);
06870          }
06871          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
06872             ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
06873          }
06874          ast_mutex_unlock(&p->lock);
06875 #endif
06876       } else {
06877          ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
06878          res = -1;
06879       }
06880    } else {
06881       res = -1;
06882    }
06883 
06884    return res;
06885 }

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

Avoid the silly dahdi_getevent which ignores a bunch of events.

Definition at line 612 of file chan_dahdi.c.

Referenced by __dahdi_exception(), analog_ss_thread(), dahdi_handle_event(), do_monitor(), mwi_thread(), my_distinctive_ring(), my_get_callerid(), and my_get_event().

00613 {
00614    int j;
00615    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00616       return -1;
00617    return j;
00618 }

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

Definition at line 7137 of file chan_dahdi.c.

References ast_async_goto(), ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_channel_lock, ast_channel_macrocontext(), ast_channel_name(), ast_channel_tech_pvt(), ast_channel_unlock, AST_CONTROL_ANSWER, ast_debug, ast_dsp_set_features(), ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_free, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_verb, dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, dahdi_pvt::callprogress, CALLPROGRESS_FAX, dahdi_pvt::callwaitcas, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_confmute(), dahdi_subchannel::dfd, dahdi_pvt::dsp, DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, errno, dahdi_subchannel::f, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, dahdi_pvt::faxhandled, ast_frame::frametype, ast_frame_subclass::integer, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, NULL, pbx_builtin_setvar_helper(), S_COR, S_OR, send_cwcidspill(), ast_frame::subclass, dahdi_pvt::subs, and dahdi_pvt::usefaxbuffers.

Referenced by dahdi_handle_event(), and dahdi_read().

07138 {
07139    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
07140    struct ast_frame *f = *dest;
07141 
07142    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07143       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07144       (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
07145 
07146    if (p->confirmanswer) {
07147       if (f->frametype == AST_FRAME_DTMF_END) {
07148          ast_debug(1, "Confirm answer on %s!\n", ast_channel_name(ast));
07149          /* Upon receiving a DTMF digit, consider this an answer confirmation instead
07150             of a DTMF digit */
07151          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07152          p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07153          /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
07154          p->confirmanswer = 0;
07155       } else {
07156          p->subs[idx].f.frametype = AST_FRAME_NULL;
07157          p->subs[idx].f.subclass.integer = 0;
07158       }
07159       *dest = &p->subs[idx].f;
07160    } else if (p->callwaitcas) {
07161       if (f->frametype == AST_FRAME_DTMF_END) {
07162          if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07163             ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07164             ast_free(p->cidspill);
07165             p->cidspill = NULL;
07166             send_cwcidspill(p);
07167          }
07168          p->callwaitcas = 0;
07169       }
07170       p->subs[idx].f.frametype = AST_FRAME_NULL;
07171       p->subs[idx].f.subclass.integer = 0;
07172       *dest = &p->subs[idx].f;
07173    } else if (f->subclass.integer == 'f') {
07174       if (f->frametype == AST_FRAME_DTMF_END) {
07175          /* Fax tone -- Handle and return NULL */
07176          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07177             /* If faxbuffers are configured, use them for the fax transmission */
07178             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07179                struct dahdi_bufferinfo bi = {
07180                   .txbufpolicy = p->faxbuf_policy,
07181                   .bufsize = p->bufsize,
07182                   .numbufs = p->faxbuf_no
07183                };
07184                int res;
07185 
07186                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07187                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
07188                } else {
07189                   p->bufferoverrideinuse = 1;
07190                }
07191             }
07192             p->faxhandled = 1;
07193             if (p->dsp) {
07194                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07195                ast_dsp_set_features(p->dsp, p->dsp_features);
07196                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
07197             }
07198             if (strcmp(ast_channel_exten(ast), "fax")) {
07199                const char *target_context = S_OR(ast_channel_macrocontext(ast), ast_channel_context(ast));
07200 
07201                /* We need to unlock 'ast' here because ast_exists_extension has the
07202                 * potential to start autoservice on the channel. Such action is prone
07203                 * to deadlock.
07204                 */
07205                ast_mutex_unlock(&p->lock);
07206                ast_channel_unlock(ast);
07207                if (ast_exists_extension(ast, target_context, "fax", 1,
07208                   S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
07209                   ast_channel_lock(ast);
07210                   ast_mutex_lock(&p->lock);
07211                   ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
07212                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
07213                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
07214                   if (ast_async_goto(ast, target_context, "fax", 1))
07215                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
07216                } else {
07217                   ast_channel_lock(ast);
07218                   ast_mutex_lock(&p->lock);
07219                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07220                }
07221             } else {
07222                ast_debug(1, "Already in a fax extension, not redirecting\n");
07223             }
07224          } else {
07225             ast_debug(1, "Fax already handled\n");
07226          }
07227          dahdi_confmute(p, 0);
07228       }
07229       p->subs[idx].f.frametype = AST_FRAME_NULL;
07230       p->subs[idx].f.subclass.integer = 0;
07231       *dest = &p->subs[idx].f;
07232    }
07233 }

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

Definition at line 7290 of file chan_dahdi.c.

References alloc_sub(), analog_ss_thread(), ast_party_caller::ani, ast_party_caller::ani2, dahdi_pvt::answeronpolarityswitch, ast_callid_threadstorage_auto(), ast_callid_threadstorage_auto_clean(), AST_CAUSE_NO_ANSWER, ast_channel_caller(), ast_channel_lock, ast_channel_name(), ast_channel_pbx(), ast_channel_rings_set(), ast_channel_softhangup_internal_flag_add(), ast_channel_tech_pvt(), ast_channel_trylock, ast_channel_unlock, AST_CONTROL_ANSWER, AST_CONTROL_OFFHOOK, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, ast_copy_string(), ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_free, ast_hangup(), ast_log, ast_mutex_lock, ast_mutex_unlock, ast_null_frame, ast_pthread_create_detached, ast_queue_hangup_with_cause(), ast_queue_hold(), ast_queue_unhold(), ast_setstate(), ast_softhangup(), AST_SOFTHANGUP_DEV, AST_SOFTHANGUP_EXPLICIT, AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DIALING_OFFHOOK, AST_STATE_DOWN, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strdup, ast_strlen_zero, ast_tvdiff_ms(), ast_tvnow(), ast_verb, attempt_transfer(), dahdi_pvt::callprogress, CALLPROGRESS_PROGRESS, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitingrepeat, CANPROGRESSDETECT, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, check_for_conference(), dahdi_pvt::cid_name, cid_name, dahdi_pvt::cid_num, cid_num, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cidcwexpire, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_conf_update(), dahdi_confmute(), dahdi_dial_str(), dahdi_ec_disable(), dahdi_ec_enable(), dahdi_get_event(), dahdi_get_index, dahdi_handle_dtmf(), dahdi_new(), DAHDI_OVERLAPDIAL_INCOMING, dahdi_ring_phone(), dahdi_set_hook(), dahdi_sig_pri_lib_handles(), dahdi_train_ec(), dahdi_pvt::dahditrcallerid, ast_frame::data, ast_frame::datalen, dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialednone, dahdi_pvt::dialing, DLA_LOCK, DLA_UNLOCK, dahdi_pvt::dop, dahdi_pvt::dsp, dahdi_pvt::echobreak, dahdi_pvt::echocanon, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, event2str(), dahdi_subchannel::f, dahdi_pvt::fake_event, dahdi_pvt::finaldial, dahdi_pvt::flashtime, ast_frame::frametype, get_alarms(), handle_alarms(), handle_clear_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), ast_party_caller::id, dahdi_pvt::inalarm, ast_frame_subclass::integer, dahdi_subchannel::inthreeway, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, MIN_MS_SINCE_FLASH, dahdi_pvt::mohsuggest, ast_party_id::name, dahdi_subchannel::needanswer, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, NULL, ast_party_id::number, ast_frame::offset, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pvt::owner, dahdi_subchannel::owner, dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pvt::polaritydelaytv, dahdi_pvt::polarityonanswerdelay, ast_frame::ptr, dahdi_pvt::pulsedial, dahdi_pvt::radio, restore_conference(), dahdi_pvt::ringt, dahdi_pvt::ringt_base, S_COR, ast_frame::samples, save_conference(), dahdi_pvt::sig, sig2str, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, SIG_PRI_CALL_LEVEL_PROCEEDING, sig_pri_chan_alarm_notify(), sig_pri_dial_complete(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, sig_ss7_set_alarm(), ast_frame::src, ast_party_name::str, ast_party_number::str, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, ast_frame::subclass, dahdi_pvt::subs, swap_subs(), dahdi_pvt::threewaycalling, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, unalloc_sub(), ast_party_name::valid, ast_party_number::valid, dahdi_pvt::waitingfordt, and dahdi_pvt::whichwink.

Referenced by __dahdi_exception().

07291 {
07292    int res, x;
07293    int idx, mysig;
07294    char *c;
07295    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
07296    pthread_t threadid;
07297    struct ast_channel *chan;
07298    struct ast_frame *f;
07299 
07300    idx = dahdi_get_index(ast, p, 0);
07301    if (idx < 0) {
07302       return &ast_null_frame;
07303    }
07304    mysig = p->sig;
07305    if (p->outsigmod > -1)
07306       mysig = p->outsigmod;
07307    p->subs[idx].f.frametype = AST_FRAME_NULL;
07308    p->subs[idx].f.subclass.integer = 0;
07309    p->subs[idx].f.datalen = 0;
07310    p->subs[idx].f.samples = 0;
07311    p->subs[idx].f.mallocd = 0;
07312    p->subs[idx].f.offset = 0;
07313    p->subs[idx].f.src = "dahdi_handle_event";
07314    p->subs[idx].f.data.ptr = NULL;
07315    f = &p->subs[idx].f;
07316 
07317    if (p->fake_event) {
07318       res = p->fake_event;
07319       p->fake_event = 0;
07320    } else
07321       res = dahdi_get_event(p->subs[idx].dfd);
07322 
07323    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07324 
07325    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07326       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07327       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07328 #if defined(HAVE_PRI)
07329       if (dahdi_sig_pri_lib_handles(p->sig)
07330          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07331          && p->pri
07332          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07333          /* absorb event */
07334       } else
07335 #endif   /* defined(HAVE_PRI) */
07336       {
07337          /* Unmute conference */
07338          dahdi_confmute(p, 0);
07339          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07340          p->subs[idx].f.subclass.integer = res & 0xff;
07341          dahdi_handle_dtmf(ast, idx, &f);
07342       }
07343       return f;
07344    }
07345 
07346    if (res & DAHDI_EVENT_DTMFDOWN) {
07347       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07348 #if defined(HAVE_PRI)
07349       if (dahdi_sig_pri_lib_handles(p->sig)
07350          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07351          && p->pri
07352          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07353          /* absorb event */
07354       } else
07355 #endif   /* defined(HAVE_PRI) */
07356       {
07357          /* Mute conference */
07358          dahdi_confmute(p, 1);
07359          p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07360          p->subs[idx].f.subclass.integer = res & 0xff;
07361          dahdi_handle_dtmf(ast, idx, &f);
07362       }
07363       return &p->subs[idx].f;
07364    }
07365 
07366    switch (res) {
07367    case DAHDI_EVENT_EC_DISABLED:
07368       ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07369       p->echocanon = 0;
07370       break;
07371 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07372    case DAHDI_EVENT_TX_CED_DETECTED:
07373       ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07374       break;
07375    case DAHDI_EVENT_RX_CED_DETECTED:
07376       ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07377       break;
07378    case DAHDI_EVENT_EC_NLP_DISABLED:
07379       ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07380       break;
07381    case DAHDI_EVENT_EC_NLP_ENABLED:
07382       ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07383       break;
07384 #endif
07385    case DAHDI_EVENT_BITSCHANGED:
07386 #ifdef HAVE_OPENR2
07387       if (p->sig != SIG_MFCR2) {
07388          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07389       } else {
07390          ast_debug(1, "bits changed in chan %d\n", p->channel);
07391          openr2_chan_handle_cas(p->r2chan);
07392       }
07393 #else
07394       ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07395 #endif
07396       break;
07397    case DAHDI_EVENT_PULSE_START:
07398       /* Stop tone if there's a pulse start and the PBX isn't started */
07399       if (!ast_channel_pbx(ast))
07400          tone_zone_play_tone(p->subs[idx].dfd, -1);
07401       break;
07402    case DAHDI_EVENT_DIALCOMPLETE:
07403       /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */
07404 #if defined(HAVE_PRI)
07405       if (dahdi_sig_pri_lib_handles(p->sig)) {
07406          if (p->inalarm) {
07407             break;
07408          }
07409          if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
07410             ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",
07411                ast_channel_name(ast), strerror(errno));
07412             return NULL;
07413          }
07414          if (x) {
07415             /* Still dialing in DAHDI driver */
07416             break;
07417          }
07418          /*
07419           * The ast channel is locked and the private may be locked more
07420           * than once.
07421           */
07422          sig_pri_dial_complete(p->sig_pvt, ast);
07423          break;
07424       }
07425 #endif   /* defined(HAVE_PRI) */
07426 #ifdef HAVE_OPENR2
07427       if ((p->sig & SIG_MFCR2) && p->r2chan && ast_channel_state(ast) != AST_STATE_UP) {
07428          /* we don't need to do anything for this event for R2 signaling
07429             if the call is being setup */
07430          break;
07431       }
07432 #endif
07433       if (p->inalarm) break;
07434       if ((p->radio || (p->oprmode < 0))) break;
07435       if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
07436          ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",ast_channel_name(ast), strerror(errno));
07437          return NULL;
07438       }
07439       if (!x) { /* if not still dialing in driver */
07440          dahdi_ec_enable(p);
07441          if (p->echobreak) {
07442             dahdi_train_ec(p);
07443             ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
07444             p->dop.op = DAHDI_DIAL_OP_REPLACE;
07445             res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
07446             p->echobreak = 0;
07447          } else {
07448             p->dialing = 0;
07449             if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
07450                /* if thru with dialing after offhook */
07451                if (ast_channel_state(ast) == AST_STATE_DIALING_OFFHOOK) {
07452                   ast_setstate(ast, AST_STATE_UP);
07453                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07454                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07455                   break;
07456                } else { /* if to state wait for offhook to dial rest */
07457                   /* we now wait for off hook */
07458                   ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
07459                }
07460             }
07461             if (ast_channel_state(ast) == AST_STATE_DIALING) {
07462                if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
07463                   ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
07464                } else if (p->confirmanswer || (!p->dialednone
07465                   && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
07466                      || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
07467                      || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
07468                      || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
07469                      || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
07470                      || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
07471                      || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
07472                      || (mysig == SIG_SF_FEATB)))) {
07473                   ast_setstate(ast, AST_STATE_RINGING);
07474                } else if (!p->answeronpolarityswitch) {
07475                   ast_setstate(ast, AST_STATE_UP);
07476                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07477                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07478                   /* If aops=0 and hops=1, this is necessary */
07479                   p->polarity = POLARITY_REV;
07480                } else {
07481                   /* Start clean, so we can catch the change to REV polarity when party answers */
07482                   p->polarity = POLARITY_IDLE;
07483                }
07484             }
07485          }
07486       }
07487       break;
07488    case DAHDI_EVENT_ALARM:
07489       switch (p->sig) {
07490 #if defined(HAVE_PRI)
07491       case SIG_PRI_LIB_HANDLE_CASES:
07492          sig_pri_chan_alarm_notify(p->sig_pvt, 0);
07493          break;
07494 #endif   /* defined(HAVE_PRI) */
07495 #if defined(HAVE_SS7)
07496       case SIG_SS7:
07497          sig_ss7_set_alarm(p->sig_pvt, 1);
07498          break;
07499 #endif   /* defined(HAVE_SS7) */
07500       default:
07501          p->inalarm = 1;
07502          break;
07503       }
07504       res = get_alarms(p);
07505       handle_alarms(p, res);
07506 #ifdef HAVE_PRI
07507       if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
07508          /* fall through intentionally */
07509       } else {
07510          break;
07511       }
07512 #endif
07513 #if defined(HAVE_SS7)
07514       if (p->sig == SIG_SS7)
07515          break;
07516 #endif   /* defined(HAVE_SS7) */
07517 #ifdef HAVE_OPENR2
07518       if (p->sig == SIG_MFCR2)
07519          break;
07520 #endif
07521    case DAHDI_EVENT_ONHOOK:
07522       if (p->radio) {
07523          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07524          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
07525          break;
07526       }
07527       if (p->oprmode < 0)
07528       {
07529          if (p->oprmode != -1) break;
07530          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
07531          {
07532             /* Make sure it starts ringing */
07533             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
07534             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
07535             save_conference(p->oprpeer);
07536             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07537          }
07538          break;
07539       }
07540       switch (p->sig) {
07541       case SIG_FXOLS:
07542       case SIG_FXOGS:
07543       case SIG_FXOKS:
07544          /* Check for some special conditions regarding call waiting */
07545          if (idx == SUB_REAL) {
07546             /* The normal line was hung up */
07547             if (p->subs[SUB_CALLWAIT].owner) {
07548                /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
07549                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
07550                ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
07551                unalloc_sub(p, SUB_CALLWAIT);
07552 #if 0
07553                p->subs[idx].needanswer = 0;
07554                p->subs[idx].needringing = 0;
07555 #endif
07556                p->callwaitingrepeat = 0;
07557                p->cidcwexpire = 0;
07558                p->cid_suppress_expire = 0;
07559                p->owner = NULL;
07560                /* Don't start streaming audio yet if the incoming call isn't up yet */
07561                if (ast_channel_state(p->subs[SUB_REAL].owner) != AST_STATE_UP)
07562                   p->dialing = 1;
07563                dahdi_ring_phone(p);
07564             } else if (p->subs[SUB_THREEWAY].owner) {
07565                unsigned int mssinceflash;
07566                /* Here we have to retain the lock on both the main channel, the 3-way channel, and
07567                   the private structure -- not especially easy or clean */
07568                while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
07569                   /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
07570                   DLA_UNLOCK(&p->lock);
07571                   CHANNEL_DEADLOCK_AVOIDANCE(ast);
07572                   /* We can grab ast and p in that order, without worry.  We should make sure
07573                      nothing seriously bad has happened though like some sort of bizarre double
07574                      masquerade! */
07575                   DLA_LOCK(&p->lock);
07576                   if (p->owner != ast) {
07577                      ast_log(LOG_WARNING, "This isn't good...\n");
07578                      return NULL;
07579                   }
07580                }
07581                if (!p->subs[SUB_THREEWAY].owner) {
07582                   ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
07583                   return NULL;
07584                }
07585                mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
07586                ast_debug(1, "Last flash was %u ms ago\n", mssinceflash);
07587                if (mssinceflash < MIN_MS_SINCE_FLASH) {
07588                   /* It hasn't been long enough since the last flashook.  This is probably a bounce on
07589                      hanging up.  Hangup both channels now */
07590                   if (p->subs[SUB_THREEWAY].owner)
07591                      ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
07592                   ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
07593                   ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
07594                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07595                } else if ((ast_channel_pbx(ast)) || (ast_channel_state(ast) == AST_STATE_UP)) {
07596                   if (p->transfer) {
07597                      /* In any case this isn't a threeway call anymore */
07598                      p->subs[SUB_REAL].inthreeway = 0;
07599                      p->subs[SUB_THREEWAY].inthreeway = 0;
07600                      /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
07601                      if (!p->transfertobusy && ast_channel_state(ast) == AST_STATE_BUSY) {
07602                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07603                         /* Swap subs and dis-own channel */
07604                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
07605                         p->owner = NULL;
07606                         /* Ring the phone */
07607                         dahdi_ring_phone(p);
07608                      } else if (!attempt_transfer(p)) {
07609                         /*
07610                          * Transfer successful.  Don't actually hang up at this point.
07611                          * Let our channel legs of the calls die off as the transfer
07612                          * percolates through the core.
07613                          */
07614                         break;
07615                      }
07616                   } else {
07617                      ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
07618                      if (p->subs[SUB_THREEWAY].owner)
07619                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07620                   }
07621                } else {
07622                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07623                   /* Swap subs and dis-own channel */
07624                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
07625                   p->owner = NULL;
07626                   /* Ring the phone */
07627                   dahdi_ring_phone(p);
07628                }
07629             }
07630          } else {
07631             ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
07632          }
07633          /* Fall through */
07634       default:
07635          dahdi_ec_disable(p);
07636          return NULL;
07637       }
07638       break;
07639    case DAHDI_EVENT_RINGOFFHOOK:
07640       if (p->inalarm) break;
07641       if (p->oprmode < 0)
07642       {
07643          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
07644          {
07645             /* Make sure it stops ringing */
07646             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
07647             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
07648             restore_conference(p->oprpeer);
07649          }
07650          break;
07651       }
07652       if (p->radio)
07653       {
07654          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07655          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
07656          break;
07657       }
07658       /* for E911, its supposed to wait for offhook then dial
07659          the second half of the dial string */
07660       if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast_channel_state(ast) == AST_STATE_DIALING_OFFHOOK)) {
07661          c = strchr(p->dialdest, '/');
07662          if (c)
07663             c++;
07664          else
07665             c = p->dialdest;
07666          if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
07667          else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
07668          if (strlen(p->dop.dialstr) > 4) {
07669             memset(p->echorest, 'w', sizeof(p->echorest) - 1);
07670             strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
07671             p->echorest[sizeof(p->echorest) - 1] = '\0';
07672             p->echobreak = 1;
07673             p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
07674          } else
07675             p->echobreak = 0;
07676          if (dahdi_dial_str(p, p->dop.op, p->dop.dialstr)) {
07677             x = DAHDI_ONHOOK;
07678             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07679             return NULL;
07680          }
07681          p->dialing = 1;
07682          return &p->subs[idx].f;
07683       }
07684       switch (p->sig) {
07685       case SIG_FXOLS:
07686       case SIG_FXOGS:
07687       case SIG_FXOKS:
07688          switch (ast_channel_state(ast)) {
07689          case AST_STATE_RINGING:
07690             dahdi_ec_enable(p);
07691             dahdi_train_ec(p);
07692             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07693             p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07694             /* Make sure it stops ringing */
07695             p->subs[SUB_REAL].needringing = 0;
07696             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
07697             ast_debug(1, "channel %d answered\n", p->channel);
07698 
07699             /* Cancel any running CallerID spill */
07700             ast_free(p->cidspill);
07701             p->cidspill = NULL;
07702             restore_conference(p);
07703 
07704             p->dialing = 0;
07705             p->callwaitcas = 0;
07706             if (p->confirmanswer) {
07707                /* Ignore answer if "confirm answer" is enabled */
07708                p->subs[idx].f.frametype = AST_FRAME_NULL;
07709                p->subs[idx].f.subclass.integer = 0;
07710             } else if (!ast_strlen_zero(p->dop.dialstr)) {
07711                /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
07712                res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
07713                if (res) {
07714                   p->dop.dialstr[0] = '\0';
07715                   return NULL;
07716                } else {
07717                   ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
07718                   p->subs[idx].f.frametype = AST_FRAME_NULL;
07719                   p->subs[idx].f.subclass.integer = 0;
07720                   p->dialing = 1;
07721                }
07722                p->dop.dialstr[0] = '\0';
07723                ast_setstate(ast, AST_STATE_DIALING);
07724             } else
07725                ast_setstate(ast, AST_STATE_UP);
07726             return &p->subs[idx].f;
07727          case AST_STATE_DOWN:
07728             ast_setstate(ast, AST_STATE_RING);
07729             ast_channel_rings_set(ast, 1);
07730             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07731             p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
07732             ast_debug(1, "channel %d picked up\n", p->channel);
07733             return &p->subs[idx].f;
07734          case AST_STATE_UP:
07735             /* Make sure it stops ringing */
07736             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
07737             /* Okay -- probably call waiting*/
07738             ast_queue_unhold(p->owner);
07739             p->subs[idx].needunhold = 1;
07740             break;
07741          case AST_STATE_RESERVED:
07742             /* Start up dialtone */
07743             if (has_voicemail(p))
07744                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
07745             else
07746                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
07747             break;
07748          default:
07749             ast_log(LOG_WARNING, "FXO phone off hook in weird state %u??\n", ast_channel_state(ast));
07750          }
07751          break;
07752       case SIG_FXSLS:
07753       case SIG_FXSGS:
07754       case SIG_FXSKS:
07755          if (ast_channel_state(ast) == AST_STATE_RING) {
07756             p->ringt = p->ringt_base;
07757          }
07758 
07759          /* If we get a ring then we cannot be in
07760           * reversed polarity. So we reset to idle */
07761          ast_debug(1, "Setting IDLE polarity due "
07762             "to ring. Old polarity was %d\n",
07763             p->polarity);
07764          p->polarity = POLARITY_IDLE;
07765 
07766          /* Fall through */
07767       case SIG_EM:
07768       case SIG_EM_E1:
07769       case SIG_EMWINK:
07770       case SIG_FEATD:
07771       case SIG_FEATDMF:
07772       case SIG_FEATDMF_TA:
07773       case SIG_E911:
07774       case SIG_FGC_CAMA:
07775       case SIG_FGC_CAMAMF:
07776       case SIG_FEATB:
07777       case SIG_SF:
07778       case SIG_SFWINK:
07779       case SIG_SF_FEATD:
07780       case SIG_SF_FEATDMF:
07781       case SIG_SF_FEATB:
07782          if (ast_channel_state(ast) == AST_STATE_PRERING)
07783             ast_setstate(ast, AST_STATE_RING);
07784          if ((ast_channel_state(ast) == AST_STATE_DOWN) || (ast_channel_state(ast) == AST_STATE_RING)) {
07785             ast_debug(1, "Ring detected\n");
07786             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07787             p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
07788          } else if (p->outgoing && ((ast_channel_state(ast) == AST_STATE_RINGING) || (ast_channel_state(ast) == AST_STATE_DIALING