Wed Oct 28 13:31:58 2009

Asterisk developer's documentation


chan_dahdi.c File Reference

DAHDI for Pseudo TDM. More...

#include "asterisk.h"
#include <values.h>
#include <sys/signal.h>
#include <sys/ioctl.h>
#include <math.h>
#include <ctype.h>
#include <dahdi/user.h>
#include <dahdi/tonezone.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/cdr.h"
#include "asterisk/cel.h"
#include "asterisk/features.h"
#include "asterisk/musiconhold.h"
#include "asterisk/say.h"
#include "asterisk/tdd.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/astdb.h"
#include "asterisk/manager.h"
#include "asterisk/causes.h"
#include "asterisk/term.h"
#include "asterisk/utils.h"
#include "asterisk/transcap.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/smdi.h"
#include "asterisk/astobj.h"
#include "asterisk/event.h"
#include "asterisk/devicestate.h"
#include "asterisk/paths.h"

Include 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_distRings
struct  dahdi_pvt
struct  dahdi_subchannel
struct  distRingData
struct  mwi_thread_data
struct  mwisend_info
struct  ringContextData

Defines

#define ASCII_BYTES_PER_CHAR   80
#define AST_LAW(p)   (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
#define CALLPROGRESS_FAX   (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
#define CALLPROGRESS_FAX_INCOMING   4
#define CALLPROGRESS_FAX_OUTGOING   2
#define CALLPROGRESS_PROGRESS   1
#define CALLWAITING_REPEAT_SAMPLES   ( (10000 * 8) / READ_SIZE)
#define CALLWAITING_SILENT_SAMPLES   ( (300 * 8) / READ_SIZE)
#define 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 CONF_USER_REAL   (1 << 0)
#define CONF_USER_THIRDCALL   (1 << 1)
#define DEFAULT_CIDRINGS   1
 Typically, how many rings before we should send Caller*ID.
#define DEFAULT_RINGT   ( (8000 * 8) / READ_SIZE)
#define END_SILENCE_LEN   400
#define FORMAT   "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
#define FORMAT   "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
#define FORMAT2   "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
#define FORMAT2   "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
#define GET_CHANNEL(p)   ((p)->channel)
#define HANGUP   1
#define HEADER_LEN   ((HEADER_MS + TRAILER_MS) * 8)
#define HEADER_MS   50
#define ISTRUNK(p)
#define MASK_AVAIL   (1 << 0)
#define MASK_INUSE   (1 << 1)
#define MAX_CHANLIST_LEN   80
#define MAX_SLAVES   4
#define MIN_MS_SINCE_FLASH   ( (2000) )
#define NEED_MFDETECT(p)   (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
 Signaling types that need to use MF detection should be placed in this macro.
#define NUM_CADENCE_MAX   25
#define NUM_SPANS   32
#define POLARITY_IDLE   0
#define POLARITY_REV   1
#define PROC_DAHDI_OPT_NOCHAN   (1 << 0)
#define PROC_DAHDI_OPT_NOWARN   (1 << 1)
#define READ_SIZE   160
#define sig2str   dahdi_sig2str
#define SIG_BRI   (0x2000000 | DAHDI_SIG_CLEAR)
#define SIG_BRI_PTMP   (0X4000000 | DAHDI_SIG_CLEAR)
#define SIG_E911   (0x1000000 | DAHDI_SIG_EM)
#define SIG_EM   DAHDI_SIG_EM
#define SIG_EM_E1   DAHDI_SIG_EM_E1
#define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
#define SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
#define SIG_FEATD   (0x0200000 | DAHDI_SIG_EM)
#define SIG_FEATDMF   (0x0400000 | DAHDI_SIG_EM)
#define SIG_FEATDMF_TA   (0x2000000 | DAHDI_SIG_EM)
#define SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
#define SIG_FGC_CAMAMF   (0x8000000 | DAHDI_SIG_EM)
#define SIG_FXOGS   DAHDI_SIG_FXOGS
#define SIG_FXOKS   DAHDI_SIG_FXOKS
#define SIG_FXOLS   DAHDI_SIG_FXOLS
#define SIG_FXSGS   DAHDI_SIG_FXSGS
#define SIG_FXSKS   DAHDI_SIG_FXSKS
#define SIG_FXSLS   DAHDI_SIG_FXSLS
#define SIG_MFCR2   DAHDI_SIG_CAS
#define SIG_PRI   DAHDI_SIG_CLEAR
#define SIG_PRI_LIB_HANDLE_CASES
#define SIG_SF   DAHDI_SIG_SF
#define SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
#define SIG_SF_FEATD   (0x0200000 | DAHDI_SIG_SF)
#define SIG_SF_FEATDMF   (0x0400000 | DAHDI_SIG_SF)
#define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
#define SIG_SS7   (0x1000000 | DAHDI_SIG_CLEAR)
#define SMDI_MD_WAIT_TIMEOUT   1500
#define SUB_CALLWAIT   1
#define SUB_REAL   0
#define SUB_THREEWAY   2
#define TRAILER_MS   5
#define TRANSFER   0

Enumerations

enum  DAHDI_IFLIST { DAHDI_IFLIST_NONE, DAHDI_IFLIST_MAIN }
enum  mwisend_states {
  MWI_SEND_NULL = 0, MWI_SEND_SA, MWI_SEND_SA_WAIT, MWI_SEND_PAUSE,
  MWI_SEND_SPILL, MWI_SEND_CLEANUP, MWI_SEND_DONE
}

Functions

static struct ast_frame__dahdi_exception (struct ast_channel *ast)
static void __reg_module (void)
static int __unload_module (void)
static void __unreg_module (void)
static int action_dahdidialoffhook (struct mansession *s, const struct message *m)
static int action_dahdidndoff (struct mansession *s, const struct message *m)
static int action_dahdidndon (struct mansession *s, const struct message *m)
static int action_dahdirestart (struct mansession *s, const struct message *m)
static int action_dahdishowchannels (struct mansession *s, const struct message *m)
static int action_transfer (struct mansession *s, const struct message *m)
static int action_transferhangup (struct mansession *s, const struct message *m)
static char * alarm2str (int alm)
static int alloc_sub (struct dahdi_pvt *p, int x)
static int analog_lib_handles (int signalling, int radio, int oprmode)
static void * analog_ss_thread (void *data)
static int analog_tone_to_dahditone (enum analog_tone tone)
static int analogsub_to_dahdisub (enum analog_sub analogsub)
static int attempt_transfer (struct dahdi_pvt *p)
static int available (struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *reason, int *channelmatched, int *groupmatched)
static int build_channels (struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
static int bump_gains (struct dahdi_pvt *p)
static int calc_energy (const unsigned char *buf, int len, int law)
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 int dahdi_answer (struct ast_channel *ast)
static enum ast_bridge_result dahdi_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
static int dahdi_call (struct ast_channel *ast, char *rdest, int timeout)
static int dahdi_callwait (struct ast_channel *ast)
static struct dahdi_chan_conf dahdi_chan_conf_default (void)
static void dahdi_close (int fd)
static void dahdi_close_sub (struct dahdi_pvt *chan_pvt, int sub_num)
static int dahdi_confmute (struct dahdi_pvt *p, int muted)
static char * dahdi_destroy_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int dahdi_destroy_channel_bynum (int channel)
static int dahdi_digit_begin (struct ast_channel *ast, char digit)
static int dahdi_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
static void dahdi_disable_ec (struct dahdi_pvt *p)
static int dahdi_dnd (struct dahdi_pvt *dahdichan, int flag)
 enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
static void dahdi_enable_ec (struct dahdi_pvt *p)
static struct ast_framedahdi_exception (struct ast_channel *ast)
static int dahdi_fake_event (struct dahdi_pvt *p, int mode)
static int dahdi_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static int dahdi_func_read (struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
static int dahdi_func_write (struct ast_channel *chan, const char *function, char *data, const char *value)
static int dahdi_get_event (int fd)
 Avoid the silly dahdi_getevent which ignores a bunch of events.
static int dahdi_get_index (struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
static void dahdi_handle_dtmfup (struct ast_channel *ast, int idx, struct ast_frame **dest)
static struct ast_framedahdi_handle_event (struct ast_channel *ast)
static int dahdi_hangup (struct ast_channel *ast)
static void dahdi_iflist_extract (struct dahdi_pvt *pvt)
static void dahdi_iflist_insert (struct dahdi_pvt *pvt)
static int dahdi_indicate (struct ast_channel *chan, int condition, const void *data, size_t datalen)
static void dahdi_link (struct dahdi_pvt *slave, struct dahdi_pvt *master)
static struct ast_channeldahdi_new (struct dahdi_pvt *, int, int, int, int, int, const char *)
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, void *data)
static struct ast_framedahdi_read (struct ast_channel *ast)
static struct ast_channeldahdi_request (const char *type, int format, const struct ast_channel *requestor, void *data, int *cause)
static int dahdi_restart (void)
static char * dahdi_restart_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int dahdi_ring_phone (struct dahdi_pvt *p)
static int dahdi_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 int dahdi_sig_pri_lib_handles (int signaling)
static void dahdi_softhangup_all (void)
static void dahdi_train_ec (struct dahdi_pvt *p)
static void dahdi_unlink (struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
static int dahdi_wait_event (int fd)
 Avoid the silly dahdi_waitevent which ignores a bunch of events.
static int dahdi_wink (struct dahdi_pvt *p, int index)
static int dahdi_write (struct ast_channel *ast, struct ast_frame *frame)
static enum analog_event dahdievent_to_analogevent (int event)
static enum analog_sigtype dahdisig_to_analogsig (int sig)
static void destroy_all_channels (void)
static void destroy_channel (struct dahdi_pvt *cur, int now)
static void destroy_dahdi_pvt (struct dahdi_pvt *pvt)
static int digit_to_dtmfindex (char digit)
static void disable_dtmf_detect (struct dahdi_pvt *p)
static void * do_monitor (void *data)
static int drc_sample (int sample, float drc)
static struct dahdi_pvtduplicate_pseudo (struct dahdi_pvt *src)
static void enable_dtmf_detect (struct dahdi_pvt *p)
static const char * event2str (int event)
static void fill_rxgain (struct dahdi_gains *g, float gain, float drc, int law)
static void fill_txgain (struct dahdi_gains *g, float gain, float drc, int law)
static struct dahdi_pvtfind_channel (int channel)
static int get_alarms (struct dahdi_pvt *p)
static void handle_alarms (struct dahdi_pvt *p, int alms)
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 isourconf (struct dahdi_pvt *p, struct dahdi_subchannel *c)
static int isslavenative (struct dahdi_pvt *p, struct dahdi_pvt **out)
static int load_module (void)
static struct dahdi_pvtmkintf (int channel, const struct dahdi_chan_conf *conf, int reloading)
static void mwi_event_cb (const struct ast_event *event, void *userdata)
static int mwi_send_init (struct dahdi_pvt *pvt)
static int mwi_send_process_buffer (struct dahdi_pvt *pvt, int num_read)
static int mwi_send_process_event (struct dahdi_pvt *pvt, int event)
static void * mwi_thread (void *data)
static void my_all_subchannels_hungup (void *pvt)
static int my_allocate_sub (void *pvt, enum analog_sub analogsub)
static 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_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 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_dtmfup (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 int my_has_voicemail (void *pvt)
static void my_increase_ss_count (void)
static int my_is_dialing (void *pvt, enum analog_sub sub)
static int my_is_off_hook (void *pvt)
static void my_lock_private (void *pvt)
static 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_callerid *cid)
static void my_set_cadence (void *pvt, int *cidrings, struct ast_channel *ast)
static void my_set_confirmanswer (void *pvt, int flag)
static void my_set_dialing (void *pvt, int flag)
static int my_set_echocanceller (void *pvt, int enable)
static int my_set_linear_mode (void *pvt, int idx, int linear_mode)
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 int my_stop_callwait (void *pvt)
static int my_stop_cid_detect (void *pvt)
static void my_swap_subchannels (void *pvt, enum analog_sub a, struct ast_channel *ast_a, enum analog_sub b, struct ast_channel *ast_b)
static int my_train_echocanceller (void *pvt)
static int my_unallocate_sub (void *pvt, enum analog_sub analogsub)
static void my_unlock_private (void *pvt)
static int my_wait_event (void *pvt)
static int my_wink (void *pvt, enum analog_sub sub)
static void notify_message (char *mailbox_full, int thereornot)
 Send MWI state change.
static int parse_buffers_policy (const char *parse, int *num_buffers, int *policy)
static int process_dahdi (struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
static void process_echocancel (struct dahdi_chan_conf *confp, const char *data, unsigned int line)
static int reload (void)
static int reset_conf (struct dahdi_pvt *p)
static int restart_monitor (void)
static int restore_conference (struct dahdi_pvt *p)
static int restore_gains (struct dahdi_pvt *p)
static int revert_fax_buffers (struct dahdi_pvt *p, struct ast_channel *ast)
static int save_conference (struct dahdi_pvt *p)
static int send_callerid (struct dahdi_pvt *p)
static int send_cwcidspill (struct dahdi_pvt *p)
static int set_actual_gain (int fd, int chan, float rxgain, float txgain, float rxdrc, float txdrc, int law)
static int set_actual_rxgain (int fd, int chan, float gain, float drc, int law)
static int set_actual_txgain (int fd, int chan, float gain, float drc, int law)
static int setup_dahdi (int reload)
static int sigtype_to_signalling (int sigtype)
static void swap_subs (struct dahdi_pvt *p, int a, int b)
static int unalloc_sub (struct dahdi_pvt *p, int x)
static int unload_module (void)
static int update_conf (struct dahdi_pvt *p)
static void wakeup_sub (struct dahdi_pvt *p, int a)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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, .load = load_module, .unload = unload_module, .reload = reload, }
struct {
   int   alarm
   char *   name
alarms []
static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}}
static struct ast_module_infoast_module_info = &__mod_info
static struct dahdi_ring_cadence cadences [NUM_CADENCE_MAX]
static int cidrings [NUM_CADENCE_MAX]
 cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on.
static const char config [] = "chan_dahdi.conf"
static struct analog_callback dahdi_analog_callbacks
static struct ast_cli_entry dahdi_cli []
static struct ast_channel_tech dahdi_tech
static struct ast_jb_conf default_jbconf
static char defaultcic [64] = ""
static char defaultozz [64] = ""
static int distinctiveringaftercid = 0
static int dtmfcid_level = 256
static const char *const events []
static int firstdigittimeout = 16000
 Wait up to 16 seconds for first digit (FXO logic).
static int gendigittimeout = 8000
 How long to wait for following digits (FXO logic).
static struct ast_jb_conf global_jbconf
static int ifcount = 0
static struct dahdi_pvtifend = NULL
static struct dahdi_pvtiflist = NULL
static ast_mutex_t iflock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
 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 = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
 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 parkinglot [AST_MAX_EXTENSION] = ""
static char progzone [10] = ""
static ast_mutex_t restart_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
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 = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static const char *const subnames []
static const char tdesc [] = "DAHDI Telephony Driver"
static int usedistinctiveringdetection = 0
static int user_has_defined_cadences = 0


Detailed Description

DAHDI for Pseudo TDM.

Author:
Mark Spencer <markster@digium.com>
Connects to the DAHDI telephony library as well as libpri. Libpri is optional and needed only if you are going to use ISDN connections.

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

See also
Todo:
Deprecate the "musiconhold" configuration option post 1.4

Definition in file chan_dahdi.c.


Define Documentation

#define ASCII_BYTES_PER_CHAR   80

Referenced by dahdi_sendtext().

#define AST_LAW (  )     (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)

#define CALLPROGRESS_FAX   (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)

#define CALLPROGRESS_FAX_INCOMING   4

Definition at line 365 of file chan_dahdi.c.

Referenced by dahdi_new(), and process_dahdi().

#define CALLPROGRESS_FAX_OUTGOING   2

Definition at line 364 of file chan_dahdi.c.

Referenced by dahdi_new(), and process_dahdi().

#define CALLPROGRESS_PROGRESS   1

Definition at line 363 of file chan_dahdi.c.

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

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

10,000 ms

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

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

Definition at line 396 of file chan_dahdi.c.

Referenced by dahdi_new().

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

Definition at line 397 of file chan_dahdi.c.

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

#define CHAN_PSEUDO   -2

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

500 ms

Definition at line 503 of file chan_dahdi.c.

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 660 of file chan_dahdi.c.

#define CONF_USER_THIRDCALL   (1 << 1)

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

Define if you want to check the hook state for an FXO (FXS signalled) interface before dialing on it. Certain FXO interfaces always think they're out of service with this method however.

Definition at line 295 of file chan_dahdi.c.

Referenced by dahdi_chan_conf_default().

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

8,000 ms

Definition at line 505 of file chan_dahdi.c.

#define END_SILENCE_LEN   400

Referenced by dahdi_sendtext().

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

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

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

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

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

Definition at line 1467 of file chan_dahdi.c.

Referenced by my_complete_conference_update(), and update_conf().

#define HANGUP   1

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

#define MASK_INUSE   (1 << 1)

Channel currently in use

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

Referenced by process_dahdi().

#define MAX_SLAVES   4

#define MIN_MS_SINCE_FLASH   ( (2000) )

2000 ms

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

Referenced by analog_ss_thread(), and dahdi_new().

#define NUM_CADENCE_MAX   25

Definition at line 368 of file chan_dahdi.c.

Referenced by process_dahdi().

#define NUM_SPANS   32

Definition at line 358 of file chan_dahdi.c.

Referenced by destroy_all_channels().

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

Referenced by process_dahdi(), and setup_dahdi().

#define PROC_DAHDI_OPT_NOWARN   (1 << 1)

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

Definition at line 15701 of file chan_dahdi.c.

Referenced by process_dahdi(), and setup_dahdi().

#define READ_SIZE   160

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

Definition at line 496 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 sig2str   dahdi_sig2str

#define SIG_BRI   (0x2000000 | DAHDI_SIG_CLEAR)

Definition at line 344 of file chan_dahdi.c.

Referenced by dahdi_sig2str(), and process_dahdi().

#define SIG_BRI_PTMP   (0X4000000 | DAHDI_SIG_CLEAR)

Definition at line 345 of file chan_dahdi.c.

Referenced by dahdi_sig2str(), and process_dahdi().

#define SIG_E911   (0x1000000 | DAHDI_SIG_EM)

#define SIG_EM   DAHDI_SIG_EM

#define SIG_EM_E1   DAHDI_SIG_EM_E1

#define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)

#define SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)

#define SIG_FEATD   (0x0200000 | DAHDI_SIG_EM)

#define SIG_FEATDMF   (0x0400000 | DAHDI_SIG_EM)

#define SIG_FEATDMF_TA   (0x2000000 | DAHDI_SIG_EM)

#define SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)

#define SIG_FGC_CAMAMF   (0x8000000 | DAHDI_SIG_EM)

#define SIG_FXOGS   DAHDI_SIG_FXOGS

#define SIG_FXOKS   DAHDI_SIG_FXOKS

#define SIG_FXOLS   DAHDI_SIG_FXOLS

#define SIG_FXSGS   DAHDI_SIG_FXSGS

#define SIG_FXSKS   DAHDI_SIG_FXSKS

#define SIG_FXSLS   DAHDI_SIG_FXSLS

#define SIG_MFCR2   DAHDI_SIG_CAS

#define SIG_PRI   DAHDI_SIG_CLEAR

Definition at line 343 of file chan_dahdi.c.

Referenced by dahdi_indicate(), dahdi_sig2str(), mkintf(), and process_dahdi().

#define SIG_PRI_LIB_HANDLE_CASES

#define SIG_SF   DAHDI_SIG_SF

#define SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)

#define SIG_SF_FEATD   (0x0200000 | DAHDI_SIG_SF)

#define SIG_SF_FEATDMF   (0x0400000 | DAHDI_SIG_SF)

#define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)

#define SIG_SS7   (0x1000000 | DAHDI_SIG_CLEAR)

#define SMDI_MD_WAIT_TIMEOUT   1500

Definition at line 253 of file chan_dahdi.c.

Referenced by analog_ss_thread().

#define SUB_CALLWAIT   1

#define SUB_REAL   0

Active call

Definition at line 615 of file chan_dahdi.c.

Referenced by __dahdi_exception(), analog_ss_thread(), analogsub_to_dahdisub(), attempt_transfer(), build_device(), bump_gains(), check_for_conference(), close_call(), close_client(), dahdi_answer(), dahdi_bridge(), dahdi_call(), dahdi_confmute(), dahdi_destroy_channel_bynum(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_func_write(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_read(), dahdi_request(), dahdi_restart(), dahdi_ring_phone(), dahdi_set_hwgain(), dahdi_set_swgain(), dahdi_setoption(), dahdi_show_channel(), dahdi_train_ec(), dahdi_unlink(), destroy_dahdi_pvt(), disable_dtmf_detect(), do_monitor(), duplicate_pseudo(), enable_dtmf_detect(), find_subchannel_by_name(), get_alarms(), handle_init_event(), HandleCallIncoming(), HandleCallOutgoing(), key_call(), key_dial_page(), mkintf(), mwi_send_init(), mwi_send_process_buffer(), mwi_send_process_event(), mwi_thread(), my_all_subchannels_hungup(), my_complete_conference_update(), my_flash(), my_get_callerid(), my_get_event(), my_is_off_hook(), my_off_hook(), my_set_cadence(), my_start(), my_start_cid_detect(), my_stop_cid_detect(), my_wait_event(), my_wink(), process_request(), rcv_mac_addr(), reset_conf(), restore_conference(), restore_gains(), revert_fax_buffers(), save_conference(), send_callerid(), TransferCallStep1(), unistim_do_senddigit(), unistim_hangup(), unistim_senddigit_end(), and update_conf().

#define SUB_THREEWAY   2

#define TRAILER_MS   5

Referenced by dahdi_sendtext().

#define TRANSFER   0


Enumeration Type Documentation

Specify the lists dahdi_pvt can be put in.

Enumerator:
DAHDI_IFLIST_NONE  The dahdi_pvt is not in any list.
DAHDI_IFLIST_MAIN  The dahdi_pvt is in the main interface list

Definition at line 684 of file chan_dahdi.c.

00684                   {
00685    DAHDI_IFLIST_NONE,   /*!< The dahdi_pvt is not in any list. */
00686    DAHDI_IFLIST_MAIN,   /*!< The dahdi_pvt is in the main interface list */
00687 #if defined(HAVE_PRI)
00688    DAHDI_IFLIST_NO_B_CHAN, /*!< The dahdi_pvt is in a no B channel interface list */
00689 #endif   /* defined(HAVE_PRI) */
00690 };

Enumerator:
MWI_SEND_NULL 
MWI_SEND_SA 
MWI_SEND_SA_WAIT 
MWI_SEND_PAUSE 
MWI_SEND_SPILL 
MWI_SEND_CLEANUP 
MWI_SEND_DONE 

Definition at line 668 of file chan_dahdi.c.

00668              {
00669    MWI_SEND_NULL = 0,
00670    MWI_SEND_SA,
00671    MWI_SEND_SA_WAIT,
00672    MWI_SEND_PAUSE,
00673    MWI_SEND_SPILL,
00674    MWI_SEND_CLEANUP,
00675    MWI_SEND_DONE,
00676 } mwisend_states;


Function Documentation

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

Definition at line 7799 of file chan_dahdi.c.

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

Referenced by dahdi_exception(), and dahdi_read().

07800 {
07801    int res;
07802    int idx;
07803    struct ast_frame *f;
07804    int usedindex = -1;
07805    struct dahdi_pvt *p = ast->tech_pvt;
07806 
07807    idx = dahdi_get_index(ast, p, 1);
07808 
07809    p->subs[idx].f.frametype = AST_FRAME_NULL;
07810    p->subs[idx].f.datalen = 0;
07811    p->subs[idx].f.samples = 0;
07812    p->subs[idx].f.mallocd = 0;
07813    p->subs[idx].f.offset = 0;
07814    p->subs[idx].f.subclass = 0;
07815    p->subs[idx].f.delivery = ast_tv(0,0);
07816    p->subs[idx].f.src = "dahdi_exception";
07817    p->subs[idx].f.data.ptr = NULL;
07818 
07819 
07820    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
07821       /* If nobody owns us, absorb the event appropriately, otherwise
07822          we loop indefinitely.  This occurs when, during call waiting, the
07823          other end hangs up our channel so that it no longer exists, but we
07824          have neither FLASH'd nor ONHOOK'd to signify our desire to
07825          change to the other channel. */
07826       if (p->fake_event) {
07827          res = p->fake_event;
07828          p->fake_event = 0;
07829       } else
07830          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
07831       /* Switch to real if there is one and this isn't something really silly... */
07832       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
07833          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
07834          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
07835          p->owner = p->subs[SUB_REAL].owner;
07836          if (p->owner && ast_bridged_channel(p->owner))
07837             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
07838          p->subs[SUB_REAL].needunhold = 1;
07839       }
07840       switch (res) {
07841       case DAHDI_EVENT_ONHOOK:
07842          dahdi_disable_ec(p);
07843          if (p->owner) {
07844             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
07845             dahdi_ring_phone(p);
07846             p->callwaitingrepeat = 0;
07847             p->cidcwexpire = 0;
07848          } else
07849             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
07850          update_conf(p);
07851          break;
07852       case DAHDI_EVENT_RINGOFFHOOK:
07853          dahdi_enable_ec(p);
07854          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07855          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
07856             p->subs[SUB_REAL].needanswer = 1;
07857             p->dialing = 0;
07858          }
07859          break;
07860       case DAHDI_EVENT_HOOKCOMPLETE:
07861       case DAHDI_EVENT_RINGERON:
07862       case DAHDI_EVENT_RINGEROFF:
07863          /* Do nothing */
07864          break;
07865       case DAHDI_EVENT_WINKFLASH:
07866          p->flashtime = ast_tvnow();
07867          if (p->owner) {
07868             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
07869             if (p->owner->_state != AST_STATE_UP) {
07870                /* Answer if necessary */
07871                usedindex = dahdi_get_index(p->owner, p, 0);
07872                if (usedindex > -1) {
07873                   p->subs[usedindex].needanswer = 1;
07874                }
07875                ast_setstate(p->owner, AST_STATE_UP);
07876             }
07877             p->callwaitingrepeat = 0;
07878             p->cidcwexpire = 0;
07879             if (ast_bridged_channel(p->owner))
07880                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
07881             p->subs[SUB_REAL].needunhold = 1;
07882          } else
07883             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
07884          update_conf(p);
07885          break;
07886       default:
07887          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
07888       }
07889       f = &p->subs[idx].f;
07890       return f;
07891    }
07892    if (!(p->radio || (p->oprmode < 0)))
07893       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
07894    /* If it's not us, return NULL immediately */
07895    if (ast != p->owner) {
07896       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
07897       f = &p->subs[idx].f;
07898       return f;
07899    }
07900    f = dahdi_handle_event(ast);
07901 
07902    /* tell the cdr this zap device hung up */
07903    if (f == NULL) {
07904       ast_set_hangupsource(ast, ast->name, 0);
07905    }
07906 
07907    return f;
07908 }

static void __reg_module ( void   )  [static]

Definition at line 17090 of file chan_dahdi.c.

static int __unload_module ( void   )  [static]

Definition at line 15494 of file chan_dahdi.c.

References ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_destroy(), ast_manager_unregister(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_unregister_application(), destroy_all_channels(), iflock, dahdi_pvt::master, monlock, dahdi_pvt::next, and dahdi_pvt::owner.

Referenced by load_module(), and unload_module().

15495 {
15496    struct dahdi_pvt *p;
15497 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15498    int i, j;
15499 #endif
15500 
15501 #ifdef HAVE_PRI
15502    for (i = 0; i < NUM_SPANS; i++) {
15503       if (pris[i].pri.master != AST_PTHREADT_NULL)
15504          pthread_cancel(pris[i].pri.master);
15505    }
15506    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
15507    ast_unregister_application(dahdi_send_keypad_facility_app);
15508 #ifdef HAVE_PRI_PROG_W_CAUSE
15509    ast_unregister_application(dahdi_send_callrerouting_facility_app);
15510 #endif
15511 #endif
15512 #if defined(HAVE_SS7)
15513    for (i = 0; i < NUM_SPANS; i++) {
15514       if (linksets[i].master != AST_PTHREADT_NULL)
15515          pthread_cancel(linksets[i].master);
15516       }
15517    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
15518 #endif
15519 #if defined(HAVE_OPENR2)
15520    dahdi_r2_destroy_links();
15521    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
15522    ast_unregister_application(dahdi_accept_r2_call_app);
15523 #endif
15524 
15525    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
15526    ast_manager_unregister("DAHDIDialOffhook");
15527    ast_manager_unregister("DAHDIHangup");
15528    ast_manager_unregister("DAHDITransfer");
15529    ast_manager_unregister("DAHDIDNDoff");
15530    ast_manager_unregister("DAHDIDNDon");
15531    ast_manager_unregister("DAHDIShowChannels");
15532    ast_manager_unregister("DAHDIRestart");
15533    ast_channel_unregister(&dahdi_tech);
15534 
15535    /* Hangup all interfaces if they have an owner */
15536    ast_mutex_lock(&iflock);
15537    for (p = iflist; p; p = p->next) {
15538       if (p->owner)
15539          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
15540    }
15541    ast_mutex_unlock(&iflock);
15542 
15543    ast_mutex_lock(&monlock);
15544    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15545       pthread_cancel(monitor_thread);
15546       pthread_kill(monitor_thread, SIGURG);
15547       pthread_join(monitor_thread, NULL);
15548    }
15549    monitor_thread = AST_PTHREADT_STOP;
15550    ast_mutex_unlock(&monlock);
15551 
15552    destroy_all_channels();
15553 
15554 #if defined(HAVE_PRI)
15555    for (i = 0; i < NUM_SPANS; i++) {
15556       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
15557          pthread_join(pris[i].pri.master, NULL);
15558       for (j = 0; j < NUM_DCHANS; j++) {
15559          dahdi_close_pri_fd(&(pris[i]), j);
15560       }
15561    }
15562 #endif
15563 
15564 #if defined(HAVE_SS7)
15565    for (i = 0; i < NUM_SPANS; i++) {
15566       if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
15567          pthread_join(linksets[i].master, NULL);
15568       for (j = 0; j < NUM_DCHANS; j++) {
15569          dahdi_close_ss7_fd(&(linksets[i]), j);
15570       }
15571    }
15572 #endif
15573    ast_cond_destroy(&ss_thread_complete);
15574    return 0;
15575 }

static void __unreg_module ( void   )  [static]

Definition at line 17090 of file chan_dahdi.c.

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

Definition at line 14936 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(), and dahdi_pvt::owner.

Referenced by load_module().

14937 {
14938    struct dahdi_pvt *p = NULL;
14939    const char *channel = astman_get_header(m, "DAHDIChannel");
14940    const char *number = astman_get_header(m, "Number");
14941    int i;
14942 
14943    if (ast_strlen_zero(channel)) {
14944       astman_send_error(s, m, "No channel specified");
14945       return 0;
14946    }
14947    if (ast_strlen_zero(number)) {
14948       astman_send_error(s, m, "No number specified");
14949       return 0;
14950    }
14951    p = find_channel(atoi(channel));
14952    if (!p) {
14953       astman_send_error(s, m, "No such channel");
14954       return 0;
14955    }
14956    if (!p->owner) {
14957       astman_send_error(s, m, "Channel does not have it's owner");
14958       return 0;
14959    }
14960    for (i = 0; i < strlen(number); i++) {
14961       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
14962       dahdi_queue_frame(p, &f, NULL);
14963    }
14964    astman_send_ack(s, m, "DAHDIDialOffhook");
14965    return 0;
14966 }

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

Definition at line 14879 of file chan_dahdi.c.

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

Referenced by load_module().

14880 {
14881    struct dahdi_pvt *p = NULL;
14882    const char *channel = astman_get_header(m, "DAHDIChannel");
14883 
14884    if (ast_strlen_zero(channel)) {
14885       astman_send_error(s, m, "No channel specified");
14886       return 0;
14887    }
14888    p = find_channel(atoi(channel));
14889    if (!p) {
14890       astman_send_error(s, m, "No such channel");
14891       return 0;
14892    }
14893    dahdi_dnd(p, 0);
14894    astman_send_ack(s, m, "DND Disabled");
14895    return 0;
14896 }

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

Definition at line 14860 of file chan_dahdi.c.

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

Referenced by load_module().

14861 {
14862    struct dahdi_pvt *p = NULL;
14863    const char *channel = astman_get_header(m, "DAHDIChannel");
14864 
14865    if (ast_strlen_zero(channel)) {
14866       astman_send_error(s, m, "No channel specified");
14867       return 0;
14868    }
14869    p = find_channel(atoi(channel));
14870    if (!p) {
14871       astman_send_error(s, m, "No such channel");
14872       return 0;
14873    }
14874    dahdi_dnd(p, 1);
14875    astman_send_ack(s, m, "DND Enabled");
14876    return 0;
14877 }

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

Definition at line 14196 of file chan_dahdi.c.

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

Referenced by load_module().

14197 {
14198    if (dahdi_restart() != 0) {
14199       astman_send_error(s, m, "Failed rereading DAHDI configuration");
14200       return 1;
14201    }
14202    astman_send_ack(s, m, "DAHDIRestart: Success");
14203    return 0;
14204 }

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

Definition at line 14968 of file chan_dahdi.c.

References ast_channel::accountcode, alarm2str(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_ack(), dahdi_pvt::channel, dahdi_pvt::context, dahdi_dnd(), get_alarms(), iflock, ast_channel::name, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::sig, sig2str, and ast_channel::uniqueid.

Referenced by load_module().

14969 {
14970    struct dahdi_pvt *tmp = NULL;
14971    const char *id = astman_get_header(m, "ActionID");
14972    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
14973    char idText[256] = "";
14974    int channels = 0;
14975    int dahdichanquery = -1;
14976    if (!ast_strlen_zero(dahdichannel)) {
14977       dahdichanquery = atoi(dahdichannel);
14978    }
14979 
14980    astman_send_ack(s, m, "DAHDI channel status will follow");
14981    if (!ast_strlen_zero(id))
14982       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
14983 
14984    ast_mutex_lock(&iflock);
14985 
14986    for (tmp = iflist; tmp; tmp = tmp->next) {
14987       if (tmp->channel > 0) {
14988          int alm;
14989 
14990          /* If a specific channel is queried for, only deliver status for that channel */
14991          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
14992             continue;
14993 
14994          alm = get_alarms(tmp);
14995          channels++;
14996          if (tmp->owner) {
14997             /* Add data if we have a current call */
14998             astman_append(s,
14999                "Event: DAHDIShowChannels\r\n"
15000                "DAHDIChannel: %d\r\n"
15001                "Channel: %s\r\n"
15002                "Uniqueid: %s\r\n"
15003                "AccountCode: %s\r\n"
15004                "Signalling: %s\r\n"
15005                "SignallingCode: %d\r\n"
15006                "Context: %s\r\n"
15007                "DND: %s\r\n"
15008                "Alarm: %s\r\n"
15009                "%s"
15010                "\r\n",
15011                tmp->channel,
15012                tmp->owner->name,
15013                tmp->owner->uniqueid,
15014                tmp->owner->accountcode,
15015                sig2str(tmp->sig),
15016                tmp->sig,
15017                tmp->context,
15018                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15019                alarm2str(alm), idText);
15020          } else {
15021             astman_append(s,
15022                "Event: DAHDIShowChannels\r\n"
15023                "DAHDIChannel: %d\r\n"
15024                "Signalling: %s\r\n"
15025                "SignallingCode: %d\r\n"
15026                "Context: %s\r\n"
15027                "DND: %s\r\n"
15028                "Alarm: %s\r\n"
15029                "%s"
15030                "\r\n",
15031                tmp->channel, sig2str(tmp->sig), tmp->sig,
15032                tmp->context,
15033                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15034                alarm2str(alm), idText);
15035          }
15036       }
15037    }
15038 
15039    ast_mutex_unlock(&iflock);
15040 
15041    astman_append(s,
15042       "Event: DAHDIShowChannelsComplete\r\n"
15043       "%s"
15044       "Items: %d\r\n"
15045       "\r\n",
15046       idText,
15047       channels);
15048    return 0;
15049 }

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

Definition at line 14898 of file chan_dahdi.c.

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

Referenced by load_module().

14899 {
14900    struct dahdi_pvt *p = NULL;
14901    const char *channel = astman_get_header(m, "DAHDIChannel");
14902 
14903    if (ast_strlen_zero(channel)) {
14904       astman_send_error(s, m, "No channel specified");
14905       return 0;
14906    }
14907    p = find_channel(atoi(channel));
14908    if (!p) {
14909       astman_send_error(s, m, "No such channel");
14910       return 0;
14911    }
14912    dahdi_fake_event(p,TRANSFER);
14913    astman_send_ack(s, m, "DAHDITransfer");
14914    return 0;
14915 }

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

Definition at line 14917 of file chan_dahdi.c.

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

Referenced by load_module().

14918 {
14919    struct dahdi_pvt *p = NULL;
14920    const char *channel = astman_get_header(m, "DAHDIChannel");
14921 
14922    if (ast_strlen_zero(channel)) {
14923       astman_send_error(s, m, "No channel specified");
14924       return 0;
14925    }
14926    p = find_channel(atoi(channel));
14927    if (!p) {
14928       astman_send_error(s, m, "No such channel");
14929       return 0;
14930    }
14931    dahdi_fake_event(p,HANGUP);
14932    astman_send_ack(s, m, "DAHDIHangup");
14933    return 0;
14934 }

static char* alarm2str ( int  alm  )  [static]

Definition at line 3780 of file chan_dahdi.c.

References alarms, and ARRAY_LEN.

Referenced by action_dahdishowchannels(), and handle_alarms().

03781 {
03782    int x;
03783    for (x = 0; x < ARRAY_LEN(alarms); x++) {
03784       if (alarms[x].alarm & alm)
03785          return alarms[x].name;
03786    }
03787    return alm ? "Unknown Alarm" : "No Alarm";
03788 }

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

Definition at line 3584 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(), build_device(), dahdi_handle_event(), HandleCallOutgoing(), my_allocate_sub(), and rcv_mac_addr().

03585 {
03586    struct dahdi_bufferinfo bi;
03587    int res;
03588    if (p->subs[x].dfd >= 0) {
03589       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
03590       return -1;
03591    }
03592 
03593    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
03594    if (p->subs[x].dfd <= -1) {
03595       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
03596       return -1;
03597    }
03598 
03599    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
03600    if (!res) {
03601       bi.txbufpolicy = p->buf_policy;
03602       bi.rxbufpolicy = p->buf_policy;
03603       bi.numbufs = p->buf_no;
03604       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
03605       if (res < 0) {
03606          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
03607       }
03608    } else
03609       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
03610 
03611    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
03612       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
03613       dahdi_close_sub(p, x);
03614       p->subs[x].dfd = -1;
03615       return -1;
03616    }
03617    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
03618    return 0;
03619 }

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

Definition at line 3865 of file chan_dahdi.c.

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

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

03866 {
03867    switch (signalling) {
03868    case SIG_FXOLS:
03869    case SIG_FXOGS:
03870    case SIG_FXOKS:
03871    case SIG_FXSLS:
03872    case SIG_FXSGS:
03873    case SIG_FXSKS:
03874    case SIG_EMWINK:
03875    case SIG_EM:
03876    case SIG_EM_E1:
03877    case SIG_FEATD:
03878    case SIG_FEATDMF:
03879    case SIG_E911:
03880    case SIG_FGC_CAMA:
03881    case SIG_FGC_CAMAMF:
03882    case SIG_FEATB:
03883    case SIG_SFWINK:
03884    case SIG_SF:
03885    case SIG_SF_FEATD:
03886    case SIG_SF_FEATDMF:
03887    case SIG_FEATDMF_TA:
03888    case SIG_SF_FEATB:
03889       break;
03890    default:
03891       /* The rest of the function should cover the remainder of signalling types */
03892       return 0;
03893    }
03894 
03895    if (radio)
03896       return 0;
03897 
03898    if (oprmode)
03899       return 0;
03900 
03901    return 1;
03902 }

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

Definition at line 8790 of file chan_dahdi.c.

References ast_channel::_state, alloc_sub(), ARRAY_LEN, ast_bridged_channel(), ast_canmatch_extension(), ast_cond_signal(), AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, ast_dsp_digitreset(), ast_dsp_free(), ast_dsp_set_digitmode(), ast_exists_extension(), AST_FRAME_DTMF, ast_free, ast_frfree, ast_hangup(), ast_ignore_pattern(), AST_LAW, ast_log(), ast_masq_park_call(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_mutex_lock(), ast_mutex_unlock(), ast_parking_ext(), ast_pbx_run(), ast_pickup_call(), ast_pickup_ext(), ast_queue_control(), ast_read(), ast_safe_sleep(), ast_set_callerid(), ast_setstate(), ast_shrink_phone_number(), ast_smdi_md_message_destroy(), ast_smdi_md_message_wait(), AST_STATE_PRERING, AST_STATE_RING, AST_STATE_RINGING, ast_streamfile(), ast_strlen_zero(), ast_verb, ast_waitfor(), ast_waitfordigit(), ast_waitstream(), ASTOBJ_UNREF, buf, bump_gains(), dahdi_pvt::call_forward, callerid_feed(), callerid_feed_jp(), callerid_free(), callerid_get(), callerid_get_dtmf(), callerid_new(), ast_smdi_md_message::calling_st, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::cancallforward, dahdi_pvt::canpark, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_name, dahdi_pvt::cid_name, ast_callerid::cid_num, 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, ast_channel::context, ringContextData::contextData, dahdi_dnd(), dahdi_enable_ec(), 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_channel::exten, ast_frame::frametype, ast_smdi_md_message::fwd_st, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::hardwaredtmf, dahdi_pvt::hidecallerid, dahdi_pvt::immediate, ISTRUNK, ast_channel::language, len(), dahdi_subchannel::linear, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, my_getsigstr(), my_handle_notify_message(), ast_channel::name, name, NEED_MFDETECT, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, quit, distRingData::range, restore_gains(), distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, ast_channel::rings, dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, sig2str, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_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(), ast_channel::tech, ast_channel::tech_pvt, dahdi_pvt::transfer, ast_smdi_md_message::type, unalloc_sub(), dahdi_pvt::use_callerid, dahdi_pvt::use_smdi, and dahdi_pvt::usedistinctiveringdetection.

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

08791 {
08792    struct ast_channel *chan = data;
08793    struct dahdi_pvt *p = chan->tech_pvt;
08794    char exten[AST_MAX_EXTENSION] = "";
08795    char exten2[AST_MAX_EXTENSION] = "";
08796    unsigned char buf[256];
08797    char dtmfcid[300];
08798    char dtmfbuf[300];
08799    struct callerid_state *cs = NULL;
08800    char *name = NULL, *number = NULL;
08801    int distMatches;
08802    int curRingData[3];
08803    int receivedRingT;
08804    int counter1;
08805    int counter;
08806    int samples = 0;
08807    struct ast_smdi_md_message *smdi_msg = NULL;
08808    int flags = 0;
08809    int i;
08810    int timeout;
08811    int getforward = 0;
08812    char *s1, *s2;
08813    int len = 0;
08814    int res;
08815    int idx;
08816 
08817    ast_mutex_lock(&ss_thread_lock);
08818    ss_thread_count++;
08819    ast_mutex_unlock(&ss_thread_lock);
08820    /* in the bizarre case where the channel has become a zombie before we
08821       even get started here, abort safely
08822    */
08823    if (!p) {
08824       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
08825       ast_hangup(chan);
08826       goto quit;
08827    }
08828    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
08829    idx = dahdi_get_index(chan, p, 1);
08830    if (idx < 0) {
08831       ast_log(LOG_WARNING, "Huh?\n");
08832       ast_hangup(chan);
08833       goto quit;
08834    }
08835    if (p->dsp)
08836       ast_dsp_digitreset(p->dsp);
08837    switch (p->sig) {
08838    case SIG_FEATD:
08839    case SIG_FEATDMF:
08840    case SIG_FEATDMF_TA:
08841    case SIG_E911:
08842    case SIG_FGC_CAMAMF:
08843    case SIG_FEATB:
08844    case SIG_EMWINK:
08845    case SIG_SF_FEATD:
08846    case SIG_SF_FEATDMF:
08847    case SIG_SF_FEATB:
08848    case SIG_SFWINK:
08849       if (dahdi_wink(p, idx))
08850          goto quit;
08851       /* Fall through */
08852    case SIG_EM:
08853    case SIG_EM_E1:
08854    case SIG_SF:
08855    case SIG_FGC_CAMA:
08856       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08857       if (p->dsp)
08858          ast_dsp_digitreset(p->dsp);
08859       /* set digit mode appropriately */
08860       if (p->dsp) {
08861          if (NEED_MFDETECT(p))
08862             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
08863          else
08864             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
08865       }
08866       memset(dtmfbuf, 0, sizeof(dtmfbuf));
08867       /* Wait for the first digit only if immediate=no */
08868       if (!p->immediate)
08869          /* Wait for the first digit (up to 5 seconds). */
08870          res = ast_waitfordigit(chan, 5000);
08871       else
08872          res = 0;
08873       if (res > 0) {
08874          /* save first char */
08875          dtmfbuf[0] = res;
08876          switch (p->sig) {
08877          case SIG_FEATD:
08878          case SIG_SF_FEATD:
08879             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
08880             if (res > 0)
08881                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
08882             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08883             break;
08884          case SIG_FEATDMF_TA:
08885             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
08886             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08887             if (dahdi_wink(p, idx)) goto quit;
08888             dtmfbuf[0] = 0;
08889             /* Wait for the first digit (up to 5 seconds). */
08890             res = ast_waitfordigit(chan, 5000);
08891             if (res <= 0) break;
08892             dtmfbuf[0] = res;
08893             /* fall through intentionally */
08894          case SIG_FEATDMF:
08895          case SIG_E911:
08896          case SIG_FGC_CAMAMF:
08897          case SIG_SF_FEATDMF:
08898             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
08899             /* if international caca, do it again to get real ANO */
08900             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
08901             {
08902                if (dahdi_wink(p, idx)) goto quit;
08903                dtmfbuf[0] = 0;
08904                /* Wait for the first digit (up to 5 seconds). */
08905                res = ast_waitfordigit(chan, 5000);
08906                if (res <= 0) break;
08907                dtmfbuf[0] = res;
08908                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
08909             }
08910             if (res > 0) {
08911                /* if E911, take off hook */
08912                if (p->sig == SIG_E911)
08913                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08914                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
08915             }
08916             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08917             break;
08918          case SIG_FEATB:
08919          case SIG_SF_FEATB:
08920             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
08921             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08922             break;
08923          case SIG_EMWINK:
08924             /* if we received a '*', we are actually receiving Feature Group D
08925                dial syntax, so use that mode; otherwise, fall through to normal
08926                mode
08927             */
08928             if (res == '*') {
08929                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
08930                if (res > 0)
08931                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
08932                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08933                break;
08934             }
08935          default:
08936             /* If we got the first digit, get the rest */
08937             len = 1;
08938             dtmfbuf[len] = '\0';
08939             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
08940                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
08941                   timeout = matchdigittimeout;
08942                } else {
08943                   timeout = gendigittimeout;
08944                }
08945                res = ast_waitfordigit(chan, timeout);
08946                if (res < 0) {
08947                   ast_debug(1, "waitfordigit returned < 0...\n");
08948                   ast_hangup(chan);
08949                   goto quit;
08950                } else if (res) {
08951                   dtmfbuf[len++] = res;
08952                   dtmfbuf[len] = '\0';
08953                } else {
08954                   break;
08955                }
08956             }
08957             break;
08958          }
08959       }
08960       if (res == -1) {
08961          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
08962          ast_hangup(chan);
08963          goto quit;
08964       } else if (res < 0) {
08965          ast_debug(1, "Got hung up before digits finished\n");
08966          ast_hangup(chan);
08967          goto quit;
08968       }
08969 
08970       if (p->sig == SIG_FGC_CAMA) {
08971          char anibuf[100];
08972 
08973          if (ast_safe_sleep(chan,1000) == -1) {
08974             ast_hangup(chan);
08975             goto quit;
08976          }
08977          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08978          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
08979          res = my_getsigstr(chan, anibuf, "#", 10000);
08980          if ((res > 0) && (strlen(anibuf) > 2)) {
08981             if (anibuf[strlen(anibuf) - 1] == '#')
08982                anibuf[strlen(anibuf) - 1] = 0;
08983             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
08984          }
08985          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
08986       }
08987 
08988       ast_copy_string(exten, dtmfbuf, sizeof(exten));
08989       if (ast_strlen_zero(exten))
08990          ast_copy_string(exten, "s", sizeof(exten));
08991       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
08992          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
08993          if (exten[0] == '*') {
08994             char *stringp=NULL;
08995             ast_copy_string(exten2, exten, sizeof(exten2));
08996             /* Parse out extension and callerid */
08997             stringp=exten2 +1;
08998             s1 = strsep(&stringp, "*");
08999             s2 = strsep(&stringp, "*");
09000             if (s2) {
09001                if (!ast_strlen_zero(p->cid_num))
09002                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09003                else
09004                   ast_set_callerid(chan, s1, NULL, s1);
09005                ast_copy_string(exten, s2, sizeof(exten));
09006             } else
09007                ast_copy_string(exten, s1, sizeof(exten));
09008          } else if (p->sig == SIG_FEATD)
09009             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
09010       }
09011       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
09012          if (exten[0] == '*') {
09013             char *stringp=NULL;
09014             ast_copy_string(exten2, exten, sizeof(exten2));
09015             /* Parse out extension and callerid */
09016             stringp=exten2 +1;
09017             s1 = strsep(&stringp, "#");
09018             s2 = strsep(&stringp, "#");
09019             if (s2) {
09020                if (!ast_strlen_zero(p->cid_num))
09021                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09022                else
09023                   if (*(s1 + 2))
09024                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
09025                ast_copy_string(exten, s2 + 1, sizeof(exten));
09026             } else
09027                ast_copy_string(exten, s1 + 2, sizeof(exten));
09028          } else
09029             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
09030       }
09031       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
09032          if (exten[0] == '*') {
09033             char *stringp=NULL;
09034             ast_copy_string(exten2, exten, sizeof(exten2));
09035             /* Parse out extension and callerid */
09036             stringp=exten2 +1;
09037             s1 = strsep(&stringp, "#");
09038             s2 = strsep(&stringp, "#");
09039             if (s2 && (*(s2 + 1) == '0')) {
09040                if (*(s2 + 2))
09041                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
09042             }
09043             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
09044             else ast_copy_string(exten, "911", sizeof(exten));
09045          } else
09046             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
09047       }
09048       if (p->sig == SIG_FEATB) {
09049          if (exten[0] == '*') {
09050             char *stringp=NULL;
09051             ast_copy_string(exten2, exten, sizeof(exten2));
09052             /* Parse out extension and callerid */
09053             stringp=exten2 +1;
09054             s1 = strsep(&stringp, "#");
09055             ast_copy_string(exten, exten2 + 1, sizeof(exten));
09056          } else
09057             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
09058       }
09059       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
09060          dahdi_wink(p, idx);
09061          /* some switches require a minimum guard time between
09062             the last FGD wink and something that answers
09063             immediately. This ensures it */
09064          if (ast_safe_sleep(chan,100)) goto quit;
09065       }
09066       dahdi_enable_ec(p);
09067       if (NEED_MFDETECT(p)) {
09068          if (p->dsp) {
09069             if (!p->hardwaredtmf)
09070                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09071             else {
09072                ast_dsp_free(p->dsp);
09073                p->dsp = NULL;
09074             }
09075          }
09076       }
09077 
09078       if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
09079          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
09080          if (p->dsp) ast_dsp_digitreset(p->dsp);
09081          res = ast_pbx_run(chan);
09082          if (res) {
09083             ast_log(LOG_WARNING, "PBX exited non-zero\n");
09084             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09085          }
09086          goto quit;
09087       } else {
09088          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
09089          sleep(2);
09090          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
09091          if (res < 0)
09092             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
09093          else
09094             sleep(1);
09095          res = ast_streamfile(chan, "ss-noservice", chan->language);
09096          if (res >= 0)
09097             ast_waitstream(chan, "");
09098          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09099          ast_hangup(chan);
09100          goto quit;
09101       }
09102       break;
09103    case SIG_FXOLS:
09104    case SIG_FXOGS:
09105    case SIG_FXOKS:
09106       /* Read the first digit */
09107       timeout = firstdigittimeout;
09108       /* If starting a threeway call, never timeout on the first digit so someone
09109          can use flash-hook as a "hold" feature */
09110       if (p->subs[SUB_THREEWAY].owner)
09111          timeout = 999999;
09112       while (len < AST_MAX_EXTENSION-1) {
09113          /* Read digit unless it's supposed to be immediate, in which case the
09114             only answer is 's' */
09115          if (p->immediate)
09116             res = 's';
09117          else
09118             res = ast_waitfordigit(chan, timeout);
09119          timeout = 0;
09120          if (res < 0) {
09121             ast_debug(1, "waitfordigit returned < 0...\n");
09122             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09123             ast_hangup(chan);
09124             goto quit;
09125          } else if (res) {
09126             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
09127             exten[len++]=res;
09128             exten[len] = '\0';
09129          }
09130          if (!ast_ignore_pattern(chan->context, exten))
09131             tone_zone_play_tone(p->subs[idx].dfd, -1);
09132          else
09133             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
09134          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
09135             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
09136                if (getforward) {
09137                   /* Record this as the forwarding extension */
09138                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
09139                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
09140                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09141                   if (res)
09142                      break;
09143                   usleep(500000);
09144                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09145                   sleep(1);
09146                   memset(exten, 0, sizeof(exten));
09147                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
09148                   len = 0;
09149                   getforward = 0;
09150                } else {
09151                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09152                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
09153                   if (!ast_strlen_zero(p->cid_num)) {
09154                      if (!p->hidecallerid)
09155                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09156                      else
09157                         ast_set_callerid(chan, NULL, NULL, p->cid_num);
09158                   }
09159                   if (!ast_strlen_zero(p->cid_name)) {
09160                      if (!p->hidecallerid)
09161                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
09162                   }
09163                   ast_setstate(chan, AST_STATE_RING);
09164                   dahdi_enable_ec(p);
09165                   res = ast_pbx_run(chan);
09166                   if (res) {
09167                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
09168                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09169                   }
09170                   goto quit;
09171                }
09172             } else {
09173                /* It's a match, but they just typed a digit, and there is an ambiguous match,
09174                   so just set the timeout to matchdigittimeout and wait some more */
09175                timeout = matchdigittimeout;
09176             }
09177          } else if (res == 0) {
09178             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
09179             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09180             dahdi_wait_event(p->subs[idx].dfd);
09181             ast_hangup(chan);
09182             goto quit;
09183          } else if (p->callwaiting && !strcmp(exten, "*70")) {
09184             ast_verb(3, "Disabling call waiting on %s\n", chan->name);
09185             /* Disable call waiting if enabled */
09186             p->callwaiting = 0;
09187             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09188             if (res) {
09189                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
09190                   chan->name, strerror(errno));
09191             }
09192             len = 0;
09193             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
09194             memset(exten, 0, sizeof(exten));
09195             timeout = firstdigittimeout;
09196 
09197          } else if (!strcmp(exten,ast_pickup_ext())) {
09198             /* Scan all channels and see if there are any
09199              * ringing channels that have call groups
09200              * that equal this channels pickup group
09201              */
09202             if (idx == SUB_REAL) {
09203                /* Switch us from Third call to Call Wait */
09204                if (p->subs[SUB_THREEWAY].owner) {
09205                   /* If you make a threeway call and the *8# a call, it should actually
09206                      look like a callwait */
09207                   alloc_sub(p, SUB_CALLWAIT);
09208                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
09209                   unalloc_sub(p, SUB_THREEWAY);
09210                }
09211                dahdi_enable_ec(p);
09212                if (ast_pickup_call(chan)) {
09213                   ast_debug(1, "No call pickup possible...\n");
09214                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09215                   dahdi_wait_event(p->subs[idx].dfd);
09216                }
09217                ast_hangup(chan);
09218                goto quit;
09219             } else {
09220                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
09221                ast_hangup(chan);
09222                goto quit;
09223             }
09224 
09225          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
09226             ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
09227             /* Disable Caller*ID if enabled */
09228             p->hidecallerid = 1;
09229             if (chan->cid.cid_num)
09230                ast_free(chan->cid.cid_num);
09231             chan->cid.cid_num = NULL;
09232             if (chan->cid.cid_name)
09233                ast_free(chan->cid.cid_name);
09234             chan->cid.cid_name = NULL;
09235             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09236             if (res) {
09237                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
09238                   chan->name, strerror(errno));
09239             }
09240             len = 0;
09241             memset(exten, 0, sizeof(exten));
09242             timeout = firstdigittimeout;
09243          } else if (p->callreturn && !strcmp(exten, "*69")) {
09244             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09245             break;
09246          } else if (!strcmp(exten, "*78")) {
09247             dahdi_dnd(p, 1);
09248             /* Do not disturb */
09249             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09250             getforward = 0;
09251             memset(exten, 0, sizeof(exten));
09252             len = 0;
09253          } else if (!strcmp(exten, "*79")) {
09254             dahdi_dnd(p, 0);
09255             /* Do not disturb */
09256             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09257             getforward = 0;
09258             memset(exten, 0, sizeof(exten));
09259             len = 0;
09260          } else if (p->cancallforward && !strcmp(exten, "*72")) {
09261             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09262             getforward = 1;
09263             memset(exten, 0, sizeof(exten));
09264             len = 0;
09265          } else if (p->cancallforward && !strcmp(exten, "*73")) {
09266             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
09267             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09268             memset(p->call_forward, 0, sizeof(p->call_forward));
09269             getforward = 0;
09270             memset(exten, 0, sizeof(exten));
09271             len = 0;
09272          } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
09273                   p->subs[SUB_THREEWAY].owner &&
09274                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
09275             /* This is a three way call, the main call being a real channel,
09276                and we're parking the first call. */
09277             ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
09278             ast_verb(3, "Parking call to '%s'\n", chan->name);
09279             break;
09280          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
09281             ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
09282             /* Enable Caller*ID if enabled */
09283             p->hidecallerid = 0;
09284             if (chan->cid.cid_num)
09285                ast_free(chan->cid.cid_num);
09286             chan->cid.cid_num = NULL;
09287             if (chan->cid.cid_name)
09288                ast_free(chan->cid.cid_name);
09289             chan->cid.cid_name = NULL;
09290             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
09291             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09292             if (res) {
09293                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
09294                   chan->name, strerror(errno));
09295             }
09296             len = 0;
09297             memset(exten, 0, sizeof(exten));
09298             timeout = firstdigittimeout;
09299          } else if (!strcmp(exten, "*0")) {
09300             struct ast_channel *nbridge =
09301                p->subs[SUB_THREEWAY].owner;
09302             struct dahdi_pvt *pbridge = NULL;
09303             /* set up the private struct of the bridged one, if any */
09304             if (nbridge && ast_bridged_channel(nbridge))
09305                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
09306             if (nbridge && pbridge &&
09307                (nbridge->tech == &dahdi_tech) &&
09308                (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
09309                ISTRUNK(pbridge)) {
09310                int func = DAHDI_FLASH;
09311                /* Clear out the dial buffer */
09312                p->dop.dialstr[0] = '\0';
09313                /* flash hookswitch */
09314                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09315                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09316                      nbridge->name, strerror(errno));
09317                }
09318                swap_subs(p, SUB_REAL, SUB_THREEWAY);
09319                unalloc_sub(p, SUB_THREEWAY);
09320                p->owner = p->subs[SUB_REAL].owner;
09321                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
09322                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
09323                ast_hangup(chan);
09324                goto quit;
09325             } else {
09326                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09327                dahdi_wait_event(p->subs[idx].dfd);
09328                tone_zone_play_tone(p->subs[idx].dfd, -1);
09329                swap_subs(p, SUB_REAL, SUB_THREEWAY);
09330                unalloc_sub(p, SUB_THREEWAY);
09331                p->owner = p->subs[SUB_REAL].owner;
09332                ast_hangup(chan);
09333                goto quit;
09334             }
09335          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
09336                      ((exten[0] != '*') || (strlen(exten) > 2))) {
09337             ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
09338             break;
09339          }
09340          if (!timeout)
09341             timeout = gendigittimeout;
09342          if (len && !ast_ignore_pattern(chan->context, exten))
09343             tone_zone_play_tone(p->subs[idx].dfd, -1);
09344       }
09345       break;
09346    case SIG_FXSLS:
09347    case SIG_FXSGS:
09348    case SIG_FXSKS:
09349       /* check for SMDI messages */
09350       if (p->use_smdi && p->smdi_iface) {
09351          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
09352 
09353          if (smdi_msg != NULL) {
09354             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
09355 
09356             if (smdi_msg->type == 'B')
09357                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
09358             else if (smdi_msg->type == 'N')
09359                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
09360 
09361             ast_debug(1, "Received SMDI message on %s\n", chan->name);
09362          } else {
09363             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
09364          }
09365       }
09366 
09367       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
09368          number = smdi_msg->calling_st;
09369 
09370       /* If we want caller id, we're in a prering state due to a polarity reversal
09371        * and we're set to use a polarity reversal to trigger the start of caller id,
09372        * grab the caller id and wait for ringing to start... */
09373       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
09374                    (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
09375          /* If set to use DTMF CID signalling, listen for DTMF */
09376          if (p->cid_signalling == CID_SIG_DTMF) {
09377             int k = 0;
09378             cs = NULL;
09379             ast_debug(1, "Receiving DTMF cid on "
09380                "channel %s\n", chan->name);
09381             dahdi_setlinear(p->subs[idx].dfd, 0);
09382             res = 2000;
09383             for (;;) {
09384                struct ast_frame *f;
09385                res = ast_waitfor(chan, res);
09386                if (res <= 0) {
09387                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
09388                      "Exiting simple switch\n");
09389                   ast_hangup(chan);
09390                   goto quit;
09391                }
09392                f = ast_read(chan);
09393                if (!f)
09394                   break;
09395                if (f->frametype == AST_FRAME_DTMF) {
09396                   dtmfbuf[k++] = f->subclass;
09397                   ast_debug(1, "CID got digit '%c'\n", f->subclass);
09398                   res = 2000;
09399                }
09400                ast_frfree(f);
09401                if (chan->_state == AST_STATE_RING ||
09402                   chan->_state == AST_STATE_RINGING)
09403                   break; /* Got ring */
09404             }
09405             dtmfbuf[k] = '\0';
09406             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09407             /* Got cid and ring. */
09408             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
09409             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
09410             ast_debug(1, "CID is '%s', flags %d\n",
09411                dtmfcid, flags);
09412             /* If first byte is NULL, we have no cid */
09413             if (!ast_strlen_zero(dtmfcid))
09414                number = dtmfcid;
09415             else
09416                number = NULL;
09417          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
09418          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
09419             cs = callerid_new(p->cid_signalling);
09420             if (cs) {
09421                samples = 0;
09422 #if 1
09423                bump_gains(p);
09424 #endif
09425                /* Take out of linear mode for Caller*ID processing */
09426                dahdi_setlinear(p->subs[idx].dfd, 0);
09427 
09428                /* First we wait and listen for the Caller*ID */
09429                for (;;) {
09430                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
09431                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
09432                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
09433                      callerid_free(cs);
09434                      ast_hangup(chan);
09435                      goto quit;
09436                   }
09437                   if (i & DAHDI_IOMUX_SIGEVENT) {
09438                      res = dahdi_get_event(p->subs[idx].dfd);
09439                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
09440 
09441                      if (p->cid_signalling == CID_SIG_V23_JP) {
09442                         if (res == DAHDI_EVENT_RINGBEGIN) {
09443                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09444                            usleep(1);
09445                         }
09446                      } else {
09447                         res = 0;
09448                         break;
09449                      }
09450                   } else if (i & DAHDI_IOMUX_READ) {
09451                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
09452                      if (res < 0) {
09453                         if (errno != ELAST) {
09454                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09455                            callerid_free(cs);
09456                            ast_hangup(chan);
09457                            goto quit;
09458                         }
09459                         break;
09460                      }
09461                      samples += res;
09462 
09463                      if (p->cid_signalling == CID_SIG_V23_JP) {
09464                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
09465                      } else {
09466                         res = callerid_feed(cs, buf, res, AST_LAW(p));
09467                      }
09468 
09469                      if (res < 0) {
09470                         ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
09471                         break;
09472                      } else if (res)
09473                         break;
09474                      else if (samples > (8000 * 10))
09475                         break;
09476                   }
09477                }
09478                if (res == 1) {
09479                   callerid_get(cs, &name, &number, &flags);
09480                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
09481                }
09482 
09483                if (p->cid_signalling == CID_SIG_V23_JP) {
09484                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09485                   usleep(1);
09486                   res = 4000;
09487                } else {
09488 
09489                   /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
09490                   res = 2000;
09491                }
09492 
09493                for (;;) {
09494                   struct ast_frame *f;
09495                   res = ast_waitfor(chan, res);
09496                   if (res <= 0) {
09497                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
09498                         "Exiting simple switch\n");
09499                      ast_hangup(chan);
09500                      goto quit;
09501                   }
09502                   if (!(f = ast_read(chan))) {
09503                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
09504                      ast_hangup(chan);
09505                      goto quit;
09506                   }
09507                   ast_frfree(f);
09508                   if (chan->_state == AST_STATE_RING ||
09509                      chan->_state == AST_STATE_RINGING)
09510                      break; /* Got ring */
09511                }
09512 
09513                /* We must have a ring by now, so, if configured, lets try to listen for
09514                 * distinctive ringing */
09515                if (p->usedistinctiveringdetection) {
09516                   len = 0;
09517                   distMatches = 0;
09518                   /* Clear the current ring data array so we dont have old data in it. */
09519                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
09520                      curRingData[receivedRingT] = 0;
09521                   receivedRingT = 0;
09522                   counter = 0;
09523                   counter1 = 0;
09524                   /* Check to see if context is what it should be, if not set to be. */
09525                   if (strcmp(p->context,p->defcontext) != 0) {
09526                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
09527                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
09528                   }
09529 
09530                   for (;;) {
09531                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
09532                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
09533                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
09534                         callerid_free(cs);
09535                         ast_hangup(chan);
09536                         goto quit;
09537                      }
09538                      if (i & DAHDI_IOMUX_SIGEVENT) {
09539                         res = dahdi_get_event(p->subs[idx].dfd);
09540                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
09541                         res = 0;
09542                         /* Let us detect distinctive ring */
09543 
09544                         curRingData[receivedRingT] = p->ringt;
09545 
09546                         if (p->ringt < p->ringt_base/2)
09547                            break;
09548                         /* Increment the ringT counter so we can match it against
09549                            values in chan_dahdi.conf for distinctive ring */
09550                         if (++receivedRingT == ARRAY_LEN(curRingData))
09551                            break;
09552                      } else if (i & DAHDI_IOMUX_READ) {
09553                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
09554                         if (res < 0) {
09555                            if (errno != ELAST) {
09556                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09557                               callerid_free(cs);
09558                               ast_hangup(chan);
09559                               goto quit;
09560                            }
09561                            break;
09562                         }
09563                         if (p->ringt > 0) {
09564                            if (!(--p->ringt)) {
09565                               res = -1;
09566                               break;
09567                            }
09568                         }
09569                      }
09570                   }
09571                      /* this only shows up if you have n of the dring patterns filled in */
09572                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
09573                   for (counter = 0; counter < 3; counter++) {
09574                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
09575                      channel */
09576                      distMatches = 0;
09577                      for (counter1 = 0; counter1 < 3; counter1++) {
09578                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
09579                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
09580                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
09581                            curRingData[counter1]);
09582                            distMatches++;
09583                         } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
09584                               curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
09585                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
09586                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
09587                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
09588                            distMatches++;
09589                         }
09590                      }
09591 
09592                      if (distMatches == 3) {
09593                         /* The ring matches, set the context to whatever is for distinctive ring.. */
09594                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
09595                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
09596                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
09597                         break;
09598                      }
09599                   }
09600                }
09601                /* Restore linear mode (if appropriate) for Caller*ID processing */
09602                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09603 #if 1
09604                restore_gains(p);
09605 #endif
09606             } else
09607                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
09608          } else {
09609             ast_log(LOG_WARNING, "Channel %s in prering "
09610                "state, but I have nothing to do. "
09611                "Terminating simple switch, should be "
09612                "restarted by the actual ring.\n",
09613                chan->name);
09614             ast_hangup(chan);
09615             goto quit;
09616          }
09617       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
09618          if (p->cid_signalling == CID_SIG_DTMF) {
09619             int k = 0;
09620             cs = NULL;
09621             dahdi_setlinear(p->subs[idx].dfd, 0);
09622             res = 2000;
09623             for (;;) {
09624                struct ast_frame *f;
09625                res = ast_waitfor(chan, res);
09626                if (res <= 0) {
09627                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
09628                      "Exiting simple switch\n");
09629                   ast_hangup(chan);
09630                   return NULL;
09631                }
09632                f = ast_read(chan);
09633                if (f->frametype == AST_FRAME_DTMF) {
09634                   dtmfbuf[k++] = f->subclass;
09635                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
09636                   res = 2000;
09637                }
09638                ast_frfree(f);
09639 
09640                if (p->ringt_base == p->ringt)
09641                   break;
09642             }
09643             dtmfbuf[k] = '\0';
09644             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09645             /* Got cid and ring. */
09646             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
09647             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
09648                dtmfcid, flags);
09649             /* If first byte is NULL, we have no cid */
09650             if (!ast_strlen_zero(dtmfcid))
09651                number = dtmfcid;
09652             else
09653                number = NULL;
09654             /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
09655          } else {
09656             /* FSK Bell202 callerID */
09657             cs = callerid_new(p->cid_signalling);
09658             if (cs) {
09659 #if 1
09660                bump_gains(p);
09661 #endif
09662                samples = 0;
09663                len = 0;
09664                distMatches = 0;
09665                /* Clear the current ring data array so we dont have old data in it. */
09666                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
09667                   curRingData[receivedRingT] = 0;
09668                receivedRingT = 0;
09669                counter = 0;
09670                counter1 = 0;
09671                /* Check to see if context is what it should be, if not set to be. */
09672                if (strcmp(p->context,p->defcontext) != 0) {
09673                   ast_copy_string(p->context, p->defcontext, sizeof(p->context));
09674                   ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
09675                }
09676 
09677                /* Take out of linear mode for Caller*ID processing */
09678                dahdi_setlinear(p->subs[idx].dfd, 0);
09679                for (;;) {
09680                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
09681                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
09682                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
09683                      callerid_free(cs);
09684                      ast_hangup(chan);
09685                      goto quit;
09686                   }
09687                   if (i & DAHDI_IOMUX_SIGEVENT) {
09688                      res = dahdi_get_event(p->subs[idx].dfd);
09689                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
09690                      /* If we get a PR event, they hung up while processing calerid */
09691                      if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
09692                         ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
09693                         p->polarity = POLARITY_IDLE;
09694                         callerid_free(cs);
09695                         ast_hangup(chan);
09696                         goto quit;
09697                      }
09698                      res = 0;
09699                      /* Let us detect callerid when the telco uses distinctive ring */
09700 
09701                      curRingData[receivedRingT] = p->ringt;
09702 
09703                      if (p->ringt < p->ringt_base/2)
09704                         break;
09705                      /* Increment the ringT counter so we can match it against
09706                         values in chan_dahdi.conf for distinctive ring */
09707                      if (++receivedRingT == ARRAY_LEN(curRingData))
09708                         break;
09709                   } else if (i & DAHDI_IOMUX_READ) {
09710                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
09711                      if (res < 0) {
09712                         if (errno != ELAST) {
09713                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09714                            callerid_free(cs);
09715                            ast_hangup(chan);
09716                            goto quit;
09717                         }
09718                         break;
09719                      }
09720                      if (p->ringt > 0) {
09721                         if (!(--p->ringt)) {
09722                            res = -1;
09723                            break;
09724                         }
09725                      }
09726                      samples += res;
09727                      res = callerid_feed(cs, buf, res, AST_LAW(p));
09728                      if (res < 0) {
09729                         ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
09730                         break;
09731                      } else if (res)
09732                         break;
09733                      else if (samples > (8000 * 10))
09734                         break;
09735                   }
09736                }
09737                if (res == 1) {
09738                   callerid_get(cs, &name, &number, &flags);
09739                   ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
09740                }
09741                if (distinctiveringaftercid == 1) {
09742                   /* Clear the current ring data array so we dont have old data in it. */
09743                   for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
09744                      curRingData[receivedRingT] = 0;
09745                   }
09746                   receivedRingT = 0;
09747                   ast_verb(3, "Detecting post-CID distinctive ring\n");
09748                   for (;;) {
09749                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
09750                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
09751                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
09752                         callerid_free(cs);
09753                         ast_hangup(chan);
09754                         goto quit;
09755                      }
09756                      if (i & DAHDI_IOMUX_SIGEVENT) {
09757                         res = dahdi_get_event(p->subs[idx].dfd);
09758                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
09759                         res = 0;
09760                         /* Let us detect callerid when the telco uses distinctive ring */
09761 
09762                         curRingData[receivedRingT] = p->ringt;
09763 
09764                         if (p->ringt < p->ringt_base/2)
09765                            break;
09766                         /* Increment the ringT counter so we can match it against
09767                            values in chan_dahdi.conf for distinctive ring */
09768                         if (++receivedRingT == ARRAY_LEN(curRingData))
09769                            break;
09770                      } else if (i & DAHDI_IOMUX_READ) {
09771                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
09772                         if (res < 0) {
09773                            if (errno != ELAST) {
09774                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09775                               callerid_free(cs);
09776                               ast_hangup(chan);
09777                               goto quit;
09778                            }
09779                            break;
09780                         }
09781                         if (p->ringt > 0) {
09782                            if (!(--p->ringt)) {
09783                               res = -1;
09784                               break;
09785                            }
09786                         }
09787                      }
09788                   }
09789                }
09790                if (p->usedistinctiveringdetection) {
09791                   /* this only shows up if you have n of the dring patterns filled in */
09792                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
09793 
09794                   for (counter = 0; counter < 3; counter++) {
09795                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
09796                      channel */
09797                      /* this only shows up if you have n of the dring patterns filled in */
09798                      ast_verb(3, "Checking %d,%d,%d\n",
09799                            p->drings.ringnum[counter].ring[0],
09800                            p->drings.ringnum[counter].ring[1],
09801                            p->drings.ringnum[counter].ring[2]);
09802                      distMatches = 0;
09803                      for (counter1 = 0; counter1 < 3; counter1++) {
09804                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
09805                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
09806                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
09807                            curRingData[counter1]);
09808                            distMatches++;
09809                         }
09810                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
09811                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
09812                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
09813                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
09814                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
09815                            distMatches++;
09816                         }
09817                      }
09818                      if (distMatches == 3) {
09819                         /* The ring matches, set the context to whatever is for distinctive ring.. */
09820                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
09821                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
09822                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
09823                         break;
09824                      }
09825                   }
09826                }
09827                /* Restore linear mode (if appropriate) for Caller*ID processing */
09828                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09829 #if 1
09830                restore_gains(p);
09831 #endif
09832                if (res < 0) {
09833                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
09834                }
09835             } else
09836                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
09837          }
09838       } else
09839          cs = NULL;
09840 
09841       if (number)
09842          ast_shrink_phone_number(number);
09843       ast_set_callerid(chan, number, name, number);
09844 
09845       if (smdi_msg)
09846          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
09847 
09848       if (cs)
09849          callerid_free(cs);
09850 
09851       my_handle_notify_message(chan, p, flags, -1);
09852 
09853       ast_setstate(chan, AST_STATE_RING);
09854       chan->rings = 1;
09855       p->ringt = p->ringt_base;
09856       res = ast_pbx_run(chan);
09857       if (res) {
09858          ast_hangup(chan);
09859          ast_log(LOG_WARNING, "PBX exited non-zero\n");
09860       }
09861       goto quit;
09862    default:
09863       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
09864       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09865       if (res < 0)
09866             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
09867    }
09868    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09869    if (res < 0)
09870          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
09871    ast_hangup(chan);
09872 quit:
09873    ast_mutex_lock(&ss_thread_lock);
09874    ss_thread_count--;
09875    ast_cond_signal(&ss_thread_complete);
09876    ast_mutex_unlock(&ss_thread_lock);
09877    return NULL;
09878 }

static int analog_tone_to_dahditone ( enum analog_tone  tone  )  [static]

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

01551 {
01552    switch (tone) {
01553    case ANALOG_TONE_RINGTONE:
01554       return DAHDI_TONE_RINGTONE;
01555    case ANALOG_TONE_STUTTER:
01556       return DAHDI_TONE_STUTTER;
01557    case ANALOG_TONE_CONGESTION:
01558       return DAHDI_TONE_CONGESTION;
01559    case ANALOG_TONE_DIALTONE:
01560       return DAHDI_TONE_DIALTONE;
01561    case ANALOG_TONE_DIALRECALL:
01562       return DAHDI_TONE_DIALRECALL;
01563    case ANALOG_TONE_INFO:
01564       return DAHDI_TONE_INFO;
01565    default:
01566       return -1;
01567    }
01568 }

static int analogsub_to_dahdisub ( enum analog_sub  analogsub  )  [static]

Definition at line 1570 of file chan_dahdi.c.

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

Referenced by my_allocate_sub(), my_conf_add(), my_conf_del(), my_dial_digits(), my_get_sub_fd(), my_handle_dtmfup(), my_is_dialing(), my_new_analog_ast_channel(), my_play_tone(), my_swap_subchannels(), my_unallocate_sub(), and my_wink().

01571 {
01572    int index;
01573 
01574    switch (analogsub) {
01575    case ANALOG_SUB_REAL:
01576       index = SUB_REAL;
01577       break;
01578    case ANALOG_SUB_CALLWAIT:
01579       index = SUB_CALLWAIT;
01580       break;
01581    case ANALOG_SUB_THREEWAY:
01582       index = SUB_THREEWAY;
01583       break;
01584    default:
01585       ast_log(LOG_ERROR, "Unidentified sub!\n");
01586       index = SUB_REAL;
01587    }
01588 
01589    return index;
01590 }

static int attempt_transfer ( struct dahdi_pvt p  )  [static]

Definition at line 6745 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, ast_bridged_channel(), ast_channel_masquerade(), ast_channel_unlock, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_debug, ast_indicate(), ast_log(), ast_queue_control(), AST_SOFTHANGUP_DEV, AST_STATE_RING, AST_STATE_RINGING, dahdi_subchannel::dfd, LOG_WARNING, ast_channel::name, dahdi_subchannel::owner, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and unalloc_sub().

Referenced by close_call(), dahdi_handle_event(), handle_request(), and local_attended_transfer().

06746 {
06747    /* In order to transfer, we need at least one of the channels to
06748       actually be in a call bridge.  We can't conference two applications
06749       together (but then, why would we want to?) */
06750    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
06751       /* The three-way person we're about to transfer to could still be in MOH, so
06752          stop if now if appropriate */
06753       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
06754          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
06755       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
06756          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
06757       }
06758       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
06759          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
06760       }
06761        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
06762          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
06763                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
06764          return -1;
06765       }
06766       /* Orphan the channel after releasing the lock */
06767       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06768       unalloc_sub(p, SUB_THREEWAY);
06769    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06770       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06771       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
06772          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
06773       }
06774       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
06775          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06776       }
06777       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
06778          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
06779                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
06780          return -1;
06781       }
06782       /* Three-way is now the REAL */
06783       swap_subs(p, SUB_THREEWAY, SUB_REAL);
06784       ast_channel_unlock(p->subs[SUB_REAL].owner);
06785       unalloc_sub(p, SUB_THREEWAY);
06786       /* Tell the caller not to hangup */
06787       return 1;
06788    } else {
06789       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
06790          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
06791       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06792       return -1;
06793    }
06794    return 0;
06795 }

static int available ( struct dahdi_pvt p,
int  channelmatch,
ast_group_t  groupmatch,
int *  reason,
int *  channelmatched,
int *  groupmatched 
) [inline, static]

Definition at line 11768 of file chan_dahdi.c.

References analog_available(), analog_lib_handles(), dahdi_pvt::channel, dahdi_pvt::group, 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, and dahdi_pvt::sig_pvt.

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

11769 {
11770    /* First, check group matching */
11771    if (groupmatch) {
11772       if ((p->group & groupmatch) != groupmatch)
11773          return 0;
11774       *groupmatched = 1;
11775    }
11776    /* Check to see if we have a channel match */
11777    if (channelmatch != -1) {
11778       if (p->channel != channelmatch)
11779          return 0;
11780       *channelmatched = 1;
11781    }
11782 
11783    if (p->inalarm)
11784       return 0;
11785 
11786    if (analog_lib_handles(p->sig, p->radio, p->oprmode))
11787       return analog_available(p->sig_pvt, channelmatch, groupmatch, reason, channelmatched, groupmatched);
11788 
11789 #ifdef HAVE_PRI
11790    switch (p->sig) {
11791    case SIG_PRI_LIB_HANDLE_CASES:
11792       return sig_pri_available(p->sig_pvt, channelmatch, groupmatch, reason, channelmatched, groupmatched);
11793    default:
11794       break;
11795    }
11796 #endif
11797 
11798    if (p->locallyblocked || p->remotelyblocked) {
11799       return 0;
11800    }
11801 
11802    /* If no owner definitely available */
11803    if (!p->owner) {
11804 #ifdef HAVE_SS7
11805       /* Trust SS7 */
11806       if (p->ss7) {
11807          if (p->ss7call) {
11808             return 0;
11809          } else {
11810             return 1;
11811          }
11812       }
11813 #endif
11814 #ifdef HAVE_OPENR2
11815       /* Trust MFC/R2 */
11816       if (p->mfcr2) {
11817          if (p->mfcr2call) {
11818             return 0;
11819          } else {
11820             return 1;
11821          }
11822       }
11823 #endif
11824       return 1;
11825    }
11826 
11827    return 0;
11828 }

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

Definition at line 15593 of file chan_dahdi.c.

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

Referenced by process_dahdi().

15594 {
15595    char *c, *chan;
15596    int x, start, finish;
15597    struct dahdi_pvt *tmp;
15598 
15599    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
15600       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
15601       return -1;
15602    }
15603 
15604    c = ast_strdupa(value);
15605 
15606    while ((chan = strsep(&c, ","))) {
15607       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
15608          /* Range */
15609       } else if (sscanf(chan, "%30d", &start)) {
15610          /* Just one */
15611          finish = start;
15612       } else if (!strcasecmp(chan, "pseudo")) {
15613          finish = start = CHAN_PSEUDO;
15614          if (found_pseudo)
15615             *found_pseudo = 1;
15616       } else {
15617          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
15618          return -1;
15619       }
15620       if (finish < start) {
15621          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
15622          x = finish;
15623          finish = start;
15624          start = x;
15625       }
15626 
15627       for (x = start; x <= finish; x++) {
15628          tmp = mkintf(x, conf, reload);
15629 
15630          if (tmp) {
15631             ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
15632          } else {
15633             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
15634                (reload == 1) ? "reconfigure" : "register", value);
15635             return -1;
15636          }
15637       }
15638    }
15639 
15640    return 0;
15641 }

static int bump_gains ( struct dahdi_pvt p  )  [static]

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

04325 {
04326    int res;
04327 
04328    /* Bump receive gain by value stored in cid_rxgain */
04329    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
04330    if (res) {
04331       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
04332       return -1;
04333    }
04334 
04335    return 0;
04336 }

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

Definition at line 9886 of file chan_dahdi.c.

References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.

Referenced by do_monitor(), and mwi_thread().

09887 {
09888    int x;
09889    int sum = 0;
09890 
09891    if (!len)
09892       return 0;
09893 
09894    for (x = 0; x < len; x++)
09895       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
09896 
09897    return sum / len;
09898 }

static int check_for_conference ( struct dahdi_pvt p  )  [static]

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

06798 {
06799    struct dahdi_confinfo ci;
06800    /* Fine if we already have a master, etc */
06801    if (p->master || (p->confno > -1))
06802       return 0;
06803    memset(&ci, 0, sizeof(ci));
06804    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
06805       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
06806       return 0;
06807    }
06808    /* If we have no master and don't have a confno, then
06809       if we're in a conference, it's probably a MeetMe room or
06810       some such, so don't let us 3-way out! */
06811    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
06812       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
06813       return 1;
06814    }
06815    return 0;
06816 }

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

Definition at line 3904 of file chan_dahdi.c.

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

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

03905 {
03906    /* If the conference already exists, and we're already in it
03907       don't bother doing anything */
03908    struct dahdi_confinfo zi;
03909 
03910    memset(&zi, 0, sizeof(zi));
03911    zi.chan = 0;
03912 
03913    if (slavechannel > 0) {
03914       /* If we have only one slave, do a digital mon */
03915       zi.confmode = DAHDI_CONF_DIGITALMON;
03916       zi.confno = slavechannel;
03917    } else {
03918       if (!idx) {
03919          /* Real-side and pseudo-side both participate in conference */
03920          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
03921             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
03922       } else
03923          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
03924       zi.confno = p->confno;
03925    }
03926    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
03927       return 0;
03928    if (c->dfd < 0)
03929       return 0;
03930    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
03931       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
03932       return -1;
03933    }
03934    if (slavechannel < 1) {
03935       p->confno = zi.confno;
03936    }
03937    memcpy(&c->curconf, &zi, sizeof(c->curconf));
03938    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
03939    return 0;
03940 }

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

Definition at line 3953 of file chan_dahdi.c.

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

Referenced by dahdi_unlink(), my_conf_del(), and update_conf().

03954 {
03955    struct dahdi_confinfo zi;
03956    if (/* Can't delete if there's no dfd */
03957       (c->dfd < 0) ||
03958       /* Don't delete from the conference if it's not our conference */
03959       !isourconf(p, c)
03960       /* Don't delete if we don't think it's conferenced at all (implied) */
03961       ) return 0;
03962    memset(&zi, 0, sizeof(zi));
03963    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
03964       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
03965       return -1;
03966    }
03967    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
03968    memcpy(&c->curconf, &zi, sizeof(c->curconf));
03969    return 0;
03970 }

static int dahdi_answer ( struct ast_channel ast  )  [static]

Definition at line 5780 of file chan_dahdi.c.

References analog_answer(), analog_lib_handles(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_UP, dahdi_pvt::channel, dahdi_get_index(), dahdi_pvt::lock, LOG_DEBUG, 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, dahdi_pvt::span, SUB_REAL, and ast_channel::tech_pvt.

05781 {
05782    struct dahdi_pvt *p = ast->tech_pvt;
05783    int res = 0;
05784    int idx;
05785    ast_setstate(ast, AST_STATE_UP);
05786    ast_mutex_lock(&p->lock);
05787    idx = dahdi_get_index(ast, p, 0);
05788    if (idx < 0)
05789       idx = SUB_REAL;
05790    /* nothing to do if a radio channel */
05791    if ((p->radio || (p->oprmode < 0))) {
05792       ast_mutex_unlock(&p->lock);
05793       return 0;
05794    }
05795 
05796    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05797       res = analog_answer(p->sig_pvt, ast);
05798       ast_mutex_unlock(&p->lock);
05799       return res;
05800    }
05801 
05802    switch (p->sig) {
05803 #ifdef HAVE_PRI
05804    case SIG_PRI_LIB_HANDLE_CASES:
05805       res = sig_pri_answer(p->sig_pvt, ast);
05806       ast_mutex_unlock(&p->lock);
05807       return res;
05808 #endif
05809 #ifdef HAVE_SS7
05810    case SIG_SS7:
05811       if (!ss7_grab(p, p->ss7)) {
05812          p->proceeding = 1;
05813          res = isup_anm(p->ss7->ss7, p->ss7call);
05814          ss7_rel(p->ss7);
05815       } else {
05816          ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
05817          res = -1;
05818       }
05819       break;
05820 #endif
05821 #ifdef HAVE_OPENR2
05822    case SIG_MFCR2:
05823       if (!p->mfcr2_call_accepted) {
05824          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
05825             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
05826          p->mfcr2_answer_pending = 1;
05827          if (p->mfcr2_charge_calls) {
05828             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
05829             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
05830          } else {
05831             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
05832             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
05833          }
05834       } else {
05835          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
05836          dahdi_r2_answer(p);
05837       }
05838       break;
05839 #endif
05840    case 0:
05841       ast_mutex_unlock(&p->lock);
05842       return 0;
05843    default:
05844       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
05845       res = -1;
05846    }
05847    ast_mutex_unlock(&p->lock);
05848    return res;
05849 }

static enum ast_bridge_result dahdi_bridge ( struct ast_channel c0,
struct ast_channel c1,
int  flags,
struct ast_frame **  fo,
struct ast_channel **  rc,
int  timeoutms 
) [static]

Definition at line 6362 of file chan_dahdi.c.

References ast_channel::_state, AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_RETRY, ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_read(), AST_STATE_RINGING, ast_verb, ast_waitfor_n(), ast_write(), sig_pri_chan::call, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_link(), dahdi_sig_pri_lib_handles(), dahdi_unlink(), dahdi_subchannel::dfd, disable_dtmf_detect(), dahdi_pvt::echocanbridged, enable_dtmf_detect(), ast_channel::fds, ast_frame::frametype, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, dahdi_pvt::master, ast_channel::name, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pulsedial, dahdi_pvt::sig, SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, ast_channel::tech_pvt, dahdi_pvt::transfer, and update_conf().

06363 {
06364    struct ast_channel *who;
06365    struct dahdi_pvt *p0, *p1, *op0, *op1;
06366    struct dahdi_pvt *master = NULL, *slave = NULL;
06367    struct ast_frame *f;
06368    int inconf = 0;
06369    int nothingok = 1;
06370    int ofd0, ofd1;
06371    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
06372    int os0 = -1, os1 = -1;
06373    int priority = 0;
06374    struct ast_channel *oc0, *oc1;
06375    enum ast_bridge_result res;
06376 #ifdef PRI_2BCT
06377    q931_call *q931c0;
06378    q931_call *q931c1;
06379 #endif
06380 
06381    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
06382       There is code below to handle it properly until DTMF is actually seen,
06383       but due to currently unresolved issues it's ignored...
06384    */
06385 
06386    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
06387       return AST_BRIDGE_FAILED_NOWARN;
06388 
06389    ast_channel_lock(c0);
06390    while (ast_channel_trylock(c1)) {
06391       CHANNEL_DEADLOCK_AVOIDANCE(c0);
06392    }
06393 
06394    p0 = c0->tech_pvt;
06395    p1 = c1->tech_pvt;
06396    /* cant do pseudo-channels here */
06397    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
06398       ast_channel_unlock(c0);
06399       ast_channel_unlock(c1);
06400       return AST_BRIDGE_FAILED_NOWARN;
06401    }
06402 
06403    oi0 = dahdi_get_index(c0, p0, 0);
06404    oi1 = dahdi_get_index(c1, p1, 0);
06405    if ((oi0 < 0) || (oi1 < 0)) {
06406       ast_channel_unlock(c0);
06407       ast_channel_unlock(c1);
06408       return AST_BRIDGE_FAILED;
06409    }
06410 
06411    op0 = p0 = c0->tech_pvt;
06412    op1 = p1 = c1->tech_pvt;
06413    ofd0 = c0->fds[0];
06414    ofd1 = c1->fds[0];
06415    oc0 = p0->owner;
06416    oc1 = p1->owner;
06417 
06418    if (ast_mutex_trylock(&p0->lock)) {
06419       /* Don't block, due to potential for deadlock */
06420       ast_channel_unlock(c0);
06421       ast_channel_unlock(c1);
06422       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
06423       return AST_BRIDGE_RETRY;
06424    }
06425    if (ast_mutex_trylock(&p1->lock)) {
06426       /* Don't block, due to potential for deadlock */
06427       ast_mutex_unlock(&p0->lock);
06428       ast_channel_unlock(c0);
06429       ast_channel_unlock(c1);
06430       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
06431       return AST_BRIDGE_RETRY;
06432    }
06433 
06434 #if defined(HAVE_PRI)
06435    if ((dahdi_sig_pri_lib_handles(p0->sig)
06436          && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
06437       || (dahdi_sig_pri_lib_handles(p1->sig)
06438          && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
06439       /*
06440        * PRI nobch channels (hold and call waiting) are equivalent to
06441        * pseudo channels and cannot be done here.
06442        */
06443       ast_mutex_unlock(&p0->lock);
06444       ast_mutex_unlock(&p1->lock);
06445       ast_channel_unlock(c0);
06446       ast_channel_unlock(c1);
06447       return AST_BRIDGE_FAILED_NOWARN;
06448    }
06449 #endif   /* defined(HAVE_PRI) */
06450 
06451    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
06452       if (p0->owner && p1->owner) {
06453          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
06454          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
06455             master = p0;
06456             slave = p1;
06457             inconf = 1;
06458          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
06459             master = p1;
06460             slave = p0;
06461             inconf = 1;
06462          } else {
06463             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
06464             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
06465                p0->channel,
06466                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
06467                p0->subs[SUB_REAL].inthreeway, p0->channel,
06468                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
06469                p1->subs[SUB_REAL].inthreeway);
06470          }
06471          nothingok = 0;
06472       }
06473    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
06474       if (p1->subs[SUB_THREEWAY].inthreeway) {
06475          master = p1;
06476          slave = p0;
06477          nothingok = 0;
06478       }
06479    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
06480       if (p0->subs[SUB_THREEWAY].inthreeway) {
06481          master = p0;
06482          slave = p1;
06483          nothingok = 0;
06484       }
06485    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
06486       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
06487          don't put us in anything */
06488       if (p1->subs[SUB_CALLWAIT].inthreeway) {
06489          master = p1;
06490          slave = p0;
06491          nothingok = 0;
06492       }
06493    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
06494       /* Same as previous */
06495       if (p0->subs[SUB_CALLWAIT].inthreeway) {
06496          master = p0;
06497          slave = p1;
06498          nothingok = 0;
06499       }
06500    }
06501    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
06502       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
06503    if (master && slave) {
06504       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
06505          in an active threeway call with a channel that is ringing, we should
06506          indicate ringing. */
06507       if ((oi1 == SUB_THREEWAY) &&
06508          p1->subs[SUB_THREEWAY].inthreeway &&
06509          p1->subs[SUB_REAL].owner &&
06510          p1->subs[SUB_REAL].inthreeway &&
06511          (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
06512          ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
06513          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
06514          os1 = p1->subs[SUB_REAL].owner->_state;
06515       } else {
06516          ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
06517          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
06518       }
06519       if ((oi0 == SUB_THREEWAY) &&
06520          p0->subs[SUB_THREEWAY].inthreeway &&
06521          p0->subs[SUB_REAL].owner &&
06522          p0->subs[SUB_REAL].inthreeway &&
06523          (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
06524          ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
06525          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
06526          os0 = p0->subs[SUB_REAL].owner->_state;
06527       } else {
06528          ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
06529          tone_zone_play_tone(p1->subs[oi0].dfd, -1);
06530       }
06531       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
06532          if (!p0->echocanbridged || !p1->echocanbridged) {
06533             /* Disable echo cancellation if appropriate */
06534             dahdi_disable_ec(p0);
06535             dahdi_disable_ec(p1);
06536          }
06537       }
06538       dahdi_link(slave, master);
06539       master->inconference = inconf;
06540    } else if (!nothingok)
06541       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
06542 
06543    update_conf(p0);
06544    update_conf(p1);
06545    t0 = p0->subs[SUB_REAL].inthreeway;
06546    t1 = p1->subs[SUB_REAL].inthreeway;
06547 
06548    ast_mutex_unlock(&p0->lock);
06549    ast_mutex_unlock(&p1->lock);
06550 
06551    ast_channel_unlock(c0);
06552    ast_channel_unlock(c1);
06553 
06554    /* Native bridge failed */
06555    if ((!master || !slave) && !nothingok) {
06556       dahdi_enable_ec(p0);
06557       dahdi_enable_ec(p1);
06558       return AST_BRIDGE_FAILED;
06559    }
06560 
06561    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
06562 
06563    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
06564       disable_dtmf_detect(op0);
06565 
06566    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
06567       disable_dtmf_detect(op1);
06568 
06569    for (;;) {
06570       struct ast_channel *c0_priority[2] = {c0, c1};
06571       struct ast_channel *c1_priority[2] = {c1, c0};
06572 
06573       /* Here's our main loop...  Start by locking things, looking for private parts,
06574          and then balking if anything is wrong */
06575 
06576       ast_channel_lock(c0);
06577       while (ast_channel_trylock(c1)) {
06578          CHANNEL_DEADLOCK_AVOIDANCE(c0);
06579       }
06580 
06581       p0 = c0->tech_pvt;
06582       p1 = c1->tech_pvt;
06583 
06584       if (op0 == p0)
06585          i0 = dahdi_get_index(c0, p0, 1);
06586       if (op1 == p1)
06587          i1 = dahdi_get_index(c1, p1, 1);
06588 
06589       ast_channel_unlock(c0);
06590       ast_channel_unlock(c1);
06591 
06592       if (!timeoutms ||
06593          (op0 != p0) ||
06594          (op1 != p1) ||
06595          (ofd0 != c0->fds[0]) ||
06596          (ofd1 != c1->fds[0]) ||
06597          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
06598          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
06599          (oc0 != p0->owner) ||
06600          (oc1 != p1->owner) ||
06601          (t0 != p0->subs[SUB_REAL].inthreeway) ||
06602          (t1 != p1->subs[SUB_REAL].inthreeway) ||
06603          (oi0 != i0) ||
06604          (oi1 != i1)) {
06605          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
06606             op0->channel, oi0, op1->channel, oi1);
06607          res = AST_BRIDGE_RETRY;
06608          goto return_from_bridge;
06609       }
06610 
06611 #ifdef PRI_2BCT
06612       switch (p0->sig) {
06613       case SIG_PRI_LIB_HANDLE_CASES:
06614          q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
06615          break;
06616       default:
06617          q931c0 = NULL;
06618          break;
06619       }
06620       switch (p1->sig) {
06621       case SIG_PRI_LIB_HANDLE_CASES:
06622          q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
06623          break;
06624       default:
06625          q931c1 = NULL;
06626          break;
06627       }
06628       if (q931c0 && q931c1 && p0->transfer && p1->transfer) {
06629          pri_channel_bridge(q931c0, q931c1);
06630       }
06631 #endif
06632 
06633       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
06634       if (!who) {
06635          ast_debug(1, "Ooh, empty read...\n");
06636          continue;
06637       }
06638       f = ast_read(who);
06639       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
06640          *fo = f;
06641          *rc = who;
06642          res = AST_BRIDGE_COMPLETE;
06643          goto return_from_bridge;
06644       }
06645       if (f->frametype == AST_FRAME_DTMF) {
06646          if ((who == c0) && p0->pulsedial) {
06647             ast_write(c1, f);
06648          } else if ((who == c1) && p1->pulsedial) {
06649             ast_write(c0, f);
06650          } else {
06651             *fo = f;
06652             *rc = who;
06653             res = AST_BRIDGE_COMPLETE;
06654             goto return_from_bridge;
06655          }
06656       }
06657       ast_frfree(f);
06658 
06659       /* Swap who gets priority */
06660       priority = !priority;
06661    }
06662 
06663 return_from_bridge:
06664    if (op0 == p0)
06665       dahdi_enable_ec(p0);
06666 
06667    if (op1 == p1)
06668       dahdi_enable_ec(p1);
06669 
06670    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
06671       enable_dtmf_detect(op0);
06672 
06673    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
06674       enable_dtmf_detect(op1);
06675 
06676    dahdi_unlink(slave, master, 1);
06677 
06678    return res;
06679 }

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

Definition at line 4566 of file chan_dahdi.c.

References ast_channel::_state, analog_call(), analog_lib_handles(), ast_party_connected_line::ani2, ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_UP, dahdi_pvt::callwaitrings, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_num, ast_channel::connected, dahdi_sig_pri_lib_handles(), dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialednone, dahdi_pvt::dialing, dahdi_pvt::digital, errno, dahdi_pvt::hidecallerid, ast_party_connected_line::id, IS_DIGITAL, dahdi_pvt::law, dahdi_pvt::lock, LOG_ERROR, LOG_WARNING, ast_channel::name, dahdi_subchannel::needbusy, ast_party_id::number, ast_party_id::number_presentation, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, pbx_builtin_getvar_helper(), dahdi_pvt::radio, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, set_actual_gain(), dahdi_pvt::sig, SIG_MFCR2, sig_pri_call(), dahdi_pvt::sig_pvt, SIG_SS7, dahdi_pvt::stripmsd, SUB_REAL, dahdi_pvt::subs, ast_channel::tech_pvt, ast_channel::transfercapability, dahdi_pvt::txdrc, dahdi_pvt::txgain, dahdi_pvt::use_callingpres, and dahdi_pvt::waitingfordt.

04567 {
04568    struct dahdi_pvt *p = ast->tech_pvt;
04569    int x, res, mysig;
04570    char dest[256]; /* must be same length as p->dialdest */
04571 #ifdef HAVE_SS7
04572    char *c, *l;
04573 #endif
04574    ast_mutex_lock(&p->lock);
04575    ast_copy_string(dest, rdest, sizeof(dest));
04576    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
04577    if ((ast->_state == AST_STATE_BUSY)) {
04578       p->subs[SUB_REAL].needbusy = 1;
04579       ast_mutex_unlock(&p->lock);
04580       return 0;
04581    }
04582    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
04583       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
04584       ast_mutex_unlock(&p->lock);
04585       return -1;
04586    }
04587    p->waitingfordt.tv_sec = 0;
04588    p->dialednone = 0;
04589    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
04590    {
04591       /* Special pseudo -- automatically up */
04592       ast_setstate(ast, AST_STATE_UP);
04593       ast_mutex_unlock(&p->lock);
04594       return 0;
04595    }
04596    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
04597    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
04598    if (res)
04599       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
04600    p->outgoing = 1;
04601 
04602    set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
04603 
04604 #ifdef HAVE_PRI
04605    if (dahdi_sig_pri_lib_handles(p->sig)) {
04606       struct dahdi_params ps;
04607 
04608       memset(&ps, 0, sizeof(ps));
04609       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps)) {
04610          ast_log(LOG_ERROR, "Could not get params\n");
04611       }
04612       res = sig_pri_call(p->sig_pvt, ast, rdest, timeout, (ps.curlaw == DAHDI_LAW_MULAW) ? PRI_LAYER_1_ULAW : PRI_LAYER_1_ALAW);
04613       ast_mutex_unlock(&p->lock);
04614       return res;
04615    }
04616 #endif
04617 
04618    /* If this is analog signalling we can exit here */
04619    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
04620       p->callwaitrings = 0;
04621       res = analog_call(p->sig_pvt, ast, rdest, timeout);
04622       ast_mutex_unlock(&p->lock);
04623       return res;
04624    }
04625 
04626    mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
04627    switch (mysig) {
04628    case 0:
04629       /* Special pseudo -- automatically up*/
04630       ast_setstate(ast, AST_STATE_UP);
04631       break;
04632    case SIG_SS7:
04633    case SIG_MFCR2:
04634       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
04635       p->dialdest[0] = '\0';
04636       p->dialing = 1;
04637       break;
04638    default:
04639       ast_debug(1, "not yet implemented\n");
04640       ast_mutex_unlock(&p->lock);
04641       return -1;
04642    }
04643 
04644 #if defined(HAVE_SS7)
04645    if (p->ss7) {
04646       char ss7_called_nai;
04647       int called_nai_strip;
04648       char ss7_calling_nai;
04649       int calling_nai_strip;
04650       const char *charge_str = NULL;
04651       const char *gen_address = NULL;
04652       const char *gen_digits = NULL;
04653       const char *gen_dig_type = NULL;
04654       const char *gen_dig_scheme = NULL;
04655       const char *gen_name = NULL;
04656       const char *jip_digits = NULL;
04657       const char *lspi_ident = NULL;
04658       const char *rlt_flag = NULL;
04659       const char *call_ref_id = NULL;
04660       const char *call_ref_pc = NULL;
04661       const char *send_far = NULL;
04662 
04663       c = strchr(dest, '/');
04664       if (c) {
04665          c++;
04666       } else {
04667          c = "";
04668       }
04669       if (strlen(c) < p->stripmsd) {
04670          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
04671          ast_mutex_unlock(&p->lock);
04672          return -1;
04673       }
04674 
04675       if (!p->hidecallerid) {
04676          l = ast->connected.id.number;
04677       } else {
04678          l = NULL;
04679       }
04680 
04681       if (ss7_grab(p, p->ss7)) {
04682          ast_log(LOG_WARNING, "Failed to grab SS7!\n");
04683          ast_mutex_unlock(&p->lock);
04684          return -1;
04685       }
04686       p->digital = IS_DIGITAL(ast->transfercapability);
04687       p->ss7call = isup_new_call(p->ss7->ss7);
04688 
04689       if (!p->ss7call) {
04690          ss7_rel(p->ss7);
04691          ast_mutex_unlock(&p->lock);
04692          ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
04693          return -1;
04694       }
04695 
04696       called_nai_strip = 0;
04697       ss7_called_nai = p->ss7->called_nai;
04698       if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */
04699          if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
04700             called_nai_strip = strlen(p->ss7->internationalprefix);
04701             ss7_called_nai = SS7_NAI_INTERNATIONAL;
04702          } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
04703             called_nai_strip = strlen(p->ss7->nationalprefix);
04704             ss7_called_nai = SS7_NAI_NATIONAL;
04705          } else {
04706             ss7_called_nai = SS7_NAI_SUBSCRIBER;
04707          }
04708       }
04709       isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
04710 
04711       calling_nai_strip = 0;
04712       ss7_calling_nai = p->ss7->calling_nai;
04713       if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */
04714          if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
04715             calling_nai_strip = strlen(p->ss7->internationalprefix);
04716             ss7_calling_nai = SS7_NAI_INTERNATIONAL;
04717          } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
04718             calling_nai_strip = strlen(p->ss7->nationalprefix);
04719             ss7_calling_nai = SS7_NAI_NATIONAL;
04720          } else {
04721             ss7_calling_nai = SS7_NAI_SUBSCRIBER;
04722          }
04723       }
04724       isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
04725          p->use_callingpres ? cid_pres2ss7pres(ast->connected.id.number_presentation) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
04726          p->use_callingpres ? cid_pres2ss7screen(ast->connected.id.number_presentation) : SS7_SCREENING_USER_PROVIDED );
04727 
04728       isup_set_oli(p->ss7call, ast->connected.ani2);
04729       isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
04730 
04731       ast_channel_lock(ast);
04732       /* Set the charge number if it is set */
04733       charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
04734       if (charge_str)
04735          isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
04736 
04737       gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
04738       if (gen_address)
04739          isup_set_gen_address(p->ss7call, gen_address, p->gen_add_nai,p->gen_add_pres_ind, p->gen_add_num_plan,p->gen_add_type); /* need to add some types here for NAI,PRES,TYPE */
04740 
04741       gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
04742       gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
04743       gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
04744       if (gen_digits)
04745          isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
04746 
04747       gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
04748       if (gen_name)
04749          isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
04750 
04751       jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
04752       if (jip_digits)
04753          isup_set_jip_digits(p->ss7call, jip_digits);
04754 
04755       lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
04756       if (lspi_ident)
04757          isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
04758 
04759       rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
04760       if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
04761          isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */
04762       }
04763 
04764       call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
04765       call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
04766       if (call_ref_id && call_ref_pc) {
04767          isup_set_callref(p->ss7call, atoi(call_ref_id),
04768                 call_ref_pc ? atoi(call_ref_pc) : 0);
04769       }
04770 
04771       send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
04772       if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
04773          (isup_far(p->ss7->ss7, p->ss7call));
04774 
04775       ast_channel_unlock(ast);
04776 
04777       isup_iam(p->ss7->ss7, p->ss7call);
04778       ast_setstate(ast, AST_STATE_DIALING);
04779       ss7_rel(p->ss7);
04780    }
04781 #endif   /* defined(HAVE_SS7) */
04782 
04783 #ifdef HAVE_OPENR2
04784    if (p->mfcr2) {
04785       openr2_calling_party_category_t chancat;
04786       int callres = 0;
04787       char *c, *l;
04788 
04789       c = strchr(dest, '/');
04790       if (c) {
04791          c++;
04792       } else {
04793          c = "";
04794       }
04795       if (!p->hidecallerid) {
04796          l = ast->cid.cid_num;
04797       } else {
04798          l = NULL;
04799       }
04800       if (strlen(c) < p->stripmsd) {
04801          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
04802          ast_mutex_unlock(&p->lock);
04803          return -1;
04804       }
04805       p->dialing = 1;
04806       ast_channel_lock(ast);
04807       chancat = dahdi_r2_get_channel_category(ast);
04808       ast_channel_unlock(ast);
04809       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
04810       if (-1 == callres) {
04811          ast_mutex_unlock(&p->lock);
04812          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
04813          return -1;
04814       }
04815       ast_setstate(ast, AST_STATE_DIALING);
04816    }
04817 #endif /* HAVE_OPENR2 */
04818    ast_mutex_unlock(&p->lock);
04819    return 0;
04820 }

static int dahdi_callwait ( struct ast_channel ast  )  [static]

Definition at line 4524 of file chan_dahdi.c.

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

Referenced by dahdi_read().

04525 {
04526    struct dahdi_pvt *p = ast->tech_pvt;
04527    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
04528    if (p->cidspill) {
04529       ast_log(LOG_WARNING, "Spill already exists?!?\n");
04530       ast_free(p->cidspill);
04531    }
04532    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
04533       return -1;
04534    save_conference(p);
04535    /* Silence */
04536    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
04537    if (!p->callwaitrings && p->callwaitingcallerid) {
04538       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
04539       p->callwaitcas = 1;
04540       p->cidlen = 2400 + 680 + READ_SIZE * 4;
04541    } else {
04542       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
04543       p->callwaitcas = 0;
04544       p->cidlen = 2400 + READ_SIZE * 4;
04545    }
04546    p->cidpos = 0;
04547    send_callerid(p);
04548 
04549    return 0;
04550 }

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

References CID_SIG_BELL, CID_START_RING, DAHDI_CHAN_MAPPING_PHYSICAL, and DEFAULT_CIDRINGS.

Referenced by process_dahdi(), and setup_dahdi().

01311 {
01312    /* recall that if a field is not included here it is initialized
01313     * to 0 or equivalent
01314     */
01315    struct dahdi_chan_conf conf = {
01316 #ifdef HAVE_PRI
01317       .pri.pri = {
01318          .nsf = PRI_NSF_NONE,
01319          .switchtype = PRI_SWITCH_NI2,
01320          .dialplan = PRI_UNKNOWN + 1,
01321          .localdialplan = PRI_NATIONAL_ISDN + 1,
01322          .nodetype = PRI_CPE,
01323          .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01324 
01325          .minunused = 2,
01326          .idleext = "",
01327          .idledial = "",
01328          .internationalprefix = "",
01329          .nationalprefix = "",
01330          .localprefix = "",
01331          .privateprefix = "",
01332          .unknownprefix = "",
01333          .resetinterval = -1,
01334       },
01335 #endif
01336 #ifdef HAVE_SS7
01337       .ss7 = {
01338          .called_nai = SS7_NAI_NATIONAL,
01339          .calling_nai = SS7_NAI_NATIONAL,
01340          .internationalprefix = "",
01341          .nationalprefix = "",
01342          .subscriberprefix = "",
01343          .unknownprefix = ""
01344       },
01345 #endif
01346 #ifdef HAVE_OPENR2
01347       .mfcr2 = {
01348          .variant = OR2_VAR_ITU,
01349          .mfback_timeout = -1,
01350          .metering_pulse_timeout = -1,
01351          .max_ani = 10,
01352          .max_dnis = 4,
01353          .get_ani_first = -1,
01354 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01355          .skip_category_request = -1,
01356 #endif
01357          .call_files = 0,
01358          .allow_collect_calls = 0,
01359          .charge_calls = 1,
01360          .accept_on_offer = 1,
01361          .forced_release = 0,
01362          .double_answer = 0,
01363          .immediate_accept = -1,
01364          .logdir = "",
01365          .r2proto_file = "",
01366          .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01367          .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01368       },
01369 #endif
01370       .chan = {
01371          .context = "default",
01372          .cid_num = "",
01373          .cid_name = "",
01374          .mohinterpret = "default",
01375          .mohsuggest = "",
01376          .parkinglot = "",
01377          .transfertobusy = 1,
01378 
01379          .cid_signalling = CID_SIG_BELL,
01380          .cid_start = CID_START_RING,
01381          .dahditrcallerid = 0,
01382          .use_callerid = 1,
01383          .sig = -1,
01384          .outsigmod = -1,
01385 
01386          .cid_rxgain = +5.0,
01387 
01388          .tonezone = -1,
01389 
01390          .echocancel.head.tap_length = 1,
01391 
01392          .busycount = 3,
01393 
01394          .accountcode = "",
01395 
01396          .mailbox = "",
01397 
01398 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01399          .mwisend_fsk = 1,
01400 #endif
01401          .polarityonanswerdelay = 600,
01402 
01403          .sendcalleridafter = DEFAULT_CIDRINGS,
01404 
01405          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01406          .buf_no = numbufs,
01407          .usefaxbuffers = 0,
01408       },
01409       .timing = {
01410          .prewinktime = -1,
01411          .preflashtime = -1,
01412          .winktime = -1,
01413          .flashtime = -1,
01414          .starttime = -1,
01415          .rxwinktime = -1,
01416          .rxflashtime = -1,
01417          .debouncetime = -1
01418       },
01419       .is_sig_auto = 1,
01420       .smdi_port = "/dev/ttyS0",
01421    };
01422 
01423    return conf;
01424 }

static void dahdi_close ( int  fd  )  [static]

Definition at line 3550 of file chan_dahdi.c.

Referenced by dahdi_close_sub().

03551 {
03552    if (fd > 0)
03553       close(fd);
03554 }

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

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

03557 {
03558    dahdi_close(chan_pvt->subs[sub_num].dfd);
03559    chan_pvt->subs[sub_num].dfd = -1;
03560 }

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

Definition at line 4368 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_dtmfup(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_read(), my_confmute(), and my_handle_dtmfup().

04369 {
04370    int x, res;
04371 
04372    x = muted;
04373 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04374    switch (p->sig) {
04375 #if defined(HAVE_PRI)
04376    case SIG_PRI_LIB_HANDLE_CASES:
04377       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04378          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
04379          break;
04380       }
04381       /* Fall through */
04382 #endif   /* defined(HAVE_PRI) */
04383 #if defined(HAVE_SS7)
04384    case SIG_SS7:
04385 #endif   /* defined(HAVE_SS7) */
04386       {
04387          int y = 1;
04388 
04389          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
04390          if (res)
04391             ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
04392                p->channel, strerror(errno));
04393       }
04394       break;
04395    default:
04396       break;
04397    }
04398 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
04399    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
04400    if (res < 0)
04401       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
04402    return res;
04403 }

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

Definition at line 14005 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_destroy_channel_bynum(), RESULT_SUCCESS, and ast_cli_entry::usage.

14006 {
14007    int channel;
14008    int ret;
14009    switch (cmd) {
14010    case CLI_INIT:
14011       e->command = "dahdi destroy channel";
14012       e->usage =
14013          "Usage: dahdi destroy channel <chan num>\n"
14014          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
14015       return NULL;
14016    case CLI_GENERATE:
14017       return NULL;
14018    }
14019    if (a->argc != 4)
14020       return CLI_SHOWUSAGE;
14021 
14022    channel = atoi(a->argv[3]);
14023    ret = dahdi_destroy_channel_bynum(channel);
14024    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14025 }

static int dahdi_destroy_channel_bynum ( int  channel  )  [static]

Definition at line 10230 of file chan_dahdi.c.

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

Referenced by dahdi_destroy_channel(), and do_monitor().

10231 {
10232    struct dahdi_pvt *cur;
10233 
10234    ast_mutex_lock(&iflock);
10235    for (cur = iflist; cur; cur = cur->next) {
10236       if (cur->channel == channel) {
10237          int x = DAHDI_FLASH;
10238 
10239          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
10240          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
10241 
10242          destroy_channel(cur, 1);
10243          ast_mutex_unlock(&iflock);
10244          ast_module_unref(ast_module_info->self);
10245          return RESULT_SUCCESS;
10246       }
10247    }
10248    ast_mutex_unlock(&iflock);
10249    return RESULT_FAILURE;
10250 }

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

Definition at line 3654 of file chan_dahdi.c.

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

03655 {
03656    struct dahdi_pvt *pvt;
03657    int idx;
03658    int dtmf = -1;
03659    int res;
03660 
03661    pvt = chan->tech_pvt;
03662 
03663    ast_mutex_lock(&pvt->lock);
03664 
03665    idx = dahdi_get_index(chan, pvt, 0);
03666 
03667    if ((idx != SUB_REAL) || !pvt->owner)
03668       goto out;
03669 
03670 #ifdef HAVE_PRI
03671    switch (pvt->sig) {
03672    case SIG_PRI_LIB_HANDLE_CASES:
03673       res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
03674       if (!res)
03675          goto out;
03676       break;
03677    default:
03678       break;
03679    }
03680 #endif
03681    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
03682       goto out;
03683 
03684    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
03685       struct dahdi_dialoperation zo = {
03686          .op = DAHDI_DIAL_OP_APPEND,
03687       };
03688 
03689       zo.dialstr[0] = 'T';
03690       zo.dialstr[1] = digit;
03691       zo.dialstr[2] = '\0';
03692       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
03693          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
03694       else
03695          pvt->dialing = 1;
03696    } else {
03697       ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
03698       pvt->dialing = 1;
03699       pvt->begindigit = digit;
03700    }
03701 
03702 out:
03703    ast_mutex_unlock(&pvt->lock);
03704 
03705    return 0;
03706 }

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

Definition at line 3708 of file chan_dahdi.c.

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

03709 {
03710    struct dahdi_pvt *pvt;
03711    int res = 0;
03712    int idx;
03713    int x;
03714 
03715    pvt = chan->tech_pvt;
03716 
03717    ast_mutex_lock(&pvt->lock);
03718 
03719    idx = dahdi_get_index(chan, pvt, 0);
03720 
03721    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
03722       goto out;
03723 
03724 #ifdef HAVE_PRI
03725    /* This means that the digit was already sent via PRI signalling */
03726    if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
03727       goto out;
03728    }
03729 #endif
03730 
03731    if (pvt->begindigit) {
03732       x = -1;
03733       ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
03734       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
03735       pvt->dialing = 0;
03736       pvt->begindigit = 0;
03737    }
03738 
03739 out:
03740    ast_mutex_unlock(&pvt->lock);
03741 
03742    return res;
03743 }

static void dahdi_disable_ec ( struct dahdi_pvt p  )  [static]

Definition at line 4158 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_bridge(), dahdi_func_write(), dahdi_handle_event(), dahdi_hangup(), dahdi_setoption(), handle_init_event(), and my_set_echocanceller().

04159 {
04160    int res;
04161 
04162    if (p->echocanon) {
04163       struct dahdi_echocanparams ecp = { .tap_length = 0 };
04164 
04165       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04166 
04167       if (res)
04168          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04169       else
04170          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04171    }
04172 
04173    p->echocanon = 0;
04174 }

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

References analog_dnd(), analog_lib_handles(), ast_verb, dahdi_pvt::channel, dahdi_pvt::dnd, EVENT_FLAG_SYSTEM, manager_event, dahdi_pvt::oprmode, dahdi_pvt::radio, dahdi_pvt::sig, and dahdi_pvt::sig_pvt.

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

08768 {
08769    if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
08770       return analog_dnd(dahdichan->sig_pvt, flag);
08771    }
08772 
08773    if (flag == -1) {
08774       return dahdichan->dnd;
08775    }
08776 
08777    /* Do not disturb */
08778    dahdichan->dnd = flag;
08779    ast_verb(3, "%s DND on channel %d\n",
08780          flag? "Enabled" : "Disabled",
08781          dahdichan->channel);
08782    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
08783          "Channel: DAHDI/%d\r\n"
08784          "Status: %s\r\n", dahdichan->channel,
08785          flag? "enabled" : "disabled");
08786 
08787    return 0;
08788 }

static void dahdi_enable_ec ( struct dahdi_pvt p  )  [static]

Definition at line 4086 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_bridge(), dahdi_func_write(), dahdi_handle_event(), dahdi_indicate(), dahdi_setoption(), handle_init_event(), and my_set_echocanceller().

04087 {
04088    int res;
04089    if (!p)
04090       return;
04091    if (p->echocanon) {
04092       ast_debug(1, "Echo cancellation already on\n");
04093       return;
04094    }
04095    if (p->digital) {
04096       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04097       return;
04098    }
04099    if (p->echocancel.head.tap_length) {
04100 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04101       switch (p->sig) {
04102 #if defined(HAVE_PRI)
04103       case SIG_PRI_LIB_HANDLE_CASES:
04104          if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04105             /*
04106              * PRI nobch pseudo channel.  Does not need ec anyway.
04107              * Does not handle ioctl(DAHDI_AUDIOMODE)
04108              */
04109             return;
04110          }
04111          /* Fall through */
04112 #endif   /* defined(HAVE_PRI) */
04113 #if defined(HAVE_SS7)
04114       case SIG_SS7:
04115 #endif   /* defined(HAVE_SS7) */
04116          {
04117             int x = 1;
04118 
04119             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04120             if (res)
04121                ast_log(LOG_WARNING,
04122                   "Unable to enable audio mode on channel %d (%s)\n",
04123                   p->channel, strerror(errno));
04124          }
04125          break;
04126       default:
04127          break;
04128       }
04129 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
04130       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04131       if (res) {
04132          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04133       } else {
04134          p->echocanon = 1;
04135          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04136       }
04137    } else
04138       ast_debug(1, "No echo cancellation requested\n");
04139 }

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

Definition at line 7910 of file chan_dahdi.c.

References __dahdi_exception(), analog_exception(), analog_lib_handles(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::lock, dahdi_pvt::oprmode, dahdi_pvt::radio, dahdi_pvt::sig, dahdi_pvt::sig_pvt, and ast_channel::tech_pvt.

07911 {
07912    struct dahdi_pvt *p = ast->tech_pvt;
07913    struct ast_frame *f;
07914    ast_mutex_lock(&p->lock);
07915    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07916       struct analog_pvt *analog_p = p->sig_pvt;
07917       f = analog_exception(analog_p, ast);
07918    } else {
07919       f = __dahdi_exception(ast);
07920    }
07921    ast_mutex_unlock(&p->lock);
07922    return f;
07923 }

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

Definition at line 14830 of file chan_dahdi.c.

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

Referenced by action_transfer(), and action_transferhangup().

14831 {
14832    if (p) {
14833       switch (mode) {
14834       case TRANSFER:
14835          p->fake_event = DAHDI_EVENT_WINKFLASH;
14836          break;
14837       case HANGUP:
14838          p->fake_event = DAHDI_EVENT_ONHOOK;
14839          break;
14840       default:
14841          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
14842       }
14843    }
14844    return 0;
14845 }

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

Definition at line 6681 of file chan_dahdi.c.

References ast_channel::_state, analog_fixup(), analog_lib_handles(), AST_CONTROL_RINGING, ast_debug, ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RINGING, dahdi_pvt::channel, dahdi_indicate(), dahdi_sig_pri_lib_handles(), dahdi_unlink(), dahdi_pvt::lock, ast_channel::name, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::radio, dahdi_pvt::sig, sig_pri_fixup(), dahdi_pvt::sig_pvt, dahdi_pvt::subs, ast_channel::tech_pvt, and update_conf().

06682 {
06683    struct dahdi_pvt *p = newchan->tech_pvt;
06684    int x;
06685    ast_mutex_lock(&p->lock);
06686    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
06687    if (p->owner == oldchan) {
06688       p->owner = newchan;
06689    }
06690    for (x = 0; x < 3; x++)
06691       if (p->subs[x].owner == oldchan) {
06692          if (!x)
06693             dahdi_unlink(NULL, p, 0);
06694          p->subs[x].owner = newchan;
06695       }
06696    if (newchan->_state == AST_STATE_RINGING)
06697       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
06698 
06699    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06700       analog_fixup(oldchan, newchan, p->sig_pvt);
06701    } 
06702 #ifdef HAVE_PRI
06703    else if (dahdi_sig_pri_lib_handles(p->sig)) {
06704       sig_pri_fixup(oldchan, newchan, p->sig_pvt);
06705    }
06706 #endif
06707 
06708    update_conf(p);
06709    ast_mutex_unlock(&p->lock);
06710    return 0;
06711 }

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

Definition at line 6132 of file chan_dahdi.c.

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

06133 {
06134    struct dahdi_pvt *p = chan->tech_pvt;
06135    int res = 0;
06136 
06137    if (!strcasecmp(data, "rxgain")) {
06138       ast_mutex_lock(&p->lock);
06139       snprintf(buf, len, "%f", p->rxgain);
06140       ast_mutex_unlock(&p->lock);
06141    } else if (!strcasecmp(data, "txgain")) {
06142       ast_mutex_lock(&p->lock);
06143       snprintf(buf, len, "%f", p->txgain);
06144       ast_mutex_unlock(&p->lock);
06145 #if defined(HAVE_PRI)
06146 #if defined(HAVE_PRI_REVERSE_CHARGE)
06147    } else if (!strcasecmp(data, "reversecharge")) {
06148       ast_mutex_lock(&p->lock);
06149       switch (p->sig) {
06150       case SIG_PRI_LIB_HANDLE_CASES:
06151          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
06152          break;
06153       default:
06154          *buf = '\0';
06155          res = -1;
06156          break;
06157       }
06158       ast_mutex_unlock(&p->lock);
06159 #endif
06160 #if defined(HAVE_PRI_SETUP_KEYPAD)
06161    } else if (!strcasecmp(data, "keypad_digits")) {
06162       ast_mutex_lock(&p->lock);
06163       switch (p->sig) {
06164       case SIG_PRI_LIB_HANDLE_CASES:
06165          ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
06166             len);
06167          break;
06168       default:
06169          *buf = '\0';
06170          res = -1;
06171          break;
06172       }
06173       ast_mutex_unlock(&p->lock);
06174 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
06175 #endif   /* defined(HAVE_PRI) */
06176    } else {
06177       *buf = '\0';
06178       res = -1;
06179    }
06180 
06181    return res;
06182 }

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

Definition at line 6214 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_subchannel::dfd, dahdi_pvt::echocanon, errno, dahdi_pvt::lock, LOG_WARNING, parse_buffers_policy(), SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

06215 {
06216    struct dahdi_pvt *p = chan->tech_pvt;
06217    int res = 0;
06218 
06219    if (!strcasecmp(data, "buffers")) {
06220       int num_bufs, policy;
06221 
06222       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
06223          struct dahdi_bufferinfo bi = {
06224             .txbufpolicy = policy,
06225             .rxbufpolicy = policy,
06226             .bufsize = p->bufsize,
06227             .numbufs = num_bufs,
06228          };
06229          int bpres;
06230 
06231          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06232             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
06233          } else {
06234             p->bufferoverrideinuse = 1;
06235          }
06236       } else {
06237          res = -1;
06238       }
06239    } else if (!strcasecmp(data, "echocan_mode")) {
06240       if (!strcasecmp(value, "on")) {
06241          ast_mutex_lock(&p->lock);
06242          dahdi_enable_ec(p);
06243          ast_mutex_unlock(&p->lock);
06244       } else if (!strcasecmp(value, "off")) {
06245          ast_mutex_lock(&p->lock);
06246          dahdi_disable_ec(p);
06247          ast_mutex_unlock(&p->lock);
06248 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
06249       } else if (!strcasecmp(value, "fax")) {
06250          int blah = 1;
06251 
06252          ast_mutex_lock(&p->lock);
06253          if (!p->echocanon) {
06254             dahdi_enable_ec(p);
06255          }
06256          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
06257             ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
06258          }
06259          ast_mutex_unlock(&p->lock);
06260       } else if (!strcasecmp(value, "voice")) {
06261          int blah = 0;
06262 
06263          ast_mutex_lock(&p->lock);
06264          if (!p->echocanon) {
06265             dahdi_enable_ec(p);
06266          }
06267          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
06268             ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
06269          }
06270          ast_mutex_unlock(&p->lock);
06271 #endif
06272       } else {
06273          ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
06274          res = -1;
06275       }
06276    } else {
06277       res = -1;
06278    }
06279 
06280    return res;
06281 }

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

Avoid the silly dahdi_getevent which ignores a bunch of events.

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

00476 {
00477    int j;
00478    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00479       return -1;
00480    return j;
00481 }

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

Definition at line 2952 of file chan_dahdi.c.

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

Referenced by __dahdi_exception(), analog_ss_thread(), dahdi_answer(), dahdi_bridge(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_read(), dahdi_sendtext(), dahdi_setoption(), and dahdi_write().

02953 {
02954    int res;
02955    if (p->subs[SUB_REAL].owner == ast)
02956       res = 0;
02957    else if (p->subs[SUB_CALLWAIT].owner == ast)
02958       res = 1;
02959    else if (p->subs[SUB_THREEWAY].owner == ast)
02960       res = 2;
02961    else {
02962       res = -1;
02963       if (!nullok)
02964          ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
02965    }
02966    return res;
02967 }

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

Definition at line 6850 of file chan_dahdi.c.

References ast_async_goto(), ast_channel_lock, ast_channel_unlock, AST_CONTROL_ANSWER, ast_debug, ast_dsp_set_features(), ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_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, ast_channel::cid, ast_callerid::cid_num, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, ast_channel::context, dahdi_confmute(), dahdi_subchannel::dfd, dahdi_pvt::dsp, DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, errno, ast_channel::exten, dahdi_subchannel::f, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, dahdi_pvt::faxhandled, ast_frame::frametype, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, ast_channel::name, pbx_builtin_setvar_helper(), S_OR, send_cwcidspill(), ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, and dahdi_pvt::usefaxbuffers.

Referenced by dahdi_handle_event(), and dahdi_read().

06851 {
06852    struct dahdi_pvt *p = ast->tech_pvt;
06853    struct ast_frame *f = *dest;
06854 
06855    ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name);
06856 
06857    if (p->confirmanswer) {
06858       ast_debug(1, "Confirm answer on %s!\n", ast->name);
06859       /* Upon receiving a DTMF digit, consider this an answer confirmation instead
06860          of a DTMF digit */
06861       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06862       p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06863       *dest = &p->subs[idx].f;
06864       /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
06865       p->confirmanswer = 0;
06866    } else if (p->callwaitcas) {
06867       if ((f->subclass == 'A') || (f->subclass == 'D')) {
06868          ast_debug(1, "Got some DTMF, but it's for the CAS\n");
06869          if (p->cidspill)
06870             ast_free(p->cidspill);
06871          send_cwcidspill(p);
06872       }
06873       p->callwaitcas = 0;
06874       p->subs[idx].f.frametype = AST_FRAME_NULL;
06875       p->subs[idx].f.subclass = 0;
06876       *dest = &p->subs[idx].f;
06877    } else if (f->subclass == 'f') {
06878       /* Fax tone -- Handle and return NULL */
06879       if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
06880          /* If faxbuffers are configured, use them for the fax transmission */
06881          if (p->usefaxbuffers && !p->bufferoverrideinuse) {
06882             struct dahdi_bufferinfo bi = {
06883                .txbufpolicy = p->faxbuf_policy,
06884                .bufsize = p->bufsize,
06885                .numbufs = p->faxbuf_no
06886             };
06887             int res;
06888 
06889             if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06890                ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
06891             } else {
06892                p->bufferoverrideinuse = 1;
06893             }
06894          }
06895          p->faxhandled = 1;
06896          p->callprogress &= ~CALLPROGRESS_FAX;
06897          p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06898          ast_dsp_set_features(p->dsp, p->dsp_features);
06899          ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
06900          if (strcmp(ast->exten, "fax")) {
06901             const char *target_context = S_OR(ast->macrocontext, ast->context);
06902 
06903             /* We need to unlock 'ast' here because ast_exists_extension has the
06904              * potential to start autoservice on the channel. Such action is prone
06905              * to deadlock.
06906              */
06907             ast_mutex_unlock(&p->lock);
06908             ast_channel_unlock(ast);
06909             if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
06910                ast_channel_lock(ast);
06911                ast_mutex_lock(&p->lock);
06912                ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
06913                /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
06914                pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
06915                if (ast_async_goto(ast, target_context, "fax", 1))
06916                   ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
06917             } else {
06918                ast_channel_lock(ast);
06919                ast_mutex_lock(&p->lock);
06920                ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
06921             }
06922          } else {
06923             ast_debug(1, "Already in a fax extension, not redirecting\n");
06924          }
06925       } else {
06926          ast_debug(1, "Fax already handled\n");
06927       }
06928       dahdi_confmute(p, 0);
06929       p->subs[idx].f.frametype = AST_FRAME_NULL;
06930       p->subs[idx].f.subclass = 0;
06931       *dest = &p->subs[idx].f;
06932    }
06933 }

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

Definition at line 6946 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, alloc_sub(), analog_ss_thread(), dahdi_pvt::answeronpolarityswitch, ast_bridged_channel(), AST_CAUSE_NO_ANSWER, ast_channel_trylock, ast_channel_unlock, AST_CONTROL_ANSWER, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_free, ast_hangup(), ast_log(), ast_pthread_create_detached, ast_queue_control(), ast_queue_control_data(), ast_queue_hangup_with_cause(), ast_setstate(), ast_softhangup(), AST_SOFTHANGUP_DEV, AST_SOFTHANGUP_EXPLICIT, AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DIALING_OFFHOOK, AST_STATE_DOWN, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strdup, ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, attempt_transfer(), dahdi_pvt::callprogress, CALLPROGRESS_PROGRESS, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitingrepeat, CANPROGRESSDETECT, ast_channel::cdr, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, check_for_conference(), ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_ani2, dahdi_pvt::cid_name, ast_callerid::cid_name, cid_name, dahdi_pvt::cid_num, ast_callerid::cid_num, cid_num, dahdi_pvt::cidcwexpire, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_confmute(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index(), dahdi_handle_dtmfup(), 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(), EVENT_FLAG_SYSTEM, dahdi_subchannel::f, dahdi_pvt::fake_event, dahdi_pvt::finaldial, dahdi_pvt::flashtime, ast_frame::frametype, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::inalarm, dahdi_subchannel::inthreeway, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, manager_event, MIN_MS_SINCE_FLASH, dahdi_pvt::mohsuggest, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, 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, ast_channel::pbx, dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pvt::polaritydelaytv, dahdi_pvt::polarityonanswerdelay, ast_frame::ptr, dahdi_pvt::pulsedial, dahdi_pvt::radio, restore_conference(), ast_channel::rings, dahdi_pvt::ringt, dahdi_pvt::ringt_base, S_OR, ast_frame::samples, save_conference(), dahdi_pvt::sig, sig2str, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, sig_pri_chan_alarm_notify(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, ast_frame::src, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, ast_frame::subclass, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, dahdi_pvt::threewaycalling, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, unalloc_sub(), update_conf(), dahdi_pvt::waitingfordt, and dahdi_pvt::whichwink.

Referenced by __dahdi_exception().

06947 {
06948    int res, x;
06949    int idx, mysig;
06950    char *c;
06951    struct dahdi_pvt *p = ast->tech_pvt;
06952    pthread_t threadid;
06953    struct ast_channel *chan;
06954    struct ast_frame *f;
06955 
06956    idx = dahdi_get_index(ast, p, 0);
06957    mysig = p->sig;
06958    if (p->outsigmod > -1)
06959       mysig = p->outsigmod;
06960    p->subs[idx].f.frametype = AST_FRAME_NULL;
06961    p->subs[idx].f.subclass = 0;
06962    p->subs[idx].f.datalen = 0;
06963    p->subs[idx].f.samples = 0;
06964    p->subs[idx].f.mallocd = 0;
06965    p->subs[idx].f.offset = 0;
06966    p->subs[idx].f.src = "dahdi_handle_event";
06967    p->subs[idx].f.data.ptr = NULL;
06968    f = &p->subs[idx].f;
06969 
06970    if (idx < 0)
06971       return &p->subs[idx].f;
06972    if (p->fake_event) {
06973       res = p->fake_event;
06974       p->fake_event = 0;
06975    } else
06976       res = dahdi_get_event(p->subs[idx].dfd);
06977 
06978    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
06979 
06980    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
06981       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
06982       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
06983 #ifdef HAVE_PRI
06984       if (dahdi_sig_pri_lib_handles(p->sig)
06985          && !((struct sig_pri_chan *) p->sig_pvt)->proceeding
06986          && p->pri
06987          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
06988          /* absorb event */
06989       } else {
06990 #endif
06991          dahdi_confmute(p, 0);
06992          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
06993          p->subs[idx].f.subclass = res & 0xff;
06994 #ifdef HAVE_PRI
06995       }
06996 #endif
06997       dahdi_handle_dtmfup(ast, idx, &f);
06998       return f;
06999    }
07000 
07001    if (res & DAHDI_EVENT_DTMFDOWN) {
07002       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07003       /* Mute conference */
07004       dahdi_confmute(p, 1);
07005       p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07006       p->subs[idx].f.subclass = res & 0xff;
07007       return &p->subs[idx].f;
07008    }
07009 
07010    switch (res) {
07011    case DAHDI_EVENT_EC_DISABLED:
07012       ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07013       p->echocanon = 0;
07014       break;
07015 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07016    case DAHDI_EVENT_TX_CED_DETECTED:
07017       ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07018       break;
07019    case DAHDI_EVENT_RX_CED_DETECTED:
07020       ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07021       break;
07022    case DAHDI_EVENT_EC_NLP_DISABLED:
07023       ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07024       break;
07025    case DAHDI_EVENT_EC_NLP_ENABLED:
07026       ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07027       break;
07028 #endif
07029    case DAHDI_EVENT_BITSCHANGED:
07030 #ifdef HAVE_OPENR2
07031       if (p->sig != SIG_MFCR2) {
07032          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07033       } else {
07034          ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07035          openr2_chan_handle_cas(p->r2chan);
07036       }
07037 #else
07038       ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07039 #endif
07040    case DAHDI_EVENT_PULSE_START:
07041       /* Stop tone if there's a pulse start and the PBX isn't started */
07042       if (!ast->pbx)
07043          tone_zone_play_tone(p->subs[idx].dfd, -1);
07044       break;
07045    case DAHDI_EVENT_DIALCOMPLETE:
07046 #ifdef HAVE_OPENR2
07047       if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
07048          /* we don't need to do anything for this event for R2 signaling
07049             if the call is being setup */
07050          break;
07051       }
07052 #endif
07053       if (p->inalarm) break;
07054       if ((p->radio || (p->oprmode < 0))) break;
07055       if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
07056          ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
07057          return NULL;
07058       }
07059       if (!x) { /* if not still dialing in driver */
07060          dahdi_enable_ec(p);
07061          if (p->echobreak) {
07062             dahdi_train_ec(p);
07063             ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
07064             p->dop.op = DAHDI_DIAL_OP_REPLACE;
07065             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07066             p->echobreak = 0;
07067          } else {
07068             p->dialing = 0;
07069             if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
07070                /* if thru with dialing after offhook */
07071                if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
07072                   ast_setstate(ast, AST_STATE_UP);
07073                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07074                   p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
07075                   break;
07076                } else { /* if to state wait for offhook to dial rest */
07077                   /* we now wait for off hook */
07078                   ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
07079                }
07080             }
07081             if (ast->_state == AST_STATE_DIALING) {
07082                if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
07083                   ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
07084                } else if (p->confirmanswer || (!p->dialednone
07085                   && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
07086                      || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
07087                      || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
07088                      || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
07089                      || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
07090                      || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
07091                      || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
07092                      || (mysig == SIG_SF_FEATB)))) {
07093                   ast_setstate(ast, AST_STATE_RINGING);
07094                } else if (!p->answeronpolarityswitch) {
07095                   ast_setstate(ast, AST_STATE_UP);
07096                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07097                   p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
07098                   /* If aops=0 and hops=1, this is necessary */
07099                   p->polarity = POLARITY_REV;
07100                } else {
07101                   /* Start clean, so we can catch the change to REV polarity when party answers */
07102                   p->polarity = POLARITY_IDLE;
07103                }
07104             }
07105          }
07106       }
07107       break;
07108    case DAHDI_EVENT_ALARM:
07109 #ifdef HAVE_PRI
07110       switch (p->sig) {
07111       case SIG_PRI_LIB_HANDLE_CASES:
07112          sig_pri_chan_alarm_notify(p->sig_pvt, 0);
07113          break;
07114       default:
07115          break;
07116       }
07117 #endif
07118       p->inalarm = 1;
07119       res = get_alarms(p);
07120       handle_alarms(p, res);
07121 #ifdef HAVE_PRI
07122       if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
07123          /* fall through intentionally */
07124       } else {
07125          break;
07126       }
07127 #endif
07128 #ifdef HAVE_SS7
07129       if (p->sig == SIG_SS7)
07130          break;
07131 #endif
07132 #ifdef HAVE_OPENR2
07133       if (p->sig == SIG_MFCR2)
07134          break;
07135 #endif
07136    case DAHDI_EVENT_ONHOOK:
07137       if (p->radio) {
07138          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07139          p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
07140          break;
07141       }
07142       if (p->oprmode < 0)
07143       {
07144          if (p->oprmode != -1) break;
07145          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
07146          {
07147             /* Make sure it starts ringing */
07148             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
07149             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
07150             save_conference(p->oprpeer);
07151             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07152          }
07153          break;
07154       }
07155       switch (p->sig) {
07156       case SIG_FXOLS:
07157       case SIG_FXOGS:
07158       case SIG_FXOKS:
07159          /* Check for some special conditions regarding call waiting */
07160          if (idx == SUB_REAL) {
07161             /* The normal line was hung up */
07162             if (p->subs[SUB_CALLWAIT].owner) {
07163                /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
07164                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
07165                ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
07166                unalloc_sub(p, SUB_CALLWAIT);
07167 #if 0
07168                p->subs[idx].needanswer = 0;
07169                p->subs[idx].needringing = 0;
07170 #endif
07171                p->callwaitingrepeat = 0;
07172                p->cidcwexpire = 0;
07173                p->owner = NULL;
07174                /* Don't start streaming audio yet if the incoming call isn't up yet */
07175                if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
07176                   p->dialing = 1;
07177                dahdi_ring_phone(p);
07178             } else if (p->subs[SUB_THREEWAY].owner) {
07179                unsigned int mssinceflash;
07180                /* Here we have to retain the lock on both the main channel, the 3-way channel, and
07181                   the private structure -- not especially easy or clean */
07182                while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
07183                   /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
07184                   DLA_UNLOCK(&p->lock);
07185                   CHANNEL_DEADLOCK_AVOIDANCE(ast);
07186                   /* We can grab ast and p in that order, without worry.  We should make sure
07187                      nothing seriously bad has happened though like some sort of bizarre double
07188                      masquerade! */
07189                   DLA_LOCK(&p->lock);
07190                   if (p->owner != ast) {
07191                      ast_log(LOG_WARNING, "This isn't good...\n");
07192                      return NULL;
07193                   }
07194                }
07195                if (!p->subs[SUB_THREEWAY].owner) {
07196                   ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
07197                   return NULL;
07198                }
07199                mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
07200                ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
07201                if (mssinceflash < MIN_MS_SINCE_FLASH) {
07202                   /* It hasn't been long enough since the last flashook.  This is probably a bounce on
07203                      hanging up.  Hangup both channels now */
07204                   if (p->subs[SUB_THREEWAY].owner)
07205                      ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
07206                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07207                   ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
07208                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07209                } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
07210                   if (p->transfer) {
07211                      /* In any case this isn't a threeway call anymore */
07212                      p->subs[SUB_REAL].inthreeway = 0;
07213                      p->subs[SUB_THREEWAY].inthreeway = 0;
07214                      /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
07215                      if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
07216                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07217                         /* Swap subs and dis-own channel */
07218                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
07219                         p->owner = NULL;
07220                         /* Ring the phone */
07221                         dahdi_ring_phone(p);
07222                      } else {
07223                         if ((res = attempt_transfer(p)) < 0) {
07224                            p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07225                            if (p->subs[SUB_THREEWAY].owner)
07226                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07227                         } else if (res) {
07228                            /* Don't actually hang up at this point */
07229                            if (p->subs[SUB_THREEWAY].owner)
07230                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07231                            break;
07232                         }
07233                      }
07234                   } else {
07235                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07236                      if (p->subs[SUB_THREEWAY].owner)
07237                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07238                   }
07239                } else {
07240                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07241                   /* Swap subs and dis-own channel */
07242                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
07243                   p->owner = NULL;
07244                   /* Ring the phone */
07245                   dahdi_ring_phone(p);
07246                }
07247             }
07248          } else {
07249             ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
07250          }
07251          /* Fall through */
07252       default:
07253          dahdi_disable_ec(p);
07254          return NULL;
07255       }
07256       break;
07257    case DAHDI_EVENT_RINGOFFHOOK:
07258       if (p->inalarm) break;
07259       if (p->oprmode < 0)
07260       {
07261          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
07262          {
07263             /* Make sure it stops ringing */
07264             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
07265             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
07266             restore_conference(p->oprpeer);
07267          }
07268          break;
07269       }
07270       if (p->radio)
07271       {
07272          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07273          p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
07274          break;
07275       }
07276       /* for E911, its supposed to wait for offhook then dial
07277          the second half of the dial string */
07278       if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
07279          c = strchr(p->dialdest, '/');
07280          if (c)
07281             c++;
07282          else
07283             c = p->dialdest;
07284          if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
07285          else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
07286          if (strlen(p->dop.dialstr) > 4) {
07287             memset(p->echorest, 'w', sizeof(p->echorest) - 1);
07288             strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
07289             p->echorest[sizeof(p->echorest) - 1] = '\0';
07290             p->echobreak = 1;
07291             p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
07292          } else
07293             p->echobreak = 0;
07294          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
07295             int saveerr = errno;
07296 
07297             x = DAHDI_ONHOOK;
07298             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07299             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
07300             return NULL;
07301             }
07302          p->dialing = 1;
07303          return &p->subs[idx].f;
07304       }
07305       switch (p->sig) {
07306       case SIG_FXOLS:
07307       case SIG_FXOGS:
07308       case SIG_FXOKS:
07309          switch (ast->_state) {
07310          case AST_STATE_RINGING:
07311             dahdi_enable_ec(p);
07312             dahdi_train_ec(p);
07313             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07314             p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
07315             /* Make sure it stops ringing */
07316             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
07317             ast_debug(1, "channel %d answered\n", p->channel);
07318             if (p->cidspill) {
07319                /* Cancel any running CallerID spill */
07320                ast_free(p->cidspill);
07321                p->cidspill = NULL;
07322             }
07323             p->dialing = 0;
07324             p->callwaitcas = 0;
07325             if (p->confirmanswer) {
07326                /* Ignore answer if "confirm answer" is enabled */
07327                p->subs[idx].f.frametype = AST_FRAME_NULL;
07328                p->subs[idx].f.subclass = 0;
07329             } else if (!ast_strlen_zero(p->dop.dialstr)) {
07330                /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
07331                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07332                if (res < 0) {
07333                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
07334                   p->dop.dialstr[0] = '\0';
07335                   return NULL;
07336                } else {
07337                   ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
07338                   p->subs[idx].f.frametype = AST_FRAME_NULL;
07339                   p->subs[idx].f.subclass = 0;
07340                   p->dialing = 1;
07341                }
07342                p->dop.dialstr[0] = '\0';
07343                ast_setstate(ast, AST_STATE_DIALING);
07344             } else
07345                ast_setstate(ast, AST_STATE_UP);
07346             return &p->subs[idx].f;
07347          case AST_STATE_DOWN:
07348             ast_setstate(ast, AST_STATE_RING);
07349             ast->rings = 1;
07350             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07351             p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
07352             ast_debug(1, "channel %d picked up\n", p->channel);
07353             return &p->subs[idx].f;
07354          case AST_STATE_UP:
07355             /* Make sure it stops ringing */
07356             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
07357             /* Okay -- probably call waiting*/
07358             if (ast_bridged_channel(p->owner))
07359                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
07360             p->subs[idx].needunhold = 1;
07361             break;
07362          case AST_STATE_RESERVED:
07363             /* Start up dialtone */
07364             if (has_voicemail(p))
07365                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
07366             else
07367                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
07368             break;
07369          default:
07370             ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
07371          }
07372          break;
07373       case SIG_FXSLS:
07374       case SIG_FXSGS:
07375       case SIG_FXSKS:
07376          if (ast->_state == AST_STATE_RING) {
07377             p->ringt = p->ringt_base;
07378          }
07379 
07380          /* If we get a ring then we cannot be in
07381           * reversed polarity. So we reset to idle */
07382          ast_debug(1, "Setting IDLE polarity due "
07383             "to ring. Old polarity was %d\n",
07384             p->polarity);
07385          p->polarity = POLARITY_IDLE;
07386 
07387          /* Fall through */
07388       case SIG_EM:
07389       case SIG_EM_E1:
07390       case SIG_EMWINK:
07391       case SIG_FEATD:
07392       case SIG_FEATDMF:
07393       case SIG_FEATDMF_TA:
07394       case SIG_E911:
07395       case SIG_FGC_CAMA:
07396       case SIG_FGC_CAMAMF:
07397       case SIG_FEATB:
07398       case SIG_SF:
07399       case SIG_SFWINK:
07400       case SIG_SF_FEATD:
07401       case SIG_SF_FEATDMF:
07402       case SIG_SF_FEATB:
07403          if (ast->_state == AST_STATE_PRERING)
07404             ast_setstate(ast, AST_STATE_RING);
07405          if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
07406             ast_debug(1, "Ring detected\n");
07407             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07408             p->subs[idx].f.subclass = AST_CONTROL_RING;
07409          } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
07410             ast_debug(1, "Line answered\n");
07411             if (p->confirmanswer) {
07412                p->subs[idx].f.frametype = AST_FRAME_NULL;
07413                p->subs[idx].f.subclass = 0;
07414             } else {
07415                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07416                p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
07417                ast_setstate(ast, AST_STATE_UP);
07418             }
07419          } else if (ast->_state != AST_STATE_RING)
07420             ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
07421          break;
07422       default:
07423          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
07424       }
07425       break;
07426    case DAHDI_EVENT_RINGBEGIN:
07427       switch (p->sig) {
07428       case SIG_FXSLS:
07429       case SIG_FXSGS:
07430       case SIG_FXSKS:
07431          if (ast->_state == AST_STATE_RING) {
07432             p->ringt = p->ringt_base;
07433          }
07434          break;
07435       }
07436       break;
07437    case DAHDI_EVENT_RINGERON:
07438       break;
07439    case DAHDI_EVENT_NOALARM:
07440 #ifdef HAVE_PRI
07441       switch (p->sig) {
07442       case SIG_PRI_LIB_HANDLE_CASES:
07443          sig_pri_chan_alarm_notify(p->sig_pvt, 1);
07444          break;
07445       default:
07446          break;
07447       }
07448 #endif
07449       p->inalarm = 0;
07450       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
07451       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
07452                      "Channel: %d\r\n", p->channel);
07453       break;
07454    case DAHDI_EVENT_WINKFLASH:
07455       if (p->inalarm) break;
07456       if (p->radio) break;
07457       if (p->oprmode < 0) break;
07458       if (p->oprmode > 1)
07459       {
07460          struct dahdi_params par;
07461 
07462          memset(&par, 0, sizeof(par));
07463          if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
07464          {
07465             if (!par.rxisoffhook)
07466             {
07467                /* Make sure it stops ringing */
07468                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
07469                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
07470                save_conference(p);
07471                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07472             }
07473          }
07474          break;
07475       }
07476       /* Remember last time we got a flash-hook */
07477       p->flashtime = ast_tvnow();
07478       switch (mysig) {
07479       case SIG_FXOLS:
07480       case SIG_FXOGS:
07481       case SIG_FXOKS:
07482          ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
07483             idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
07484          p->callwaitcas = 0;
07485 
07486          if (idx != SUB_REAL) {
07487             ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
07488             goto winkflashdone;
07489          }
07490 
07491          if (p->subs[SUB_CALLWAIT].owner) {
07492             /* Swap to call-wait */
07493             swap_subs(p, SUB_REAL, SUB_CALLWAIT);
07494             tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
07495             p->owner = p->subs[SUB_REAL].owner;
07496             ast_debug(1, "Making %s the new owner\n", p->owner->name);
07497             if (p->owner->_state == AST_STATE_RINGING) {
07498                ast_setstate(p->owner, AST_STATE_UP);
07499                p->subs[SUB_REAL].needanswer = 1;
07500             }
07501             p->callwaitingrepeat = 0;
07502             p->cidcwexpire = 0;
07503             /* Start music on hold if appropriate */
07504             if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
07505                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
07506                   S_OR(p->mohsuggest, NULL),
07507                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
07508             }
07509             p->subs[SUB_CALLWAIT].needhold = 1;
07510             if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07511                ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
07512                   S_OR(p->mohsuggest, NULL),
07513                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
07514             }
07515             p->subs[SUB_REAL].needunhold = 1;
07516          } else if (!p->subs[SUB_THREEWAY].owner) {
07517             if (!p->threewaycalling) {
07518                /* Just send a flash if no 3-way calling */
07519                p->subs[SUB_REAL].needflash = 1;
07520                goto winkflashdone;
07521             } else if (!check_for_conference(p)) {
07522                char cid_num[256];
07523                char cid_name[256];
07524 
07525                cid_num[0] = 0;
07526                cid_name[0] = 0;
07527                if (p->dahditrcallerid && p->owner) {
07528                   if (p->owner->cid.cid_num)
07529                      ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
07530                   if (p->owner->cid.cid_name)
07531                      ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
07532                }
07533                /* XXX This section needs much more error checking!!! XXX */
07534                /* Start a 3-way call if feasible */
07535                if (!((ast->pbx) ||
07536                   (ast->_state == AST_STATE_UP) ||
07537                   (ast->_state == AST_STATE_RING))) {
07538                   ast_debug(1, "Flash when call not up or ringing\n");
07539                   goto winkflashdone;
07540                }
07541                if (alloc_sub(p, SUB_THREEWAY)) {
07542                   ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
07543                   goto winkflashdone;
07544                }
07545                /* Make new channel */
07546                chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0, 0);
07547                if (p->dahditrcallerid) {
07548                   if (!p->origcid_num)
07549                      p->origcid_num = ast_strdup(p->cid_num);
07550                   if (!p->origcid_name)
07551                      p->origcid_name = ast_strdup(p->cid_name);
07552                   ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
07553                   ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
07554                }
07555                /* Swap things around between the three-way and real call */
07556                swap_subs(p, SUB_THREEWAY, SUB_REAL);
07557                /* Disable echo canceller for better dialing */
07558                dahdi_disable_ec(p);
07559                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
07560                if (res)
07561                   ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
07562                p->owner = chan;
07563                if (!chan) {
07564                   ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
07565                } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
07566                   ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
07567                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07568                   dahdi_enable_ec(p);
07569                   ast_hangup(chan);
07570                } else {
07571                   struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
07572                   int way3bridge = 0, cdr3way = 0;
07573 
07574                      if (!other) {
07575                      other = ast_bridged_channel(p->subs[SUB_REAL].owner);
07576                   } else
07577                      way3bridge = 1;
07578 
07579                      if (p->subs[SUB_THREEWAY].owner->cdr)
07580                      cdr3way = 1;
07581 
07582                   ast_verb(3, "Started three way call on channel %d\n", p->channel);
07583 
07584                   /* Start music on hold if appropriate */
07585                   if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07586                      ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
07587                         S_OR(p->mohsuggest, NULL),
07588                         !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
07589                   }
07590                   p->subs[SUB_THREEWAY].needhold = 1;
07591                }
07592             }
07593          } else {
07594             /* Already have a 3 way call */
07595             if (p->subs[SUB_THREEWAY].inthreeway) {
07596                /* Call is already up, drop the last person */
07597                ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
07598                /* If the primary call isn't answered yet, use it */
07599                if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
07600                   /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
07601                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
07602                   p->owner = p->subs[SUB_REAL].owner;
07603                }
07604                /* Drop the last call and stop the conference */
07605                ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
07606                p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07607                p->subs[SUB_REAL].inthreeway = 0;
07608                p->subs[SUB_THREEWAY].inthreeway = 0;
07609             } else {
07610                /* Lets see what we're up to */
07611                if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
07612                   (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
07613                   int otherindex = SUB_THREEWAY;
07614                   struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
07615                   int way3bridge = 0, cdr3way = 0;
07616 
07617                   if (!other) {
07618                      other = ast_bridged_channel(p->subs[SUB_REAL].owner);
07619                   } else
07620                      way3bridge = 1;
07621 
07622                   if (p->subs[SUB_THREEWAY].owner->cdr)
07623                      cdr3way = 1;
07624 
07625                   ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
07626                   /* Put them in the threeway, and flip */
07627                   p->subs[SUB_THREEWAY].inthreeway = 1;
07628                   p->subs[SUB_REAL].inthreeway = 1;
07629                   if (ast->_state == AST_STATE_UP) {
07630                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
07631                      otherindex = SUB_REAL;
07632                   }
07633                   if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
07634                      ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
07635                   p->subs[otherindex].needunhold = 1;
07636                   p->owner = p->subs[SUB_REAL].owner;
07637                   if (ast->_state == AST_STATE_RINGING) {
07638                      ast_debug(1, "Enabling ringtone on real and threeway\n");
07639                      res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07640                      res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07641                   }
07642                } else {
07643                   ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
07644                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
07645                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07646                   p->owner = p->subs[SUB_REAL].owner;
07647                   if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
07648                      ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07649                   p->subs[SUB_REAL].needunhold = 1;
07650                   dahdi_enable_ec(p);
07651                }
07652             }
07653          }
07654 winkflashdone:
07655          update_conf(p);
07656          break;
07657       case SIG_EM:
07658       case SIG_EM_E1:
07659       case SIG_FEATD:
07660       case SIG_SF:
07661       case SIG_SFWINK:
07662       case SIG_SF_FEATD:
07663       case SIG_FXSLS:
07664       case SIG_FXSGS:
07665          if (p->dialing)
07666             ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
07667          else
07668             ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
07669          break;
07670       case SIG_FEATDMF_TA:
07671          switch (p->whichwink) {
07672          case 0:
07673             ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
07674             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
07675             break;
07676          case 1:
07677             ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
07678             break;
07679          case 2:
07680             ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
07681             return NULL;
07682          }
07683          p->whichwink++;
07684          /* Fall through */
07685       case SIG_FEATDMF:
07686       case SIG_E911:
07687       case SIG_FGC_CAMAMF:
07688       case SIG_FGC_CAMA:
07689       case SIG_FEATB:
07690       case SIG_SF_FEATDMF:
07691       case SIG_SF_FEATB:
07692       case SIG_EMWINK:
07693          /* FGD MF and EMWINK *Must* wait for wink */
07694          if (!ast_strlen_zero(p->dop.dialstr)) {
07695             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07696             if (res < 0) {
07697                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
07698                p->dop.dialstr[0] = '\0';
07699                return NULL;
07700             } else
07701                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
07702          }
07703          p->dop.dialstr[0] = '\0';
07704          break;
07705       default:
07706          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
07707       }
07708       break;
07709    case DAHDI_EVENT_HOOKCOMPLETE:
07710       if (p->inalarm) break;
07711       if ((p->radio || (p->oprmode < 0))) break;
07712       if (p->waitingfordt.tv_sec) break;
07713       switch (mysig) {
07714       case SIG_FXSLS:  /* only interesting for FXS */
07715       case SIG_FXSGS:
07716       case SIG_FXSKS:
07717       case SIG_EM:
07718       case SIG_EM_E1:
07719       case SIG_EMWINK:
07720       case SIG_FEATD:
07721       case SIG_SF:
07722       case SIG_SFWINK:
07723       case SIG_SF_FEATD:
07724          if (!ast_strlen_zero(p->dop.dialstr)) {
07725             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07726             if (res < 0) {
07727                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
07728                p->dop.dialstr[0] = '\0';
07729                return NULL;
07730             } else
07731                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
07732          }
07733          p->dop.dialstr[0] = '\0';
07734          p->dop.op = DAHDI_DIAL_OP_REPLACE;
07735          break;
07736       case SIG_FEATDMF:
07737       case SIG_FEATDMF_TA:
07738       case SIG_E911:
07739       case SIG_FGC_CAMA:
07740       case SIG_FGC_CAMAMF:
07741       case SIG_FEATB:
07742       case SIG_SF_FEATDMF:
07743       case SIG_SF_FEATB:
07744          ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
07745          break;
07746       default:
07747          break;
07748       }
07749       break;
07750    case DAHDI_EVENT_POLARITY:
07751       /*
07752