Mon Nov 24 15:34:27 2008

Asterisk developer's documentation


chan_dahdi.c File Reference

DAHDI Pseudo TDM interface. More...

#include "asterisk.h"
#include <stdio.h>
#include <string.h>
#include <sys/signal.h>
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <math.h>
#include <ctype.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.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/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/dahdi_compat.h"
#include "asterisk/tonezone_compat.h"

Go to the source code of this file.

Data Structures

struct  dahdi_chan_conf
 Channel configuration from chan_dahdi.conf . This struct is used for parsing the [channels] section of chan_dahdi.conf. Generally there is a field here for every possible configuration item. More...
struct  dahdi_distRings
struct  dahdi_pvt
struct  dahdi_subchannel
struct  distRingData
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 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 CHANNEL_PSEUDO   -12
#define CIDCW_EXPIRE_SAMPLES   ( (500 * 8) / READ_SIZE)
#define CONF_USER_REAL   (1 << 0)
#define CONF_USER_THIRDCALL   (1 << 1)
#define DAHDI_EVENT_DTMFDOWN   0
#define DAHDI_EVENT_DTMFUP   0
#define DCHAN_AVAILABLE   (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
#define DCHAN_NOTINALARM   (1 << 1)
#define DCHAN_PROVISIONED   (1 << 0)
#define DCHAN_UP   (1 << 2)
#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 %-10.10s %-10d %-10d %-10d\n"
#define FORMAT   "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
#define FORMAT2   "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
#define FORMAT2   "%7s %-10.10s %-15.15s %-10.10s %-20.20s\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 local_astman_ack(s, m, msg, zap)   do { if (!zap) astman_send_ack(s, m, "DAHDI" msg); else astman_send_ack(s, m, "Zap" msg); } while (0)
#define local_astman_header(m, hdr, zap)   astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
#define local_astman_register(a, b, c, d)
#define local_astman_unregister(a)
#define MASK_AVAIL   (1 << 0)
#define MASK_INUSE   (1 << 1)
#define MAX_CHANLIST_LEN   80
#define MAX_CHANNELS   672
#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_DCHANS   4
#define NUM_SPANS   32
#define POLARITY_IDLE   0
#define POLARITY_REV   1
#define READ_SIZE   160
#define sig2str   dahdi_sig2str
#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_GR303FXOKS   (0x0100000 | DAHDI_SIG_FXOKS)
#define SIG_GR303FXSKS   (0x0100000 | DAHDI_SIG_FXSKS)
#define SIG_PRI   DAHDI_SIG_CLEAR
#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 SMDI_MD_WAIT_TIMEOUT   1500
#define SUB_CALLWAIT   1
#define SUB_REAL   0
#define SUB_THREEWAY   2
#define tdesc   "DAHDI Telephony"
#define TRAILER_MS   5
#define TRANSFER   0

Functions

static int __action_dialoffhook (struct mansession *s, const struct message *m, int zap_mode)
static int __action_dnd (struct mansession *s, const struct message *m, int zap_mode, int dnd)
static int __action_restart (struct mansession *s, const struct message *m, int zap_mode)
static int __action_showchannels (struct mansession *s, const struct message *m, int zap_mode)
static int __action_transfer (struct mansession *s, const struct message *m, int zap_mode)
static int __action_transferhangup (struct mansession *s, const struct message *m, int zap_mode)
static struct ast_frame__dahdi_exception (struct ast_channel *ast)
static int __unload_module (void)
static char * alarm2str (int alarm)
static int alloc_sub (struct dahdi_pvt *p, int x)
 AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,.load=load_module,.unload=unload_module,.reload=reload,)
 AST_MUTEX_DEFINE_STATIC (restart_lock)
 AST_MUTEX_DEFINE_STATIC (ss_thread_lock)
 AST_MUTEX_DEFINE_STATIC (monlock)
 Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
 AST_MUTEX_DEFINE_STATIC (iflock)
 Protect the interface list (of dahdi_pvt's).
static int attempt_transfer (struct dahdi_pvt *p)
static int available (struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
static int build_channels (struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
static int bump_gains (struct dahdi_pvt *p)
static struct dahdi_pvtchandup (struct dahdi_pvt *src)
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_action_dialoffhook (struct mansession *s, const struct message *m)
static int dahdi_action_dndoff (struct mansession *s, const struct message *m)
static int dahdi_action_dndon (struct mansession *s, const struct message *m)
static int dahdi_action_restart (struct mansession *s, const struct message *m)
static int dahdi_action_showchannels (struct mansession *s, const struct message *m)
static int dahdi_action_transfer (struct mansession *s, const struct message *m)
static int dahdi_action_transferhangup (struct mansession *s, const struct message *m)
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 int dahdi_destroy_channel (int fd, int argc, char **argv)
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 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, char *function, char *data, char *buf, size_t len)
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 index, struct ast_frame **dest)
static struct ast_framedahdi_handle_event (struct ast_channel *ast)
static int dahdi_hangup (struct ast_channel *ast)
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)
static int dahdi_open (char *fn)
static void dahdi_queue_frame (struct dahdi_pvt *p, struct ast_frame *f, void *pri)
static struct ast_framedahdi_read (struct ast_channel *ast)
static struct ast_channeldahdi_request (const char *type, int format, void *data, int *cause)
static int dahdi_restart (void)
static int dahdi_restart_cmd (int fd, int argc, char **argv)
static int dahdi_ring_phone (struct dahdi_pvt *p)
static int dahdi_sendtext (struct ast_channel *c, const char *text)
static int dahdi_set_hook (int fd, int hs)
static int dahdi_setlinear (int dfd, int linear)
static int dahdi_setoption (struct ast_channel *chan, int option, void *data, int datalen)
static int dahdi_show_channel (int fd, int argc, char **argv)
static int dahdi_show_channels (int fd, int argc, char **argv)
static int dahdi_show_status (int fd, int argc, char *argv[])
static char * dahdi_sig2str (int sig)
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 void destroy_all_channels (void)
static int destroy_channel (struct dahdi_pvt *prev, 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 void enable_dtmf_detect (struct dahdi_pvt *p)
static char * event2str (int event)
static void fill_rxgain (struct dahdi_gains *g, float gain, int law)
static void fill_txgain (struct dahdi_gains *g, float gain, 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 alarms)
static int handle_dahdi_show_cadences (int fd, int argc, char *argv[])
static int handle_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, struct dahdi_pri *pri, int reloading)
static int my_dahdi_write (struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
static int my_getsigstr (struct ast_channel *chan, char *str, const char *term, int ms)
static int process_dahdi (struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
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 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, int law)
static int set_actual_rxgain (int fd, int chan, float gain, int law)
static int set_actual_txgain (int fd, int chan, float gain, int law)
static int setup_dahdi (int reload)
static void * ss_thread (void *data)
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, void *pri)
static int zap_action_dialoffhook (struct mansession *s, const struct message *m)
static int zap_action_dndoff (struct mansession *s, const struct message *m)
static int zap_action_dndon (struct mansession *s, const struct message *m)
static int zap_action_restart (struct mansession *s, const struct message *m)
static int zap_action_showchannels (struct mansession *s, const struct message *m)
static int zap_action_transfer (struct mansession *s, const struct message *m)
static int zap_action_transferhangup (struct mansession *s, const struct message *m)

Variables

struct {
   int   alarm
   char *   name
alarms []
static struct dahdi_ring_cadence cadences [NUM_CADENCE_MAX]
static struct ast_channel_techchan_tech
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 struct ast_cli_entry cli_zap_destroy_channel_deprecated
static struct ast_cli_entry cli_zap_restart_deprecated
static struct ast_cli_entry cli_zap_show_cadences_deprecated
static struct ast_cli_entry cli_zap_show_channel_deprecated
static struct ast_cli_entry cli_zap_show_channels_deprecated
static struct ast_cli_entry cli_zap_show_status_deprecated
static struct ast_cli_entry dahdi_cli []
static char dahdi_restart_usage []
static char dahdi_show_cadences_usage []
static char dahdi_show_status_usage []
static struct ast_channel_tech dahdi_tech
static struct ast_jb_conf default_jbconf
static char defaultcic [64] = ""
static char defaultozz [64] = ""
static char destroy_channel_usage []
static int distinctiveringaftercid = 0
static struct dahdi_distRings drings
static char * 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
static struct dahdi_pvtiflist
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 int num_cadence = 4
static int num_restart_pending = 0
static int numbufs = 4
static char progzone [10] = ""
static int ringt_base = DEFAULT_RINGT
dahdi_pvtround_robin [32]
static char show_channel_usage []
static char show_channels_usage []
static ast_cond_t ss_thread_complete
static int ss_thread_count = 0
static char * subnames []
static const char tdesc [] = "DAHDI Telephony Driver"
static int user_has_defined_cadences = 0
static struct ast_channel_tech zap_tech


Detailed Description

DAHDI Pseudo TDM interface.

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)

Definition at line 151 of file chan_dahdi.c.

Referenced by dahdi_call(), dahdi_callwait(), dahdi_sendtext(), send_cwcidspill(), and ss_thread().

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

10,000 ms

Definition at line 283 of file chan_dahdi.c.

Referenced by dahdi_callwait().

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

300 ms

Definition at line 282 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 799 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 800 of file chan_dahdi.c.

Referenced by dahdi_handle_event(), and dahdi_new().

#define CHAN_PSEUDO   -2

Definition at line 191 of file chan_dahdi.c.

Referenced by build_channels(), dahdi_new(), dahdi_request(), enable_dtmf_detect(), and mkintf().

#define CHANNEL_PSEUDO   -12

Definition at line 149 of file chan_dahdi.c.

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

500 ms

Definition at line 284 of file chan_dahdi.c.

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 409 of file chan_dahdi.c.

#define CONF_USER_THIRDCALL   (1 << 1)

Definition at line 410 of file chan_dahdi.c.

#define DAHDI_EVENT_DTMFDOWN   0

Definition at line 121 of file chan_dahdi.c.

Referenced by dahdi_handle_event().

#define DAHDI_EVENT_DTMFUP   0

Definition at line 122 of file chan_dahdi.c.

Referenced by dahdi_handle_event().

#define DCHAN_AVAILABLE   (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)

Definition at line 197 of file chan_dahdi.c.

#define DCHAN_NOTINALARM   (1 << 1)

Definition at line 194 of file chan_dahdi.c.

#define DCHAN_PROVISIONED   (1 << 0)

Definition at line 193 of file chan_dahdi.c.

#define DCHAN_UP   (1 << 2)

Definition at line 195 of file chan_dahdi.c.

#define DEFAULT_CIDRINGS   1

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

Definition at line 147 of file chan_dahdi.c.

Referenced by dahdi_chan_conf_default().

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

8,000 ms

Definition at line 286 of file chan_dahdi.c.

#define END_SILENCE_LEN   400

Referenced by dahdi_sendtext().

#define FORMAT   "%-40.40s %-10.10s %-10d %-10d %-10d\n"

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

#define FORMAT2   "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"

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

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

Definition at line 751 of file chan_dahdi.c.

#define HANGUP   1

Definition at line 10584 of file chan_dahdi.c.

Referenced by __action_transferhangup(), and dahdi_fake_event().

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

Referenced by build_alerting(), build_connect(), build_connect_acknowledge(), build_disconnect(), build_facility(), build_hold(), build_hold_acknowledge(), build_hold_reject(), build_information(), build_notify(), build_proceeding(), build_progress(), build_release(), build_release_complete(), build_restart(), build_resume(), build_resume_acknowledge(), build_resume_reject(), build_retrieve(), build_retrieve_acknowledge(), build_retrieve_reject(), build_setup(), build_setup_acknowledge(), build_status(), build_status_enquiry(), build_suspend(), build_suspend_acknowledge(), build_suspend_reject(), build_timeout(), build_user_information(), dahdi_sendtext(), parse_alerting(), parse_connect(), parse_disconnect(), parse_facility(), parse_information(), parse_proceeding(), parse_progress(), parse_release(), parse_release_complete(), parse_restart(), parse_setup(), parse_setup_acknowledge(), and parse_status().

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

Referenced by dahdi_indicate(), dahdi_show_channel(), and ss_thread().

#define local_astman_ack ( s,
m,
msg,
zap   )     do { if (!zap) astman_send_ack(s, m, "DAHDI" msg); else astman_send_ack(s, m, "Zap" msg); } while (0)

Definition at line 10614 of file chan_dahdi.c.

Referenced by __action_dialoffhook(), __action_dnd(), __action_restart(), __action_showchannels(), __action_transfer(), and __action_transferhangup().

#define local_astman_header ( m,
hdr,
zap   )     astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)

Definition at line 10615 of file chan_dahdi.c.

Referenced by __action_dialoffhook(), __action_dnd(), __action_transfer(), and __action_transferhangup().

#define local_astman_register ( a,
b,
c,
 ) 

Definition at line 11857 of file chan_dahdi.c.

Referenced by load_module().

#define local_astman_unregister (  ) 

Definition at line 10835 of file chan_dahdi.c.

Referenced by __unload_module().

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 279 of file chan_dahdi.c.

#define MASK_INUSE   (1 << 1)

Channel currently in use

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

Referenced by process_dahdi().

#define MAX_CHANNELS   672

No more than a DS3 per trunk group

Definition at line 189 of file chan_dahdi.c.

Referenced by mkintf().

#define MAX_SLAVES   4

Definition at line 412 of file chan_dahdi.c.

Referenced by isslavenative().

#define MIN_MS_SINCE_FLASH   ( (2000) )

2000 ms

Definition at line 285 of file chan_dahdi.c.

Referenced by 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 154 of file chan_dahdi.c.

Referenced by dahdi_new(), and ss_thread().

#define NUM_CADENCE_MAX   25

Definition at line 774 of file chan_dahdi.c.

#define NUM_DCHANS   4

No more than 4 d-channels

Definition at line 188 of file chan_dahdi.c.

#define NUM_SPANS   32

Definition at line 187 of file chan_dahdi.c.

#define POLARITY_IDLE   0

Definition at line 367 of file chan_dahdi.c.

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

#define POLARITY_REV   1

Definition at line 368 of file chan_dahdi.c.

Referenced by dahdi_handle_event(), and handle_init_event().

#define READ_SIZE   160

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

Definition at line 277 of file chan_dahdi.c.

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

#define sig2str   dahdi_sig2str

Definition at line 1278 of file chan_dahdi.c.

Referenced by __action_showchannels(), build_channels(), dahdi_handle_event(), dahdi_show_channel(), handle_init_event(), and mkintf().

#define SIG_E911   (0x1000000 | DAHDI_SIG_EM)

Definition at line 167 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_EM   DAHDI_SIG_EM

Definition at line 162 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_EM_E1   DAHDI_SIG_EM_E1

Definition at line 183 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)

Definition at line 163 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)

Definition at line 166 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_FEATD   (0x0200000 | DAHDI_SIG_EM)

Definition at line 164 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_FEATDMF   (0x0400000 | DAHDI_SIG_EM)

Definition at line 165 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_FEATDMF_TA   (0x2000000 | DAHDI_SIG_EM)

Definition at line 168 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)

Definition at line 169 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_FGC_CAMAMF   (0x8000000 | DAHDI_SIG_EM)

Definition at line 170 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_FXOGS   DAHDI_SIG_FXOGS

Definition at line 175 of file chan_dahdi.c.

Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_FXOKS   DAHDI_SIG_FXOKS

Definition at line 176 of file chan_dahdi.c.

Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().

#define SIG_FXOLS   DAHDI_SIG_FXOLS

Definition at line 174 of file chan_dahdi.c.

Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_FXSGS   DAHDI_SIG_FXSGS

Definition at line 172 of file chan_dahdi.c.

Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_FXSKS   DAHDI_SIG_FXSKS

Definition at line 173 of file chan_dahdi.c.

Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_request(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().

#define SIG_FXSLS   DAHDI_SIG_FXSLS

Definition at line 171 of file chan_dahdi.c.

Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_GR303FXOKS   (0x0100000 | DAHDI_SIG_FXOKS)

Definition at line 184 of file chan_dahdi.c.

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

#define SIG_GR303FXSKS   (0x0100000 | DAHDI_SIG_FXSKS)

Definition at line 185 of file chan_dahdi.c.

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

#define SIG_PRI   DAHDI_SIG_CLEAR

Definition at line 177 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_read(), dahdi_sig2str(), dahdi_write(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().

#define SIG_SF   DAHDI_SIG_SF

Definition at line 178 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)

Definition at line 182 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_SF_FEATD   (0x0200000 | DAHDI_SIG_SF)

Definition at line 180 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), and ss_thread().

#define SIG_SF_FEATDMF   (0x0400000 | DAHDI_SIG_SF)

Definition at line 181 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), and ss_thread().

#define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)

Definition at line 179 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SMDI_MD_WAIT_TIMEOUT   1500

Definition at line 104 of file chan_dahdi.c.

Referenced by ss_thread().

#define SUB_CALLWAIT   1

Call-Waiting call on hold

Definition at line 363 of file chan_dahdi.c.

Referenced by available(), dahdi_bridge(), dahdi_call(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_read(), dahdi_request(), dahdi_show_channel(), features_hangup(), and ss_thread().

#define SUB_REAL   0

Active call

Definition at line 362 of file chan_dahdi.c.

Referenced by __dahdi_exception(), attempt_transfer(), available(), bump_gains(), chandup(), check_for_conference(), 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_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_read(), dahdi_request(), dahdi_ring_phone(), dahdi_setoption(), dahdi_train_ec(), dahdi_unlink(), destroy_dahdi_pvt(), disable_dtmf_detect(), do_monitor(), enable_dtmf_detect(), features_hangup(), features_request(), get_alarms(), handle_init_event(), mkintf(), reset_conf(), restore_conference(), restore_gains(), save_conference(), send_callerid(), and ss_thread().

#define SUB_THREEWAY   2

Three-way call

Definition at line 364 of file chan_dahdi.c.

Referenced by attempt_transfer(), available(), dahdi_answer(), dahdi_bridge(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_show_channel(), features_hangup(), and ss_thread().

#define tdesc   "DAHDI Telephony"

Definition at line 12041 of file chan_dahdi.c.

#define TRAILER_MS   5

Referenced by dahdi_sendtext().

#define TRANSFER   0

Definition at line 10583 of file chan_dahdi.c.

Referenced by __action_transfer(), and dahdi_fake_event().


Function Documentation

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

Definition at line 10713 of file chan_dahdi.c.

References AST_FRAME_DTMF, ast_strlen_zero(), astman_get_header(), astman_send_error(), dahdi_queue_frame(), f, find_channel(), local_astman_ack, local_astman_header, dahdi_pvt::owner, and s.

Referenced by dahdi_action_dialoffhook(), and zap_action_dialoffhook().

10714 {
10715    struct dahdi_pvt *p = NULL;
10716    const char *channel = local_astman_header(m, "Channel", zap_mode);
10717    const char *number = astman_get_header(m, "Number");
10718    int i;
10719 
10720    if (ast_strlen_zero(channel)) {
10721       astman_send_error(s, m, "No channel specified");
10722       return 0;
10723    }
10724    if (ast_strlen_zero(number)) {
10725       astman_send_error(s, m, "No number specified");
10726       return 0;
10727    }
10728    if (!(p = find_channel(atoi(channel)))) {
10729       astman_send_error(s, m, "No such channel");
10730       return 0;
10731    }
10732    if (!p->owner) {
10733       astman_send_error(s, m, "Channel does not have an owner");
10734       return 0;
10735    }
10736    for (i = 0; i < strlen(number); i++) {
10737       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
10738 
10739       dahdi_queue_frame(p, &f, NULL); 
10740    }
10741    local_astman_ack(s, m, "DialOffHook", zap_mode);
10742 
10743    return 0;
10744 }

static int __action_dnd ( struct mansession s,
const struct message m,
int  zap_mode,
int  dnd 
) [static]

Definition at line 10617 of file chan_dahdi.c.

References ast_strlen_zero(), astman_send_error(), dahdi_pvt::dnd, find_channel(), local_astman_ack, local_astman_header, and s.

Referenced by dahdi_action_dndoff(), dahdi_action_dndon(), zap_action_dndoff(), and zap_action_dndon().

10618 {
10619    struct dahdi_pvt *p = NULL;
10620    const char *channel = local_astman_header(m, "Channel", zap_mode);
10621 
10622    if (ast_strlen_zero(channel)) {
10623       astman_send_error(s, m, "No channel specified");
10624       return 0;
10625    }
10626    if (!(p = find_channel(atoi(channel)))) {
10627       astman_send_error(s, m, "No such channel");
10628       return 0;
10629    }
10630    p->dnd = dnd;
10631    local_astman_ack(s, m, "DND", zap_mode);
10632 
10633    return 0;
10634 }

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

Definition at line 10811 of file chan_dahdi.c.

References astman_send_error(), dahdi_restart(), local_astman_ack, and s.

Referenced by dahdi_action_restart(), and zap_action_restart().

10812 {
10813    if (dahdi_restart() != 0) {
10814       if (zap_mode) {
10815          astman_send_error(s, m, "Failed to restart Zap");
10816       } else {
10817          astman_send_error(s, m, "Failed to restart DAHDI");
10818       }
10819       return 1;
10820    }
10821    local_astman_ack(s, m, "Restart: Success", zap_mode);
10822    return 0;
10823 }

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

Definition at line 10756 of file chan_dahdi.c.

References alarm, alarm2str(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), astman_append(), astman_get_header(), dahdi_pvt::channel, dahdi_pvt::context, dahdi_chan_name, dahdi_pvt::dnd, get_alarms(), iflist, local_astman_ack, dahdi_pvt::next, s, dahdi_pvt::sig, and sig2str.

Referenced by dahdi_action_showchannels(), and zap_action_showchannels().

10757 {
10758    struct dahdi_pvt *tmp = NULL;
10759    const char *id = astman_get_header(m, "ActionID");
10760    char idText[256] = "";
10761 
10762    local_astman_ack(s, m, " channel status will follow", zap_mode);
10763    if (!ast_strlen_zero(id))
10764       snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
10765 
10766    ast_mutex_lock(&iflock);
10767    
10768    tmp = iflist;
10769    while (tmp) {
10770       if (tmp->channel > 0) {
10771          int alarm = get_alarms(tmp);
10772          astman_append(s,
10773                   "Event: %sShowChannels\r\n"
10774                   "Channel: %d\r\n"
10775                   "Signalling: %s\r\n"
10776                   "Context: %s\r\n"
10777                   "DND: %s\r\n"
10778                   "Alarm: %s\r\n"
10779                   "%s"
10780                   "\r\n",
10781                   dahdi_chan_name,
10782                   tmp->channel, sig2str(tmp->sig), tmp->context, 
10783                   tmp->dnd ? "Enabled" : "Disabled",
10784                   alarm2str(alarm), idText);
10785       } 
10786 
10787       tmp = tmp->next;
10788    }
10789 
10790    ast_mutex_unlock(&iflock);
10791    
10792    astman_append(s, 
10793             "Event: %sShowChannelsComplete\r\n"
10794             "%s"
10795             "\r\n",
10796             dahdi_chan_name,
10797             idText);
10798    return 0;
10799 }

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

Definition at line 10656 of file chan_dahdi.c.

References ast_strlen_zero(), astman_send_error(), dahdi_fake_event(), find_channel(), local_astman_ack, local_astman_header, s, and TRANSFER.

Referenced by dahdi_action_transfer(), and zap_action_transfer().

10657 {
10658    struct dahdi_pvt *p = NULL;
10659    const char *channel = local_astman_header(m, "Channel", zap_mode);
10660 
10661    if (ast_strlen_zero(channel)) {
10662       astman_send_error(s, m, "No channel specified");
10663       return 0;
10664    }
10665    if (!(p = find_channel(atoi(channel)))) {
10666       astman_send_error(s, m, "No such channel");
10667       return 0;
10668    }
10669    dahdi_fake_event(p,TRANSFER);
10670    local_astman_ack(s, m, "Transfer", zap_mode);
10671 
10672    return 0;
10673 }

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

Definition at line 10685 of file chan_dahdi.c.

References ast_strlen_zero(), astman_send_error(), dahdi_fake_event(), find_channel(), HANGUP, local_astman_ack, local_astman_header, and s.

Referenced by dahdi_action_transferhangup(), and zap_action_transferhangup().

10686 {
10687    struct dahdi_pvt *p = NULL;
10688    const char *channel = local_astman_header(m, "Channel", zap_mode);
10689 
10690    if (ast_strlen_zero(channel)) {
10691       astman_send_error(s, m, "No channel specified");
10692       return 0;
10693    }
10694    if (!(p = find_channel(atoi(channel)))) {
10695       astman_send_error(s, m, "No such channel");
10696       return 0;
10697    }
10698    dahdi_fake_event(p, HANGUP);
10699    local_astman_ack(s, m, "Hangup", zap_mode);
10700    return 0;
10701 }

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

Definition at line 4639 of file chan_dahdi.c.

References ast_bridged_channel(), AST_CONTROL_UNHOLD, AST_FRAME_NULL, ast_log(), ast_queue_control(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_verbose(), dahdi_pvt::channel, 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, event2str(), dahdi_subchannel::f, f, dahdi_pvt::fake_event, ast_channel::fds, ast_frame::frametype, LOG_DEBUG, ast_frame::mallocd, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, option_debug, option_verbose, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::radio, ast_frame::samples, ast_frame::src, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, update_conf(), and VERBOSE_PREFIX_3.

Referenced by dahdi_exception(), and dahdi_read().

04640 {
04641    struct dahdi_pvt *p = ast->tech_pvt;
04642    int res;
04643    int usedindex=-1;
04644    int index;
04645    struct ast_frame *f;
04646 
04647 
04648    index = dahdi_get_index(ast, p, 1);
04649    
04650    p->subs[index].f.frametype = AST_FRAME_NULL;
04651    p->subs[index].f.datalen = 0;
04652    p->subs[index].f.samples = 0;
04653    p->subs[index].f.mallocd = 0;
04654    p->subs[index].f.offset = 0;
04655    p->subs[index].f.subclass = 0;
04656    p->subs[index].f.delivery = ast_tv(0,0);
04657    p->subs[index].f.src = "dahdi_exception";
04658    p->subs[index].f.data = NULL;
04659    
04660    
04661    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
04662       /* If nobody owns us, absorb the event appropriately, otherwise
04663          we loop indefinitely.  This occurs when, during call waiting, the
04664          other end hangs up our channel so that it no longer exists, but we
04665          have neither FLASH'd nor ONHOOK'd to signify our desire to
04666          change to the other channel. */
04667       if (p->fake_event) {
04668          res = p->fake_event;
04669          p->fake_event = 0;
04670       } else
04671          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
04672       /* Switch to real if there is one and this isn't something really silly... */
04673       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
04674          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
04675          ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
04676          p->owner = p->subs[SUB_REAL].owner;
04677          if (p->owner && ast_bridged_channel(p->owner))
04678             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04679          p->subs[SUB_REAL].needunhold = 1;
04680       }
04681       switch (res) {
04682       case DAHDI_EVENT_ONHOOK:
04683          dahdi_disable_ec(p);
04684          if (p->owner) {
04685             if (option_verbose > 2) 
04686                ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
04687             dahdi_ring_phone(p);
04688             p->callwaitingrepeat = 0;
04689             p->cidcwexpire = 0;
04690          } else
04691             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
04692          update_conf(p);
04693          break;
04694       case DAHDI_EVENT_RINGOFFHOOK:
04695          dahdi_enable_ec(p);
04696          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
04697          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
04698             p->subs[SUB_REAL].needanswer = 1;
04699             p->dialing = 0;
04700          }
04701          break;
04702       case DAHDI_EVENT_HOOKCOMPLETE:
04703       case DAHDI_EVENT_RINGERON:
04704       case DAHDI_EVENT_RINGEROFF:
04705          /* Do nothing */
04706          break;
04707       case DAHDI_EVENT_WINKFLASH:
04708          gettimeofday(&p->flashtime, NULL);
04709          if (p->owner) {
04710             if (option_verbose > 2) 
04711                ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
04712             if (p->owner->_state != AST_STATE_UP) {
04713                /* Answer if necessary */
04714                usedindex = dahdi_get_index(p->owner, p, 0);
04715                if (usedindex > -1) {
04716                   p->subs[usedindex].needanswer = 1;
04717                }
04718                ast_setstate(p->owner, AST_STATE_UP);
04719             }
04720             p->callwaitingrepeat = 0;
04721             p->cidcwexpire = 0;
04722             if (ast_bridged_channel(p->owner))
04723                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04724             p->subs[SUB_REAL].needunhold = 1;
04725          } else
04726             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
04727          update_conf(p);
04728          break;
04729       default:
04730          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
04731       }
04732       f = &p->subs[index].f;
04733       return f;
04734    }
04735    if (!(p->radio || (p->oprmode < 0)) && option_debug) 
04736       ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
04737    /* If it's not us, return NULL immediately */
04738    if (ast != p->owner) {
04739       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
04740       f = &p->subs[index].f;
04741       return f;
04742    }
04743    f = dahdi_handle_event(ast);
04744    return f;
04745 }

static int __unload_module ( void   )  [static]

Definition at line 10842 of file chan_dahdi.c.

References ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_destroy(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_unregister_application(), CHAN_DAHDI_PLUS_ZAP_MODE, chan_tech, dahdi_chan_mode, dahdi_cli, destroy_all_channels(), iflist, local_astman_unregister, master, dahdi_pvt::next, and dahdi_pvt::owner.

Referenced by load_module(), and unload_module().

10843 {
10844    struct dahdi_pvt *p;
10845 
10846 #ifdef HAVE_PRI
10847    int i, j;
10848    for (i = 0; i < NUM_SPANS; i++) {
10849       if (pris[i].master != AST_PTHREADT_NULL) 
10850          pthread_cancel(pris[i].master);
10851    }
10852    ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
10853 
10854    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
10855       ast_unregister_application(dahdi_send_keypad_facility_app);
10856    }
10857    ast_unregister_application(zap_send_keypad_facility_app);
10858 #endif
10859    ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
10860    local_astman_unregister("DialOffHook");
10861    local_astman_unregister("Hangup");
10862    local_astman_unregister("Transfer");
10863    local_astman_unregister("DNDoff");
10864    local_astman_unregister("DNDon");
10865    local_astman_unregister("ShowChannels");
10866    local_astman_unregister("Restart");
10867    ast_channel_unregister(chan_tech);
10868    ast_mutex_lock(&iflock);
10869    /* Hangup all interfaces if they have an owner */
10870    p = iflist;
10871    while (p) {
10872       if (p->owner)
10873          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
10874       p = p->next;
10875    }
10876    ast_mutex_unlock(&iflock);
10877    ast_mutex_lock(&monlock);
10878    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10879       pthread_cancel(monitor_thread);
10880       pthread_kill(monitor_thread, SIGURG);
10881       pthread_join(monitor_thread, NULL);
10882    }
10883    monitor_thread = AST_PTHREADT_STOP;
10884    ast_mutex_unlock(&monlock);
10885 
10886    destroy_all_channels();
10887 #ifdef HAVE_PRI      
10888    for (i = 0; i < NUM_SPANS; i++) {
10889       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
10890          pthread_join(pris[i].master, NULL);
10891       for (j = 0; j < NUM_DCHANS; j++) {
10892          dahdi_close_pri_fd(&(pris[i]), j);
10893       }
10894    }
10895 #endif
10896    ast_cond_destroy(&ss_thread_complete);
10897    return 0;
10898 }

static char* alarm2str ( int  alarm  )  [static]

Definition at line 1189 of file chan_dahdi.c.

References alarms, and name.

Referenced by __action_showchannels(), and handle_alarms().

01190 {
01191    int x;
01192    for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
01193       if (alarms[x].alarm & alarm)
01194          return alarms[x].name;
01195    }
01196    return alarm ? "Unknown Alarm" : "No Alarm";
01197 }

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

Definition at line 987 of file chan_dahdi.c.

References 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_DEBUG, LOG_WARNING, option_debug, and dahdi_pvt::subs.

Referenced by dahdi_handle_event(), dahdi_request(), and ss_thread().

00988 {
00989    struct dahdi_bufferinfo bi;
00990    int res;
00991    if (p->subs[x].dfd < 0) {
00992 #ifdef HAVE_ZAPTEL
00993       p->subs[x].dfd = dahdi_open("/dev/zap/pseudo");
00994 #else
00995       p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
00996 #endif
00997       if (p->subs[x].dfd > -1) {
00998          res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
00999          if (!res) {
01000             bi.txbufpolicy = p->buf_policy;
01001             bi.rxbufpolicy = p->buf_policy;
01002             bi.numbufs = p->buf_no;
01003             res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01004             if (res < 0) {
01005                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01006             }
01007          } else 
01008             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01009          if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01010             ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01011             dahdi_close_sub(p, x);
01012             return -1;
01013          }
01014          if (option_debug)
01015             ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01016          return 0;
01017       } else
01018          ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01019       return -1;
01020    }
01021    ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01022    return -1;
01023 }

AST_MODULE_INFO ( ASTERISK_GPL_KEY  ,
AST_MODFLAG_DEFAULT  ,
tdesc  ,
load = load_module,
unload = unload_module,
reload = reload 
)

AST_MUTEX_DEFINE_STATIC ( restart_lock   ) 

AST_MUTEX_DEFINE_STATIC ( ss_thread_lock   ) 

AST_MUTEX_DEFINE_STATIC ( monlock   ) 

Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.

AST_MUTEX_DEFINE_STATIC ( iflock   ) 

Protect the interface list (of dahdi_pvt's).

static int attempt_transfer ( struct dahdi_pvt p  )  [static]

Definition at line 3601 of file chan_dahdi.c.

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

Referenced by dahdi_handle_event(), handle_onhook_message(), handle_request(), handle_soft_key_event_message(), and local_attended_transfer().

03602 {
03603    /* In order to transfer, we need at least one of the channels to
03604       actually be in a call bridge.  We can't conference two applications
03605       together (but then, why would we want to?) */
03606    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
03607       /* The three-way person we're about to transfer to could still be in MOH, so
03608          stop if now if appropriate */
03609       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
03610          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
03611       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
03612          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
03613       }
03614       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
03615          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
03616       }
03617        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
03618          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03619                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
03620          return -1;
03621       }
03622       /* Orphan the channel after releasing the lock */
03623       ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
03624       unalloc_sub(p, SUB_THREEWAY);
03625    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03626       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03627       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
03628          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
03629       }
03630       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
03631          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
03632       }
03633       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
03634          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03635                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
03636          return -1;
03637       }
03638       /* Three-way is now the REAL */
03639       swap_subs(p, SUB_THREEWAY, SUB_REAL);
03640       ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
03641       unalloc_sub(p, SUB_THREEWAY);
03642       /* Tell the caller not to hangup */
03643       return 1;
03644    } else {
03645       ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
03646                p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
03647       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
03648       return -1;
03649    }
03650    return 0;
03651 }

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

Definition at line 7792 of file chan_dahdi.c.

References ast_channel::_state, ast_log(), AST_STATE_RINGING, AST_STATE_UP, dahdi_pvt::callwaiting, dahdi_pvt::channel, dahdi_pvt::dnd, errno, dahdi_pvt::group, dahdi_pvt::guardtime, LOG_DEBUG, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::radio, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, and dahdi_pvt::subs.

Referenced by dahdi_request().

07793 {
07794    int res;
07795    struct dahdi_params par;
07796 
07797    /* First, check group matching */
07798    if (groupmatch) {
07799       if ((p->group & groupmatch) != groupmatch)
07800          return 0;
07801       *groupmatched = 1;
07802    }
07803    /* Check to see if we have a channel match */
07804    if (channelmatch != -1) {
07805       if (p->channel != channelmatch)
07806          return 0;
07807       *channelmatched = 1;
07808    }
07809    /* We're at least busy at this point */
07810    if (busy) {
07811       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
07812          *busy = 1;
07813    }
07814    /* If do not disturb, definitely not */
07815    if (p->dnd)
07816       return 0;
07817    /* If guard time, definitely not */
07818    if (p->guardtime && (time(NULL) < p->guardtime)) 
07819       return 0;
07820       
07821    /* If no owner definitely available */
07822    if (!p->owner) {
07823 #ifdef HAVE_PRI
07824       /* Trust PRI */
07825       if (p->pri) {
07826          if (p->resetting || p->call)
07827             return 0;
07828          else
07829             return 1;
07830       }
07831 #endif
07832       if (!(p->radio || (p->oprmode < 0)))
07833       {
07834          if (!p->sig || (p->sig == SIG_FXSLS))
07835             return 1;
07836          /* Check hook state */
07837          if (p->subs[SUB_REAL].dfd > -1)
07838             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
07839          else {
07840             /* Assume not off hook on CVRS */
07841             res = 0;
07842             par.rxisoffhook = 0;
07843          }
07844          if (res) {
07845             ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
07846          } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
07847             /* When "onhook" that means no battery on the line, and thus
07848               it is out of service..., if it's on a TDM card... If it's a channel
07849               bank, there is no telling... */
07850             if (par.rxbits > -1)
07851                return 1;
07852             if (par.rxisoffhook)
07853                return 1;
07854             else
07855 #ifdef DAHDI_CHECK_HOOKSTATE
07856                return 0;
07857 #else
07858                return 1;
07859 #endif
07860          } else if (par.rxisoffhook) {
07861             ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
07862             /* Not available when the other end is off hook */
07863             return 0;
07864          }
07865       }
07866       return 1;
07867    }
07868 
07869    /* If it's not an FXO, forget about call wait */
07870    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 
07871       return 0;
07872 
07873    if (!p->callwaiting) {
07874       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
07875       return 0;
07876    }
07877 
07878    if (p->subs[SUB_CALLWAIT].dfd > -1) {
07879       /* If there is already a call waiting call, then we can't take a second one */
07880       return 0;
07881    }
07882    
07883    if ((p->owner->_state != AST_STATE_UP) &&
07884        ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
07885       /* If the current call is not up, then don't allow the call */
07886       return 0;
07887    }
07888    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
07889       /* Can't take a call wait when the three way calling hasn't been merged yet. */
07890       return 0;
07891    }
07892    /* We're cool */
07893    return 1;
07894 }

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

Definition at line 10910 of file chan_dahdi.c.

References ast_log(), ast_strdupa, ast_verbose(), dahdi_chan_conf::chan, CHAN_PSEUDO, HAVE_PRI, LOG_ERROR, mkintf(), option_verbose, dahdi_pvt::sig, sig2str, strsep(), and VERBOSE_PREFIX_3.

Referenced by process_dahdi().

10911 {
10912    char *c, *chan;
10913    int x, start, finish;
10914    struct dahdi_pvt *tmp;
10915 #ifdef HAVE_PRI
10916    struct dahdi_pri *pri;
10917    int trunkgroup, y;
10918 #endif
10919    
10920    if ((reload == 0) && (conf->chan.sig < 0)) {
10921       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
10922       return -1;
10923    }
10924 
10925    c = ast_strdupa(value);
10926 
10927 #ifdef HAVE_PRI
10928    pri = NULL;
10929    if (iscrv) {
10930       if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
10931          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
10932          return -1;
10933       }
10934       if (trunkgroup < 1) {
10935          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
10936          return -1;
10937       }
10938       c += y;
10939       for (y = 0; y < NUM_SPANS; y++) {
10940          if (pris[y].trunkgroup == trunkgroup) {
10941             pri = pris + y;
10942             break;
10943          }
10944       }
10945       if (!pri) {
10946          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
10947          return -1;
10948       }
10949    }
10950 #endif         
10951 
10952    while ((chan = strsep(&c, ","))) {
10953       if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
10954          /* Range */
10955       } else if (sscanf(chan, "%d", &start)) {
10956          /* Just one */
10957          finish = start;
10958       } else if (!strcasecmp(chan, "pseudo")) {
10959          finish = start = CHAN_PSEUDO;
10960          if (found_pseudo)
10961             *found_pseudo = 1;
10962       } else {
10963          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
10964          return -1;
10965       }
10966       if (finish < start) {
10967          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
10968          x = finish;
10969          finish = start;
10970          start = x;
10971       }
10972 
10973       for (x = start; x <= finish; x++) {
10974 #ifdef HAVE_PRI
10975          tmp = mkintf(x, conf, pri, reload);
10976 #else       
10977          tmp = mkintf(x, conf, NULL, reload);
10978 #endif         
10979 
10980          if (tmp) {
10981             if (option_verbose > 2) {
10982 #ifdef HAVE_PRI
10983                if (pri)
10984                   ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
10985                else
10986 #endif
10987                   ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
10988             }
10989          } else {
10990             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
10991                (reload == 1) ? "reconfigure" : "register", value);
10992             return -1;
10993          }
10994       }
10995    }
10996 
10997    return 0;
10998 }

static int bump_gains ( struct dahdi_pvt p  )  [static]

Definition at line 1640 of file chan_dahdi.c.

References ast_log(), errno, dahdi_pvt::law, LOG_WARNING, dahdi_pvt::rxgain, set_actual_gain(), SUB_REAL, dahdi_pvt::subs, and dahdi_pvt::txgain.

Referenced by ss_thread().

01641 {
01642    int res;
01643 
01644    /* Bump receive gain by 5.0db */
01645    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
01646    if (res) {
01647       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
01648       return -1;
01649    }
01650 
01651    return 0;
01652 }

static struct dahdi_pvt* chandup ( struct dahdi_pvt src  )  [static]

Definition at line 7896 of file chan_dahdi.c.

References ast_log(), ast_malloc, ast_mutex_init(), dahdi_open(), destroy_dahdi_pvt(), errno, iflist, LOG_ERROR, dahdi_pvt::next, dahdi_pvt::prev, and SUB_REAL.

Referenced by dahdi_request().

07897 {
07898    struct dahdi_pvt *p;
07899    struct dahdi_bufferinfo bi;
07900    int res;
07901    
07902    if ((p = ast_malloc(sizeof(*p)))) {
07903       memcpy(p, src, sizeof(struct dahdi_pvt));
07904       ast_mutex_init(&p->lock);
07905 #ifdef HAVE_ZAPTEL
07906       p->subs[SUB_REAL].dfd = dahdi_open("/dev/zap/pseudo");
07907 #else
07908       p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
07909 #endif
07910       /* Allocate a DAHDI structure */
07911       if (p->subs[SUB_REAL].dfd < 0) {
07912          ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
07913          destroy_dahdi_pvt(&p);
07914          return NULL;
07915       }
07916       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
07917       if (!res) {
07918          bi.txbufpolicy = p->buf_policy;
07919          bi.rxbufpolicy = p->buf_policy;
07920          bi.numbufs = p->buf_no;
07921          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
07922          if (res < 0) {
07923             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
07924          }
07925       } else
07926          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
07927    }
07928    p->destroy = 1;
07929    p->next = iflist;
07930    p->prev = NULL;
07931    iflist = p;
07932    if (iflist->next)
07933       iflist->next->prev = p;
07934    return p;
07935 }

static int check_for_conference ( struct dahdi_pvt p  )  [static]

Definition at line 3653 of file chan_dahdi.c.

References ast_log(), ast_verbose(), dahdi_pvt::channel, dahdi_pvt::confno, errno, dahdi_pvt::master, option_verbose, SUB_REAL, dahdi_pvt::subs, and VERBOSE_PREFIX_3.

Referenced by dahdi_handle_event().

03654 {
03655    struct dahdi_confinfo ci;
03656    /* Fine if we already have a master, etc */
03657    if (p->master || (p->confno > -1))
03658       return 0;
03659    memset(&ci, 0, sizeof(ci));
03660    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
03661       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
03662       return 0;
03663    }
03664    /* If we have no master and don't have a confno, then 
03665       if we're in a conference, it's probably a MeetMe room or
03666       some such, so don't let us 3-way out! */
03667    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
03668       if (option_verbose > 2) 
03669          ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
03670       return 1;
03671    }
03672    return 0;
03673 }

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

Definition at line 1280 of file chan_dahdi.c.

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

Referenced by update_conf().

01281 {
01282    /* If the conference already exists, and we're already in it
01283       don't bother doing anything */
01284    struct dahdi_confinfo zi;
01285    
01286    memset(&zi, 0, sizeof(zi));
01287    zi.chan = 0;
01288 
01289    if (slavechannel > 0) {
01290       /* If we have only one slave, do a digital mon */
01291       zi.confmode = DAHDI_CONF_DIGITALMON;
01292       zi.confno = slavechannel;
01293    } else {
01294       if (!index) {
01295          /* Real-side and pseudo-side both participate in conference */
01296          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
01297             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
01298       } else
01299          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
01300       zi.confno = p->confno;
01301    }
01302    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
01303       return 0;
01304    if (c->dfd < 0)
01305       return 0;
01306    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01307       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
01308       return -1;
01309    }
01310    if (slavechannel < 1) {
01311       p->confno = zi.confno;
01312    }
01313    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01314    ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01315    return 0;
01316 }

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

Definition at line 1329 of file chan_dahdi.c.

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

Referenced by dahdi_unlink(), and update_conf().

01330 {
01331    struct dahdi_confinfo zi;
01332    if (/* Can't delete if there's no dfd */
01333       (c->dfd < 0) ||
01334       /* Don't delete from the conference if it's not our conference */
01335       !isourconf(p, c)
01336       /* Don't delete if we don't think it's conferenced at all (implied) */
01337       ) return 0;
01338    memset(&zi, 0, sizeof(zi));
01339    zi.chan = 0;
01340    zi.confno = 0;
01341    zi.confmode = 0;
01342    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01343       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
01344       return -1;
01345    }
01346    ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01347    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01348    return 0;
01349 }

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

Definition at line 10751 of file chan_dahdi.c.

References __action_dialoffhook(), and s.

10752 {
10753    return __action_dialoffhook(s, m, 0);
10754 }

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

Definition at line 10651 of file chan_dahdi.c.

References __action_dnd(), and s.

10652 {
10653    return __action_dnd(s, m, 0, 0);
10654 }

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

Definition at line 10641 of file chan_dahdi.c.

References __action_dnd(), and s.

10642 {
10643    return __action_dnd(s, m, 0, 1);
10644 }

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

Definition at line 10830 of file chan_dahdi.c.

References __action_restart(), and s.

10831 {
10832    return __action_restart(s, m, 0);
10833 }

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

Definition at line 10806 of file chan_dahdi.c.

References __action_showchannels(), and s.

10807 {
10808    return __action_showchannels(s, m, 0);
10809 }

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

Definition at line 10680 of file chan_dahdi.c.

References __action_transfer(), and s.

10681 {
10682    return __action_transfer(s, m, 0);
10683 }

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

Definition at line 10708 of file chan_dahdi.c.

References __action_transferhangup(), and s.

10709 {
10710    return __action_transferhangup(s, m, 0);
10711 }

static int dahdi_answer ( struct ast_channel ast  )  [static]

Definition at line 2847 of file chan_dahdi.c.

References ast_channel::_state, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, dahdi_pvt::channel, dahdi_enable_ec(), dahdi_get_index(), dahdi_set_hook(), dahdi_train_ec(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::digital, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::polaritydelaytv, dahdi_pvt::radio, dahdi_pvt::ringt, dahdi_pvt::sig, 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_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::span, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and ast_channel::tech_pvt.

02848 {
02849    struct dahdi_pvt *p = ast->tech_pvt;
02850    int res = 0;
02851    int index;
02852    int oldstate = ast->_state;
02853    ast_setstate(ast, AST_STATE_UP);
02854    ast_mutex_lock(&p->lock);
02855    index = dahdi_get_index(ast, p, 0);
02856    if (index < 0)
02857       index = SUB_REAL;
02858    /* nothing to do if a radio channel */
02859    if ((p->radio || (p->oprmode < 0))) {
02860       ast_mutex_unlock(&p->lock);
02861       return 0;
02862    }
02863    switch (p->sig) {
02864    case SIG_FXSLS:
02865    case SIG_FXSGS:
02866    case SIG_FXSKS:
02867       p->ringt = 0;
02868       /* Fall through */
02869    case SIG_EM:
02870    case SIG_EM_E1:
02871    case SIG_EMWINK:
02872    case SIG_FEATD:
02873    case SIG_FEATDMF:
02874    case SIG_FEATDMF_TA:
02875    case SIG_E911:
02876    case SIG_FGC_CAMA:
02877    case SIG_FGC_CAMAMF:
02878    case SIG_FEATB:
02879    case SIG_SF:
02880    case SIG_SFWINK:
02881    case SIG_SF_FEATD:
02882    case SIG_SF_FEATDMF:
02883    case SIG_SF_FEATB:
02884    case SIG_FXOLS:
02885    case SIG_FXOGS:
02886    case SIG_FXOKS:
02887       /* Pick up the line */
02888       ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
02889       if (p->hanguponpolarityswitch) {
02890          gettimeofday(&p->polaritydelaytv, NULL);
02891       }
02892       res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02893       tone_zone_play_tone(p->subs[index].dfd, -1);
02894       p->dialing = 0;
02895       if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
02896          if (oldstate == AST_STATE_RINGING) {
02897             ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
02898             tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
02899             swap_subs(p, SUB_THREEWAY, SUB_REAL);
02900             p->owner = p->subs[SUB_REAL].owner;
02901          }
02902       }
02903       if (p->sig & __DAHDI_SIG_FXS) {
02904          dahdi_enable_ec(p);
02905          dahdi_train_ec(p);
02906       }
02907       break;
02908 #ifdef HAVE_PRI
02909    case SIG_PRI:
02910       /* Send a pri acknowledge */
02911       if (!pri_grab(p, p->pri)) {
02912          p->proceeding = 1;
02913          res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
02914          pri_rel(p->pri);
02915       } else {
02916          ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
02917          res = -1;
02918       }
02919       break;
02920 #endif
02921    case 0:
02922       ast_mutex_unlock(&p->lock);
02923       return 0;
02924    default:
02925       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
02926       res = -1;
02927    }
02928    ast_mutex_unlock(&p->lock);
02929    return res;
02930 }

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 3254 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_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree, ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_read(), AST_STATE_RINGING, ast_verbose(), ast_waitfor_n(), ast_write(), dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_link(), dahdi_unlink(), DEADLOCK_AVOIDANCE, dahdi_subchannel::dfd, disable_dtmf_detect(), dahdi_pvt::echocanbridged, enable_dtmf_detect(), f, ast_channel::fds, dahdi_subchannel::inthreeway, dahdi_pvt::lock, ast_channel::lock, LOG_DEBUG, LOG_NOTICE, master, option_verbose, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pulsedial, dahdi_pvt::sig, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, ast_channel::tech_pvt, dahdi_pvt::transfer, update_conf(), and VERBOSE_PREFIX_3.

03255 {
03256    struct ast_channel *who;
03257    struct dahdi_pvt *p0, *p1, *op0, *op1;
03258    struct dahdi_pvt *master = NULL, *slave = NULL;
03259    struct ast_frame *f;
03260    int inconf = 0;
03261    int nothingok = 1;
03262    int ofd0, ofd1;
03263    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
03264    int os0 = -1, os1 = -1;
03265    int priority = 0;
03266    struct ast_channel *oc0, *oc1;
03267    enum ast_bridge_result res;
03268 
03269 #ifdef PRI_2BCT
03270    int triedtopribridge = 0;
03271    q931_call *q931c0 = NULL, *q931c1 = NULL;
03272 #endif
03273 
03274    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
03275       There is code below to handle it properly until DTMF is actually seen,
03276       but due to currently unresolved issues it's ignored...
03277    */
03278 
03279    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
03280       return AST_BRIDGE_FAILED_NOWARN;
03281 
03282    ast_mutex_lock(&c0->lock);
03283    while (ast_mutex_trylock(&c1->lock)) {
03284       DEADLOCK_AVOIDANCE(&c0->lock);
03285    }
03286 
03287    p0 = c0->tech_pvt;
03288    p1 = c1->tech_pvt;
03289    /* cant do pseudo-channels here */
03290    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
03291       ast_mutex_unlock(&c0->lock);
03292       ast_mutex_unlock(&c1->lock);
03293       return AST_BRIDGE_FAILED_NOWARN;
03294    }
03295 
03296    oi0 = dahdi_get_index(c0, p0, 0);
03297    oi1 = dahdi_get_index(c1, p1, 0);
03298    if ((oi0 < 0) || (oi1 < 0)) {
03299       ast_mutex_unlock(&c0->lock);
03300       ast_mutex_unlock(&c1->lock);
03301       return AST_BRIDGE_FAILED;
03302    }
03303 
03304    op0 = p0 = c0->tech_pvt;
03305    op1 = p1 = c1->tech_pvt;
03306    ofd0 = c0->fds[0];
03307    ofd1 = c1->fds[0];
03308    oc0 = p0->owner;
03309    oc1 = p1->owner;
03310 
03311    if (ast_mutex_trylock(&p0->lock)) {
03312       /* Don't block, due to potential for deadlock */
03313       ast_mutex_unlock(&c0->lock);
03314       ast_mutex_unlock(&c1->lock);
03315       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
03316       return AST_BRIDGE_RETRY;
03317    }
03318    if (ast_mutex_trylock(&p1->lock)) {
03319       /* Don't block, due to potential for deadlock */
03320       ast_mutex_unlock(&p0->lock);
03321       ast_mutex_unlock(&c0->lock);
03322       ast_mutex_unlock(&c1->lock);
03323       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
03324       return AST_BRIDGE_RETRY;
03325    }
03326 
03327    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03328       if (p0->owner && p1->owner) {
03329          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
03330          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
03331             master = p0;
03332             slave = p1;
03333             inconf = 1;
03334          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
03335             master = p1;
03336             slave = p0;
03337             inconf = 1;
03338          } else {
03339             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
03340             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
03341                p0->channel,
03342                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
03343                p0->subs[SUB_REAL].inthreeway, p0->channel,
03344                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
03345                p1->subs[SUB_REAL].inthreeway);
03346          }
03347          nothingok = 0;
03348       }
03349    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
03350       if (p1->subs[SUB_THREEWAY].inthreeway) {
03351          master = p1;
03352          slave = p0;
03353          nothingok = 0;
03354       }
03355    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
03356       if (p0->subs[SUB_THREEWAY].inthreeway) {
03357          master = p0;
03358          slave = p1;
03359          nothingok = 0;
03360       }
03361    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
03362       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise, 
03363          don't put us in anything */
03364       if (p1->subs[SUB_CALLWAIT].inthreeway) {
03365          master = p1;
03366          slave = p0;
03367          nothingok = 0;
03368       }
03369    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
03370       /* Same as previous */
03371       if (p0->subs[SUB_CALLWAIT].inthreeway) {
03372          master = p0;
03373          slave = p1;
03374          nothingok = 0;
03375       }
03376    }
03377    ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
03378       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
03379    if (master && slave) {
03380       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
03381          in an active threeway call with a channel that is ringing, we should
03382          indicate ringing. */
03383       if ((oi1 == SUB_THREEWAY) && 
03384           p1->subs[SUB_THREEWAY].inthreeway && 
03385           p1->subs[SUB_REAL].owner && 
03386           p1->subs[SUB_REAL].inthreeway && 
03387           (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03388          ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
03389          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
03390          os1 = p1->subs[SUB_REAL].owner->_state;
03391       } else {
03392          ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
03393          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
03394       }
03395       if ((oi0 == SUB_THREEWAY) && 
03396           p0->subs[SUB_THREEWAY].inthreeway && 
03397           p0->subs[SUB_REAL].owner && 
03398           p0->subs[SUB_REAL].inthreeway && 
03399           (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03400          ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
03401          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
03402          os0 = p0->subs[SUB_REAL].owner->_state;
03403       } else {
03404          ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
03405          tone_zone_play_tone(p1->subs[oi0].dfd, -1);
03406       }
03407       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03408          if (!p0->echocanbridged || !p1->echocanbridged) {
03409             /* Disable echo cancellation if appropriate */
03410             dahdi_disable_ec(p0);
03411             dahdi_disable_ec(p1);
03412          }
03413       }
03414       dahdi_link(slave, master);
03415       master->inconference = inconf;
03416    } else if (!nothingok)
03417       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
03418 
03419    update_conf(p0);
03420    update_conf(p1);
03421    t0 = p0->subs[SUB_REAL].inthreeway;
03422    t1 = p1->subs[SUB_REAL].inthreeway;
03423 
03424    ast_mutex_unlock(&p0->lock);
03425    ast_mutex_unlock(&p1->lock);
03426 
03427    ast_mutex_unlock(&c0->lock);
03428    ast_mutex_unlock(&c1->lock);
03429 
03430    /* Native bridge failed */
03431    if ((!master || !slave) && !nothingok) {
03432       dahdi_enable_ec(p0);
03433       dahdi_enable_ec(p1);
03434       return AST_BRIDGE_FAILED;
03435    }
03436    
03437    if (option_verbose > 2) 
03438       ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03439 
03440    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03441       disable_dtmf_detect(op0);
03442 
03443    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03444       disable_dtmf_detect(op1);
03445 
03446    for (;;) {
03447       struct ast_channel *c0_priority[2] = {c0, c1};
03448       struct ast_channel *c1_priority[2] = {c1, c0};
03449 
03450       /* Here's our main loop...  Start by locking things, looking for private parts, 
03451          and then balking if anything is wrong */
03452       ast_mutex_lock(&c0->lock);
03453       while (ast_mutex_trylock(&c1->lock)) {
03454          DEADLOCK_AVOIDANCE(&c0->lock);
03455       }
03456 
03457       p0 = c0->tech_pvt;
03458       p1 = c1->tech_pvt;
03459 
03460       if (op0 == p0)
03461          i0 = dahdi_get_index(c0, p0, 1);
03462       if (op1 == p1)
03463          i1 = dahdi_get_index(c1, p1, 1);
03464       ast_mutex_unlock(&c0->lock);
03465       ast_mutex_unlock(&c1->lock);
03466 
03467       if (!timeoutms || 
03468           (op0 != p0) ||
03469           (op1 != p1) || 
03470           (ofd0 != c0->fds[0]) || 
03471           (ofd1 != c1->fds[0]) ||
03472           (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 
03473           (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 
03474           (oc0 != p0->owner) || 
03475           (oc1 != p1->owner) ||
03476           (t0 != p0->subs[SUB_REAL].inthreeway) ||
03477           (t1 != p1->subs[SUB_REAL].inthreeway) ||
03478           (oi0 != i0) ||
03479           (oi1 != i1)) {
03480          ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
03481             op0->channel, oi0, op1->channel, oi1);
03482          res = AST_BRIDGE_RETRY;
03483          goto return_from_bridge;
03484       }
03485 
03486 #ifdef PRI_2BCT
03487       q931c0 = p0->call;
03488       q931c1 = p1->call;
03489       if (p0->transfer && p1->transfer 
03490           && q931c0 && q931c1 
03491           && !triedtopribridge) {
03492          pri_channel_bridge(q931c0, q931c1);
03493          triedtopribridge = 1;
03494       }
03495 #endif
03496 
03497       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
03498       if (!who) {
03499          ast_log(LOG_DEBUG, "Ooh, empty read...\n");
03500          continue;
03501       }
03502       f = ast_read(who);
03503       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
03504          *fo = f;
03505          *rc = who;
03506          res = AST_BRIDGE_COMPLETE;
03507          goto return_from_bridge;
03508       }
03509       if (f->frametype == AST_FRAME_DTMF) {
03510          if ((who == c0) && p0->pulsedial) {
03511             ast_write(c1, f);
03512          } else if ((who == c1) && p1->pulsedial) {
03513             ast_write(c0, f);
03514          } else {
03515             *fo = f;
03516             *rc = who;
03517             res = AST_BRIDGE_COMPLETE;
03518             goto return_from_bridge;
03519          }
03520       }
03521       ast_frfree(f);
03522       
03523       /* Swap who gets priority */
03524       priority = !priority;
03525    }
03526 
03527 return_from_bridge:
03528    if (op0 == p0)
03529       dahdi_enable_ec(p0);
03530 
03531    if (op1 == p1)
03532       dahdi_enable_ec(p1);
03533 
03534    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03535       enable_dtmf_detect(op0);
03536 
03537    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03538       enable_dtmf_detect(op1);
03539 
03540    dahdi_unlink(slave, master, 1);
03541 
03542    return res;
03543 }

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

Definition at line 1829 of file chan_dahdi.c.

References ast_channel::_state, ast_callerid_generate(), AST_LAW, ast_log(), ast_malloc, ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, AST_STATE_UP, ast_strlen_zero(), ast_transfercapability2str(), ast_verbose(), dahdi_pvt::callwait_name, dahdi_pvt::callwait_num, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitrings, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_callwait(), dahdi_get_index(), dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialednone, dahdi_pvt::dialing, dahdi_pvt::digital, dahdi_pvt::distinctivering, dahdi_pvt::dop, dahdi_pvt::echobreak, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, dahdi_pvt::finaldial, free, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, IS_DIGITAL, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_pvt::law, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, MAX_CALLERID_SIZE, dahdi_subchannel::needbusy, dahdi_subchannel::needringing, dahdi_pvt::oprmode, option_verbose, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pvt::owner, pbx_builtin_getvar_helper(), PRI_TRANS_CAP_DIGITAL, dahdi_pvt::priexclusive, dahdi_pvt::pulse, dahdi_pvt::radio, dahdi_pvt::rxgain, s, send_callerid(), dahdi_pvt::sendcalleridafter, set_actual_gain(), dahdi_pvt::sig, 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_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::stripmsd, SUB_CALLWAIT, SUB_REAL, dahdi_pvt::subs, ast_channel::tech_pvt, ast_channel::transfercapability, dahdi_pvt::txgain, dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, VERBOSE_PREFIX_3, and dahdi_pvt::whichwink.

01830 {
01831    struct dahdi_pvt *p = ast->tech_pvt;
01832    int x, res, index,mysig;
01833    char *c, *n, *l;
01834 #ifdef HAVE_PRI
01835    char *s = NULL;
01836 #endif
01837    char dest[256]; /* must be same length as p->dialdest */
01838    ast_mutex_lock(&p->lock);
01839    ast_copy_string(dest, rdest, sizeof(dest));
01840    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
01841    if ((ast->_state == AST_STATE_BUSY)) {
01842       p->subs[SUB_REAL].needbusy = 1;
01843       ast_mutex_unlock(&p->lock);
01844       return 0;
01845    }
01846    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
01847       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
01848       ast_mutex_unlock(&p->lock);
01849       return -1;
01850    }
01851    p->dialednone = 0;
01852    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
01853    {
01854       /* Special pseudo -- automatically up */
01855       ast_setstate(ast, AST_STATE_UP); 
01856       ast_mutex_unlock(&p->lock);
01857       return 0;
01858    }
01859    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
01860    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
01861    if (res)
01862       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
01863    p->outgoing = 1;
01864 
01865    set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
01866 
01867    mysig = p->sig;
01868    if (p->outsigmod > -1)
01869       mysig = p->outsigmod;
01870 
01871    switch (mysig) {
01872    case SIG_FXOLS:
01873    case SIG_FXOGS:
01874    case SIG_FXOKS:
01875       if (p->owner == ast) {
01876          /* Normal ring, on hook */
01877          
01878          /* Don't send audio while on hook, until the call is answered */
01879          p->dialing = 1;
01880          if (p->use_callerid) {
01881             /* Generate the Caller-ID spill if desired */
01882             if (p->cidspill) {
01883                ast_log(LOG_WARNING, "cidspill already exists??\n");
01884                free(p->cidspill);
01885             }
01886             p->callwaitcas = 0;
01887             if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01888                p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
01889                p->cidpos = 0;
01890                send_callerid(p);
01891             }
01892          }
01893          /* Choose proper cadence */
01894          if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
01895             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
01896                ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
01897             p->cidrings = cidrings[p->distinctivering - 1];
01898          } else {
01899             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
01900                ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
01901             p->cidrings = p->sendcalleridafter;
01902          }
01903 
01904          /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
01905          c = strchr(dest, '/');
01906          if (c)
01907             c++;
01908          if (c && (strlen(c) < p->stripmsd)) {
01909             ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
01910             c = NULL;
01911          }
01912          if (c) {
01913             p->dop.op = DAHDI_DIAL_OP_REPLACE;
01914             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
01915             ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
01916          } else {
01917             p->dop.dialstr[0] = '\0';
01918          }
01919          x = DAHDI_RING;
01920          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
01921             ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
01922             ast_mutex_unlock(&p->lock);
01923             return -1;
01924          }
01925          p->dialing = 1;
01926       } else {
01927          /* Call waiting call */
01928          p->callwaitrings = 0;
01929          if (ast->cid.cid_num)
01930             ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
01931          else
01932             p->callwait_num[0] = '\0';
01933          if (ast->cid.cid_name)
01934             ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
01935          else
01936             p->callwait_name[0] = '\0';
01937          /* Call waiting tone instead */
01938          if (dahdi_callwait(ast)) {
01939             ast_mutex_unlock(&p->lock);
01940             return -1;
01941          }
01942          /* Make ring-back */
01943          if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
01944             ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
01945             
01946       }
01947       n = ast->cid.cid_name;
01948       l = ast->cid.cid_num;
01949       if (l)
01950          ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
01951       else
01952          p->lastcid_num[0] = '\0';
01953       if (n)
01954          ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
01955       else
01956          p->lastcid_name[0] = '\0';
01957       ast_setstate(ast, AST_STATE_RINGING);
01958       index = dahdi_get_index(ast, p, 0);
01959       if (index > -1) {
01960          p->subs[index].needringing = 1;
01961       }
01962       break;
01963    case SIG_FXSLS:
01964    case SIG_FXSGS:
01965    case SIG_FXSKS:
01966    case SIG_EMWINK:
01967    case SIG_EM:
01968    case SIG_EM_E1:
01969    case SIG_FEATD:
01970    case SIG_FEATDMF:
01971    case SIG_E911:
01972    case SIG_FGC_CAMA:
01973    case SIG_FGC_CAMAMF:
01974    case SIG_FEATB:
01975    case SIG_SFWINK:
01976    case SIG_SF:
01977    case SIG_SF_FEATD:
01978    case SIG_SF_FEATDMF:
01979    case SIG_FEATDMF_TA:
01980    case SIG_SF_FEATB:
01981       c = strchr(dest, '/');
01982       if (c)
01983          c++;
01984       else
01985          c = "";
01986       if (strlen(c) < p->stripmsd) {
01987          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
01988          ast_mutex_unlock(&p->lock);
01989          return -1;
01990       }
01991 #ifdef HAVE_PRI
01992       /* Start the trunk, if not GR-303 */
01993       if (!p->pri) {
01994 #endif
01995          x = DAHDI_START;
01996          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
01997          if (res < 0) {
01998             if (errno != EINPROGRESS) {
01999                ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02000                ast_mutex_unlock(&p->lock);
02001                return -1;
02002             }
02003          }
02004 #ifdef HAVE_PRI
02005       }
02006 #endif
02007       ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
02008       p->dop.op = DAHDI_DIAL_OP_REPLACE;
02009 
02010       c += p->stripmsd;
02011 
02012       switch (mysig) {
02013       case SIG_FEATD:
02014          l = ast->cid.cid_num;
02015          if (l) 
02016             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02017          else
02018             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02019          break;
02020       case SIG_FEATDMF:
02021          l = ast->cid.cid_num;
02022          if (l) 
02023             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02024          else
02025             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02026          break;
02027       case SIG_FEATDMF_TA:
02028       {
02029          const char *cic, *ozz;
02030 
02031          /* If you have to go through a Tandem Access point you need to use this */
02032          ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02033          if (!ozz)
02034             ozz = defaultozz;
02035          cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02036          if (!cic)
02037             cic = defaultcic;
02038          if (!ozz || !cic) {
02039             ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02040             ast_mutex_unlock(&p->lock);
02041             return -1;
02042          }
02043          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02044          snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02045          p->whichwink = 0;
02046       }
02047          break;
02048       case SIG_E911:
02049          ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02050          break;
02051       case SIG_FGC_CAMA:
02052          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02053          break;
02054       case SIG_FGC_CAMAMF:
02055       case SIG_FEATB:
02056          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02057          break;
02058       default:
02059          if (p->pulse)
02060             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02061          else
02062             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02063          break;
02064       }
02065 
02066       if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02067          memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02068          strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02069          p->echorest[sizeof(p->echorest) - 1] = '\0';
02070          p->echobreak = 1;
02071          p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02072       } else
02073          p->echobreak = 0;
02074       if (!res) {
02075          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02076             int saveerr = errno;
02077 
02078             x = DAHDI_ONHOOK;
02079             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02080             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02081             ast_mutex_unlock(&p->lock);
02082             return -1;
02083          }
02084       } else
02085          ast_log(LOG_DEBUG, "Deferring dialing...\n");
02086       p->dialing = 1;
02087       if (ast_strlen_zero(c))
02088          p->dialednone = 1;
02089       ast_setstate(ast, AST_STATE_DIALING);
02090       break;
02091    case 0:
02092       /* Special pseudo -- automatically up*/
02093       ast_setstate(ast, AST_STATE_UP);
02094       break;      
02095    case SIG_PRI:
02096       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
02097       p->dialdest[0] = '\0';
02098       break;
02099    default:
02100       ast_log(LOG_DEBUG, "not yet implemented\n");
02101       ast_mutex_unlock(&p->lock);
02102       return -1;
02103    }
02104 #ifdef HAVE_PRI
02105    if (p->pri) {
02106       struct pri_sr *sr;
02107 #ifdef SUPPORT_USERUSER
02108       const char *useruser;
02109 #endif
02110       int pridialplan;
02111       int dp_strip;
02112       int prilocaldialplan;
02113       int ldp_strip;
02114       int exclusive;
02115       const char *rr_str;
02116       int redirect_reason;
02117 
02118       c = strchr(dest, '/');
02119       if (c)
02120          c++;
02121       else
02122          c = dest;
02123 
02124       l = NULL;
02125       n = NULL;
02126 
02127       if (!p->hidecallerid) {
02128          l = ast->cid.cid_num;
02129          if (!p->hidecalleridname) {
02130             n = ast->cid.cid_name;
02131          }
02132       }
02133 
02134 
02135       if (strlen(c) < p->stripmsd) {
02136          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02137          ast_mutex_unlock(&p->lock);
02138          return -1;
02139       }
02140       if (mysig != SIG_FXSKS) {
02141          p->dop.op = DAHDI_DIAL_OP_REPLACE;
02142          s = strchr(c + p->stripmsd, 'w');
02143          if (s) {
02144             if (strlen(s) > 1)
02145                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
02146             else
02147                p->dop.dialstr[0] = '\0';
02148             *s = '\0';
02149          } else {
02150             p->dop.dialstr[0] = '\0';
02151          }
02152       }
02153       if (pri_grab(p, p->pri)) {
02154          ast_log(LOG_WARNING, "Failed to grab PRI!\n");
02155          ast_mutex_unlock(&p->lock);
02156          return -1;
02157       }
02158       if (!(p->call = pri_new_call(p->pri->pri))) {
02159          ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
02160          pri_rel(p->pri);
02161          ast_mutex_unlock(&p->lock);
02162          return -1;
02163       }
02164       if (!(sr = pri_sr_new())) {
02165          ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
02166          pri_destroycall(p->pri->pri, p->call);
02167          p->call = NULL;
02168          pri_rel(p->pri);
02169          ast_mutex_unlock(&p->lock);
02170          return -1;
02171       }
02172       if (p->bearer || (mysig == SIG_FXSKS)) {
02173          if (p->bearer) {
02174             ast_log(LOG_DEBUG, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
02175             p->bearer->call = p->call;
02176          } else
02177             ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
02178          pri_set_crv(p->pri->pri, p->call, p->channel, 0);
02179       }
02180       p->digital = IS_DIGITAL(ast->transfercapability);
02181       /* Add support for exclusive override */
02182       if (p->priexclusive)
02183          exclusive = 1;
02184       else {
02185       /* otherwise, traditional behavior */
02186          if (p->pri->nodetype == PRI_NETWORK)
02187             exclusive = 0;
02188          else
02189             exclusive = 1;
02190       }
02191       
02192       pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
02193       pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 
02194                (p->digital ? -1 : 
02195                   ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
02196       if (p->pri->facilityenable)
02197          pri_facility_enable(p->pri->pri);
02198 
02199       if (option_verbose > 2)
02200          ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
02201       dp_strip = 0;
02202       pridialplan = p->pri->dialplan - 1;
02203       if (pridialplan == -2) { /* compute dynamically */
02204          if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02205             dp_strip = strlen(p->pri->internationalprefix);
02206             pridialplan = PRI_INTERNATIONAL_ISDN;
02207          } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02208             dp_strip = strlen(p->pri->nationalprefix);
02209             pridialplan = PRI_NATIONAL_ISDN;
02210          } else {
02211             pridialplan = PRI_LOCAL_ISDN;
02212          }
02213       }
02214       pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
02215 
02216       ldp_strip = 0;
02217       prilocaldialplan = p->pri->localdialplan - 1;
02218       if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */
02219          if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02220             ldp_strip = strlen(p->pri->internationalprefix);
02221             prilocaldialplan = PRI_INTERNATIONAL_ISDN;
02222          } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02223             ldp_strip = strlen(p->pri->nationalprefix);
02224             prilocaldialplan = PRI_NATIONAL_ISDN;
02225          } else {
02226             prilocaldialplan = PRI_LOCAL_ISDN;
02227          }
02228       }
02229       pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
02230          p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
02231       if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
02232          if (!strcasecmp(rr_str, "UNKNOWN"))
02233             redirect_reason = 0;
02234          else if (!strcasecmp(rr_str, "BUSY"))
02235             redirect_reason = 1;
02236          else if (!strcasecmp(rr_str, "NO_REPLY"))
02237             redirect_reason = 2;
02238          else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
02239             redirect_reason = 15;
02240          else
02241             redirect_reason = PRI_REDIR_UNCONDITIONAL;
02242       } else
02243          redirect_reason = PRI_REDIR_UNCONDITIONAL;
02244       pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
02245 
02246 #ifdef SUPPORT_USERUSER
02247       /* User-user info */
02248       useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
02249 
02250       if (useruser)
02251          pri_sr_set_useruser(sr, useruser);
02252 #endif
02253 
02254       if (pri_setup(p->pri->pri, p->call, sr)) {
02255          ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 
02256             c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
02257          pri_rel(p->pri);
02258          ast_mutex_unlock(&p->lock);
02259          pri_sr_free(sr);
02260          return -1;
02261       }
02262       pri_sr_free(sr);
02263       ast_setstate(ast, AST_STATE_DIALING);
02264       pri_rel(p->pri);
02265    }
02266 #endif      
02267    ast_mutex_unlock(&p->lock);
02268    return 0;
02269 }

static int dahdi_callwait ( struct ast_channel ast  )  [static]

Definition at line 1801 of file chan_dahdi.c.

References 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, free, LOG_WARNING, READ_SIZE, save_conference(), send_callerid(), and ast_channel::tech_pvt.

Referenced by dahdi_call(), and dahdi_read().

01802 {
01803    struct dahdi_pvt *p = ast->tech_pvt;
01804    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01805    if (p->cidspill) {
01806       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01807       free(p->cidspill);
01808    }
01809    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01810       return -1;
01811    save_conference(p);
01812    /* Silence */
01813    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01814    if (!p->callwaitrings && p->callwaitingcallerid) {
01815       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01816       p->callwaitcas = 1;
01817       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01818    } else {
01819       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01820       p->callwaitcas = 0;
01821       p->cidlen = 2400 + READ_SIZE * 4;
01822    }
01823    p->cidpos = 0;
01824    send_callerid(p);
01825    
01826    return 0;
01827 }

static struct dahdi_chan_conf dahdi_chan_conf_default ( void   )  [static]

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

Definition at line 609 of file chan_dahdi.c.

References dahdi_chan_conf::chan, CID_SIG_BELL, CID_START_RING, dahdi_pvt::context, and DEFAULT_CIDRINGS.

Referenced by setup_dahdi().

00609                                                             {
00610    /* recall that if a field is not included here it is initialized
00611     * to 0 or equivalent
00612     */
00613    struct dahdi_chan_conf conf = {
00614 #ifdef HAVE_PRI
00615       .pri = {
00616          .nsf = PRI_NSF_NONE,
00617          .switchtype = PRI_SWITCH_NI2,
00618          .dialplan = PRI_NATIONAL_ISDN + 1,
00619          .localdialplan = PRI_NATIONAL_ISDN + 1,
00620          .nodetype = PRI_CPE,
00621 
00622          .minunused = 2,
00623          .idleext = "",
00624          .idledial = "",
00625          .internationalprefix = "",
00626          .nationalprefix = "",
00627          .localprefix = "",
00628          .privateprefix = "",
00629          .unknownprefix = "",
00630 
00631          .resetinterval = 3600
00632       },
00633 #endif
00634       .chan = {
00635          .context = "default",
00636          .cid_num = "",
00637          .cid_name = "",
00638          .mohinterpret = "default",
00639          .mohsuggest = "",
00640          .transfertobusy = 1,
00641 
00642          .cid_signalling = CID_SIG_BELL,
00643          .cid_start = CID_START_RING,
00644          .dahditrcallerid = 0,
00645          .use_callerid = 1,
00646          .sig = -1,
00647          .outsigmod = -1,
00648 
00649          .tonezone = -1,
00650 
00651          .echocancel = 1,
00652 
00653          .busycount = 3,
00654          .busycompare = 0,
00655          .busytonelength = 0,
00656          .busyquietlength = 0,
00657          .busyfuzziness = 0,
00658          .silencethreshold = 0,
00659 
00660          .accountcode = "",
00661 
00662          .mailbox = "",
00663 
00664 
00665          .polarityonanswerdelay = 600,
00666 
00667          .sendcalleridafter = DEFAULT_CIDRINGS,
00668 
00669          .buf_policy = DAHDI_POLICY_IMMEDIATE,
00670          .buf_no = numbufs
00671       },
00672       .timing = {
00673          .prewinktime = -1,
00674          .preflashtime = -1,
00675          .winktime = -1,
00676          .flashtime = -1,
00677          .starttime = -1,
00678          .rxwinktime = -1,
00679          .rxflashtime = -1,
00680          .debouncetime = -1
00681       },
00682       .smdi_port = "/dev/ttyS0",
00683    };
00684 
00685    return conf;
00686 }

static void dahdi_close ( int  fd  )  [static]

Definition at line 957 of file chan_dahdi.c.

Referenced by dahdi_close_sub().

00958 {
00959    if (fd > 0)
00960       close(fd);
00961 }

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

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

00964 {
00965    dahdi_close(chan_pvt->subs[sub_num].dfd);
00966    chan_pvt->subs[sub_num].dfd = -1;
00967 }

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

Definition at line 1684 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, errno, LOG_WARNING, dahdi_pvt::sig, SIG_PRI, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_handle_dtmfup(), dahdi_handle_event(), dahdi_hangup(), and dahdi_new().

01685 {
01686    int x, y, res;
01687    x = muted;
01688    if (p->sig == SIG_PRI) {
01689       y = 1;
01690       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
01691       if (res)
01692          ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
01693    }
01694    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
01695    if (res < 0)
01696       ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
01697    return res;
01698 }

static int dahdi_destroy_channel ( int  fd,
int  argc,
char **  argv 
) [static]

Definition at line 10050 of file chan_dahdi.c.

References dahdi_destroy_channel_bynum(), and RESULT_SHOWUSAGE.

10051 {
10052    int channel;
10053    
10054    if (argc != 4)
10055       return RESULT_SHOWUSAGE;
10056    
10057    channel = atoi(argv[3]);
10058 
10059    return dahdi_destroy_channel_bynum(channel);
10060 }

static int dahdi_destroy_channel_bynum ( int  channel  )  [static]

Definition at line 6721 of file chan_dahdi.c.

References ast_module_unref(), dahdi_pvt::channel, destroy_channel(), iflist, dahdi_pvt::next, dahdi_pvt::prev, RESULT_FAILURE, RESULT_SUCCESS, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_destroy_channel(), and handle_init_event().

06722 {
06723    struct dahdi_pvt *tmp = NULL;
06724    struct dahdi_pvt *prev = NULL;
06725 
06726    tmp = iflist;
06727    while (tmp) {
06728       if (tmp->channel == channel) {
06729          int x = DAHDI_FLASH;
06730          ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */
06731          destroy_channel(prev, tmp, 1);
06732          ast_module_unref(ast_module_info->self);
06733          return RESULT_SUCCESS;
06734       }
06735       prev = tmp;
06736       tmp = tmp->next;
06737    }
06738    return RESULT_FAILURE;
06739 }

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

Definition at line 1058 of file chan_dahdi.c.

References ast_channel::_state, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DIALING, dahdi_pvt::begindigit, dahdi_get_index(), dahdi_pvt::dialdest, dahdi_pvt::dialing, digit_to_dtmfindex(), errno, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::owner, dahdi_pvt::pulse, dahdi_pvt::sig, SIG_PRI, dahdi_pvt::span, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

01059 {
01060    struct dahdi_pvt *pvt;
01061    int index;
01062    int dtmf = -1;
01063    
01064    pvt = chan->tech_pvt;
01065 
01066    ast_mutex_lock(&pvt->lock);
01067 
01068    index = dahdi_get_index(chan, pvt, 0);
01069 
01070    if ((index != SUB_REAL) || !pvt->owner)
01071       goto out;
01072 
01073 #ifdef HAVE_PRI
01074    if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01075       if (pvt->setup_ack) {
01076          if (!pri_grab(pvt, pvt->pri)) {
01077             pri_information(pvt->pri->pri, pvt->call, digit);
01078             pri_rel(pvt->pri);
01079          } else
01080             ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01081       } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01082          int res;
01083          ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01084          res = strlen(pvt->dialdest);
01085          pvt->dialdest[res++] = digit;
01086          pvt->dialdest[res] = '\0';
01087       }
01088       goto out;
01089    }
01090 #endif
01091    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01092       goto out;
01093 
01094    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
01095       int res;
01096       struct dahdi_dialoperation zo = {
01097          .op = DAHDI_DIAL_OP_APPEND,
01098          .dialstr[0] = 'T',
01099          .dialstr[1] = digit,
01100          .dialstr[2] = 0,
01101       };
01102       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
01103          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
01104       else
01105          pvt->dialing = 1;
01106    } else {
01107       ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
01108       pvt->dialing = 1;
01109       pvt->begindigit = digit;
01110    }
01111 
01112 out:
01113    ast_mutex_unlock(&pvt->lock);
01114 
01115    return 0;
01116 }

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

Definition at line 1118 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::begindigit, dahdi_get_index(), dahdi_pvt::dialing, dahdi_pvt::lock, LOG_DEBUG, dahdi_pvt::owner, dahdi_pvt::pulse, dahdi_pvt::sig, SIG_PRI, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

01119 {
01120    struct dahdi_pvt *pvt;
01121    int res = 0;
01122    int index;
01123    int x;
01124    
01125    pvt = chan->tech_pvt;
01126 
01127    ast_mutex_lock(&pvt->lock);
01128    
01129    index = dahdi_get_index(chan, pvt, 0);
01130 
01131    if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
01132       goto out;
01133 
01134 #ifdef HAVE_PRI
01135    /* This means that the digit was already sent via PRI signalling */
01136    if (pvt->sig == SIG_PRI && !pvt->begindigit)
01137       goto out;
01138 #endif
01139 
01140    if (pvt->begindigit) {
01141       x = -1;
01142       ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
01143       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
01144       pvt->dialing = 0;
01145       pvt->begindigit = 0;
01146    }
01147 
01148 out:
01149    ast_mutex_unlock(&pvt->lock);
01150 
01151    return res;
01152 }

static void dahdi_disable_ec ( struct dahdi_pvt p  )  [static]

Definition at line 1515 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, LOG_DEBUG, LOG_WARNING, option_debug, SUB_REAL, and dahdi_pvt::subs.

Referenced by __dahdi_exception(), dahdi_bridge(), dahdi_handle_event(), dahdi_hangup(), dahdi_setoption(), and handle_init_event().

01516 {
01517    int x;
01518    int res;
01519    if (p->echocancel) {
01520       x = 0;
01521       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
01522       if (res)
01523          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
01524       else if (option_debug)
01525          ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
01526    }
01527    p->echocanon = 0;
01528 }

static void dahdi_enable_ec ( struct dahdi_pvt p  )  [static]

Definition at line 1465 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, dahdi_pvt::digital, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, LOG_DEBUG, LOG_WARNING, option_debug, dahdi_pvt::sig, SIG_PRI, SUB_REAL, and dahdi_pvt::subs.

Referenced by __dahdi_exception(), dahdi_answer(), dahdi_bridge(), dahdi_handle_event(), dahdi_setoption(), handle_init_event(), and ss_thread().

01466 {
01467    int x;
01468    int res;
01469    if (!p)
01470       return;
01471    if (p->echocanon) {
01472       ast_log(LOG_DEBUG, "Echo cancellation already on\n");
01473       return;
01474    }
01475    if (p->digital) {
01476       ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
01477       return;
01478    }
01479    if (p->echocancel) {
01480       if (p->sig == SIG_PRI) {
01481          x = 1;
01482          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
01483          if (res)
01484             ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
01485       }
01486       x = p->echocancel;
01487       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
01488       if (res) 
01489          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
01490       else {
01491          p->echocanon = 1;
01492          if (option_debug)
01493             ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
01494       }
01495    } else if (option_debug)
01496       ast_log(LOG_DEBUG, "No echo cancellation requested\n");
01497 }

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

Definition at line 4747 of file chan_dahdi.c.

References __dahdi_exception(), ast_mutex_lock(), ast_mutex_unlock(), f, dahdi_pvt::lock, and ast_channel::tech_pvt.

04748 {
04749    struct dahdi_pvt *p = ast->tech_pvt;
04750    struct ast_frame *f;
04751    ast_mutex_lock(&p->lock);
04752    f = __dahdi_exception(ast);
04753    ast_mutex_unlock(&p->lock);
04754    return f;
04755 }

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

Definition at line 10586 of file chan_dahdi.c.

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

Referenced by __action_transfer(), and __action_transferhangup().

10587 {
10588    if (p) {
10589       switch (mode) {
10590          case TRANSFER:
10591             p->fake_event = DAHDI_EVENT_WINKFLASH;
10592             break;
10593          case HANGUP:
10594             p->fake_event = DAHDI_EVENT_ONHOOK;
10595             break;
10596          default:
10597             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
10598       }
10599    }
10600    return 0;
10601 }

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

Definition at line 3545 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), dahdi_pvt::channel, dahdi_unlink(), dahdi_pvt::lock, LOG_DEBUG, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::subs, and ast_channel::tech_pvt.

03546 {
03547    struct dahdi_pvt *p = newchan->tech_pvt;
03548    int x;
03549    ast_mutex_lock(&p->lock);
03550    ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
03551    if (p->owner == oldchan) {
03552       p->owner = newchan;
03553    }
03554    for (x = 0; x < 3; x++)
03555       if (p->subs[x].owner == oldchan) {
03556          if (!x)
03557             dahdi_unlink(NULL, p, 0);
03558          p->subs[x].owner = newchan;
03559       }
03560    if (newchan->_state == AST_STATE_RINGING) 
03561       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
03562    update_conf(p);
03563    ast_mutex_unlock(&p->lock);
03564    return 0;
03565 }

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

Definition at line 3117 of file chan_dahdi.c.

References ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::lock, dahdi_pvt::rxgain, ast_channel::tech_pvt, and dahdi_pvt::txgain.

03118 {
03119    struct dahdi_pvt *p = chan->tech_pvt;
03120    
03121    if (!strcasecmp(data, "rxgain")) {
03122       ast_mutex_lock(&p->lock);
03123       snprintf(buf, len, "%f", p->rxgain);
03124       ast_mutex_unlock(&p->lock);   
03125    } else if (!strcasecmp(data, "txgain")) {
03126       ast_mutex_lock(&p->lock);
03127       snprintf(buf, len, "%f", p->txgain);
03128       ast_mutex_unlock(&p->lock);   
03129    } else {
03130       ast_copy_string(buf, "", len);
03131    }
03132    return 0;
03133 }

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

Avoid the silly dahdi_getevent which ignores a bunch of events.

Definition at line 256 of file chan_dahdi.c.

Referenced by __dahdi_exception(), dahdi_handle_event(), and ss_thread().

00257 {
00258    int j;
00259    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00260       return -1;
00261    return j;
00262 }

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

Definition at line 802 of file chan_dahdi.c.

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

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

00803 {
00804    int res;
00805    if (p->subs[SUB_REAL].owner == ast)
00806       res = 0;
00807    else if (p->subs[SUB_CALLWAIT].owner == ast)
00808       res = 1;
00809    else if (p->subs[SUB_THREEWAY].owner == ast)
00810       res = 2;
00811    else {
00812       res = -1;
00813       if (!nullok)
00814          ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
00815    }
00816    return res;
00817 }

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

Definition at line 3708 of file chan_dahdi.c.

References ast_async_goto(), AST_CONTROL_ANSWER, ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_NULL, ast_log(), ast_verbose(), dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, ast_channel::cid, ast_callerid::cid_num, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, ast_channel::context, dahdi_confmute(), ast_channel::exten, dahdi_subchannel::f, f, dahdi_pvt::faxhandled, ast_frame::frametype, free, LOG_DEBUG, LOG_NOTICE, ast_channel::macrocontext, option_debug, option_verbose, pbx_builtin_setvar_helper(), S_OR, send_cwcidspill(), ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.

Referenced by dahdi_handle_event(), and dahdi_read().

03709 {
03710    struct dahdi_pvt *p = ast->tech_pvt;
03711    struct ast_frame *f = *dest;
03712 
03713    if (option_debug)
03714       ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
03715 
03716    if (p->confirmanswer) {
03717       if (option_debug)
03718          ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
03719       /* Upon receiving a DTMF digit, consider this an answer confirmation instead
03720          of a DTMF digit */
03721       p->subs[index].f.frametype = AST_FRAME_CONTROL;
03722       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
03723       *dest = &p->subs[index].f;
03724       /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
03725       p->confirmanswer = 0;
03726    } else if (p->callwaitcas) {
03727       if ((f->subclass == 'A') || (f->subclass == 'D')) {
03728          if (option_debug)
03729             ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
03730          if (p->cidspill)
03731             free(p->cidspill);
03732          send_cwcidspill(p);
03733       }
03734       if ((f->subclass != 'm') && (f->subclass != 'u')) 
03735          p->callwaitcas = 0;
03736       p->subs[index].f.frametype = AST_FRAME_NULL;
03737       p->subs[index].f.subclass = 0;
03738       *dest = &p->subs[index].f;
03739    } else if (f->subclass == 'f') {
03740       /* Fax tone -- Handle and return NULL */
03741       if ((p->callprogress & 0x6) && !p->faxhandled) {
03742          p->faxhandled++;
03743          if (strcmp(ast->exten, "fax")) {
03744             const char *target_context = S_OR(ast->macrocontext, ast->context);
03745 
03746             if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
03747                if (option_verbose > 2)
03748                   ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
03749                /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
03750                pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
03751                if (ast_async_goto(ast, target_context, "fax", 1))
03752                   ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
03753             } else
03754                ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
03755          } else if (option_debug)
03756             ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
03757       } else if (option_debug)
03758             ast_log(LOG_DEBUG, "Fax already handled\n");
03759       dahdi_confmute(p, 0);
03760       p->subs[index].f.frametype = AST_FRAME_NULL;
03761       p->subs[index].f.subclass = 0;
03762       *dest = &p->subs[index].f;
03763    } else if (f->subclass == 'm') {
03764       /* Confmute request */
03765       dahdi_confmute(p, 1);
03766       p->subs[index].f.frametype = AST_FRAME_NULL;
03767       p->subs[index].f.subclass = 0;
03768       *dest = &p->subs[index].f;    
03769    } else if (f->subclass == 'u') {
03770       /* Unmute */
03771       dahdi_confmute(p, 0);
03772       p->subs[index].f.frametype = AST_FRAME_NULL;
03773       p->subs[index].f.subclass = 0;
03774       *dest = &p->subs[index].f;    
03775    } else
03776       dahdi_confmute(p, 0);
03777 }

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

Definition at line 3799 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, alloc_sub(), dahdi_pvt::answeronpolarityswitch, ast_bridged_channel(), AST_CONTROL_ANSWER, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_pthread_create, ast_queue_control(), ast_queue_control_data(), ast_queue_hangup(), 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_verbose(), attempt_transfer(), dahdi_pvt::callwaitcas, CANPROGRESSDETECT, dahdi_pvt::channel, 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::cidrings, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_confmute(), dahdi_disable_ec(), dahdi_enable_ec(), DAHDI_EVENT_DTMFDOWN, DAHDI_EVENT_DTMFUP, dahdi_get_event(), dahdi_get_index(), dahdi_handle_dtmfup(), dahdi_new(), dahdi_ring_phone(), dahdi_set_hook(), dahdi_train_ec(), dahdi_pvt::dahditrcallerid, ast_frame::data, ast_frame::datalen, DEADLOCK_AVOIDANCE, dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialing, dahdi_pvt::dop, dahdi_pvt::echobreak, dahdi_pvt::echocanon, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, event2str(), EVENT_FLAG_SYSTEM, dahdi_subchannel::f, f, dahdi_pvt::fake_event, dahdi_pvt::finaldial, dahdi_pvt::flashtime, ast_frame::frametype, free, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::inalarm, dahdi_subchannel::inthreeway, ast_channel::lock, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, ast_frame::mallocd, manager_event(), MIN_MS_SINCE_FLASH, dahdi_pvt::mohsuggest, dahdi_pvt::msgstate, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::onhooktime, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, option_debug, option_verbose, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pvt::overlapdial, dahdi_subchannel::owner, dahdi_pvt::owner, ast_channel::pbx, dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pvt::polaritydelaytv, dahdi_pvt::polarityonanswerdelay, 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_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, ast_frame::src, ss_thread(), 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(), dahdi_pvt::unknown_alarm, update_conf(), VERBOSE_PREFIX_3, and dahdi_pvt::whichwink.

Referenced by __dahdi_exception().

03800 {
03801    int res, x;
03802    int index, mysig;
03803    char *c;
03804    struct dahdi_pvt *p = ast->tech_pvt;
03805    pthread_t threadid;
03806    pthread_attr_t attr;
03807    struct ast_channel *chan;
03808    struct ast_frame *f;
03809 
03810    index = dahdi_get_index(ast, p, 0);
03811    mysig = p->sig;
03812    if (p->outsigmod > -1)
03813       mysig = p->outsigmod;
03814    p->subs[index].f.frametype = AST_FRAME_NULL;
03815    p->subs[index].f.subclass = 0;
03816    p->subs[index].f.datalen = 0;
03817    p->subs[index].f.samples = 0;
03818    p->subs[index].f.mallocd = 0;
03819    p->subs[index].f.offset = 0;
03820    p->subs[index].f.src = "dahdi_handle_event";
03821    p->subs[index].f.data = NULL;
03822    f = &p->subs[index].f;
03823 
03824    if (index < 0)
03825       return &p->subs[index].f;
03826    if (p->fake_event) {
03827       res = p->fake_event;
03828       p->fake_event = 0;
03829    } else
03830       res = dahdi_get_event(p->subs[index].dfd);
03831 
03832    if (option_debug)
03833       ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
03834 
03835    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
03836       p->pulsedial =  (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
03837 
03838       ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
03839 #ifdef HAVE_PRI
03840       if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) {
03841          /* absorb event */
03842       } else {
03843 #endif
03844          p->subs[index].f.frametype = AST_FRAME_DTMF_END;
03845          p->subs[index].f.subclass = res & 0xff;
03846 #ifdef HAVE_PRI
03847       }
03848 #endif
03849       dahdi_handle_dtmfup(ast, index, &f);
03850       return f;
03851    }
03852 
03853    if (res & DAHDI_EVENT_DTMFDOWN) {
03854       if (option_debug)
03855          ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
03856       /* Mute conference */
03857       dahdi_confmute(p, 1);
03858       p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
03859       p->subs[index].f.subclass = res & 0xff;
03860       return &p->subs[index].f;
03861    }
03862 
03863    switch (res) {
03864 #ifdef DAHDI_EVENT_EC_DISABLED
03865       case DAHDI_EVENT_EC_DISABLED:
03866          if (option_verbose > 2) 
03867             ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
03868          p->echocanon = 0;
03869          break;
03870 #endif
03871       case DAHDI_EVENT_BITSCHANGED:
03872          ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
03873       case DAHDI_EVENT_PULSE_START:
03874          /* Stop tone if there's a pulse start and the PBX isn't started */
03875          if (!ast->pbx)
03876             tone_zone_play_tone(p->subs[index].dfd, -1);
03877          break;   
03878       case DAHDI_EVENT_DIALCOMPLETE:
03879          if (p->inalarm) break;
03880          if ((p->radio || (p->oprmode < 0))) break;
03881          if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
03882             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
03883             return NULL;
03884          }
03885          if (!x) { /* if not still dialing in driver */
03886             dahdi_enable_ec(p);
03887             if (p->echobreak) {
03888                dahdi_train_ec(p);
03889                ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
03890                p->dop.op = DAHDI_DIAL_OP_REPLACE;
03891                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
03892                p->echobreak = 0;
03893             } else {
03894                p->dialing = 0;
03895                if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
03896                   /* if thru with dialing after offhook */
03897                   if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
03898                      ast_setstate(ast, AST_STATE_UP);
03899                      p->subs[index].f.frametype = AST_FRAME_CONTROL;
03900                      p->subs[index].f.subclass = AST_CONTROL_ANSWER;
03901                      break;
03902                   } else { /* if to state wait for offhook to dial rest */
03903                      /* we now wait for off hook */
03904                      ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
03905                   }
03906                }
03907                if (ast->_state == AST_STATE_DIALING) {
03908                   if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03909                      ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
03910                   } else if (p->confirmanswer || (!p->dialednone && ((mysig == SIG_EM) || (mysig == SIG_EM_E1) ||  (mysig == SIG_EMWINK) || (mysig == SIG_FEATD) || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF) || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB) || (mysig == SIG_SF) || (mysig == SIG_SFWINK) || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF) || (mysig == SIG_SF_FEATB)))) {
03911                      ast_setstate(ast, AST_STATE_RINGING);
03912                   } else if (!p->answeronpolarityswitch) {
03913                      ast_setstate(ast, AST_STATE_UP);
03914                      p->subs[index].f.frametype = AST_FRAME_CONTROL;
03915                      p->subs[index].f.subclass = AST_CONTROL_ANSWER;
03916                      /* If aops=0 and hops=1, this is necessary */
03917                      p->polarity = POLARITY_REV;
03918                   } else {
03919                      /* Start clean, so we can catch the change to REV polarity when party answers */
03920                      p->polarity = POLARITY_IDLE;
03921                   }
03922                }
03923             }
03924          }
03925          break;
03926       case DAHDI_EVENT_ALARM:
03927 #ifdef HAVE_PRI
03928          if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
03929             /* T309 is not enabled : hangup calls when alarm occurs */
03930             if (p->call) {
03931                if (p->pri && p->pri->pri) {
03932                   if (!pri_grab(p, p->pri)) {
03933                      pri_hangup(p->pri->pri, p->call, -1);
03934                      pri_destroycall(p->pri->pri, p->call);
03935                      p->call = NULL;
03936                      pri_rel(p->pri);
03937                   } else
03938                      ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03939                } else
03940                   ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
03941             }
03942             if (p->owner)
03943                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03944          }
03945          if (p->bearer)
03946             p->bearer->inalarm = 1;
03947          else
03948 #endif
03949          p->inalarm = 1;
03950          res = get_alarms(p);
03951          handle_alarms(p, res);
03952 #ifdef HAVE_LIBPRI
03953          if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
03954             /* fall through intentionally */
03955          } else {
03956             break;
03957          }
03958 #endif
03959       case DAHDI_EVENT_ONHOOK:
03960          if (p->radio) {
03961             p->subs[index].f.frametype = AST_FRAME_CONTROL;
03962             p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
03963             break;
03964          }
03965          if (p->oprmode < 0)
03966          {
03967             if (p->oprmode != -1) break;
03968             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
03969             {
03970                /* Make sure it starts ringing */
03971                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
03972                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
03973                save_conference(p->oprpeer);
03974                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
03975             }
03976             break;
03977          }
03978          switch (p->sig) {
03979          case SIG_FXOLS:
03980          case SIG_FXOGS:
03981          case SIG_FXOKS:
03982             p->onhooktime = time(NULL);
03983             p->msgstate = -1;
03984             /* Check for some special conditions regarding call waiting */
03985             if (index == SUB_REAL) {
03986                /* The normal line was hung up */
03987                if (p->subs[SUB_CALLWAIT].owner) {
03988                   /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
03989                   swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03990                   if (option_verbose > 2) 
03991                      ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
03992                   unalloc_sub(p, SUB_CALLWAIT); 
03993 #if 0
03994                   p->subs[index].needanswer = 0;
03995                   p->subs[index].needringing = 0;
03996 #endif                  
03997                   p->callwaitingrepeat = 0;
03998                   p->cidcwexpire = 0;
03999                   p->owner = NULL;
04000                   /* Don't start streaming audio yet if the incoming call isn't up yet */
04001                   if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
04002                      p->dialing = 1;
04003                   dahdi_ring_phone(p);
04004                } else if (p->subs[SUB_THREEWAY].owner) {
04005                   unsigned int mssinceflash;
04006                   /* Here we have to retain the lock on both the main channel, the 3-way channel, and
04007                      the private structure -- not especially easy or clean */
04008                   while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
04009                      /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
04010                      ast_mutex_unlock(&p->lock);
04011                      DEADLOCK_AVOIDANCE(&ast->lock);
04012                      /* We can grab ast and p in that order, without worry.  We should make sure
04013                         nothing seriously bad has happened though like some sort of bizarre double
04014                         masquerade! */
04015                      ast_mutex_lock(&p->lock);
04016                      if (p->owner != ast) {
04017                         ast_log(LOG_WARNING, "This isn't good...\n");
04018                         return NULL;
04019                      }
04020                   }
04021                   if (!p->subs[SUB_THREEWAY].owner) {
04022                      ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
04023                      return NULL;
04024                   }
04025                   mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
04026                   ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
04027                   if (mssinceflash < MIN_MS_SINCE_FLASH) {
04028                      /* It hasn't been long enough since the last flashook.  This is probably a bounce on 
04029                         hanging up.  Hangup both channels now */
04030                      if (p->subs[SUB_THREEWAY].owner)
04031                         ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
04032                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04033                      ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
04034                      ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04035                   } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
04036                      if (p->transfer) {
04037                         /* In any case this isn't a threeway call anymore */
04038                         p->subs[SUB_REAL].inthreeway = 0;
04039                         p->subs[SUB_THREEWAY].inthreeway = 0;
04040                         /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
04041                         if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
04042                            ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04043                            /* Swap subs and dis-own channel */
04044                            swap_subs(p, SUB_THREEWAY, SUB_REAL);
04045                            p->owner = NULL;
04046                            /* Ring the phone */
04047                            dahdi_ring_phone(p);
04048                         } else {
04049                            if ((res = attempt_transfer(p)) < 0) {
04050                               p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04051                               if (p->subs[SUB_THREEWAY].owner)
04052                                  ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04053                            } else if (res) {
04054                               /* Don't actually hang up at this point */
04055                               if (p->subs[SUB_THREEWAY].owner)
04056                                  ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04057                               break;
04058                            }
04059                         }
04060                      } else {
04061                         p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04062                         if (p->subs[SUB_THREEWAY].owner)
04063                            ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04064                      }
04065                   } else {
04066                      ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04067                      /* Swap subs and dis-own channel */
04068                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
04069                      p->owner = NULL;
04070                      /* Ring the phone */
04071                      dahdi_ring_phone(p);
04072                   }
04073                }
04074             } else {
04075                ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
04076             }
04077             /* Fall through */
04078          default:
04079             dahdi_disable_ec(p);
04080             return NULL;
04081          }
04082          break;
04083       case DAHDI_EVENT_RINGOFFHOOK:
04084          if (p->inalarm) break;
04085          if (p->oprmode < 0)
04086          {
04087             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04088             {
04089                /* Make sure it stops ringing */
04090                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04091                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
04092                restore_conference(p->oprpeer);
04093             }
04094             break;
04095          }
04096          if (p->radio)
04097          {
04098             p->subs[index].f.frametype = AST_FRAME_CONTROL;
04099             p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
04100             break;
04101          }
04102          /* for E911, its supposed to wait for offhook then dial
04103             the second half of the dial string */
04104          if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
04105             c = strchr(p->dialdest, '/');
04106             if (c)
04107                c++;
04108             else
04109                c = p->dialdest;
04110             if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
04111             else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
04112             if (strlen(p->dop.dialstr) > 4) {
04113                memset(p->echorest, 'w', sizeof(p->echorest) - 1);
04114                strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
04115                p->echorest[sizeof(p->echorest) - 1] = '\0';
04116                p->echobreak = 1;
04117                p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
04118             } else
04119                p->echobreak = 0;
04120             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
04121                int saveerr = errno;
04122 
04123                x = DAHDI_ONHOOK;
04124                ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04125                ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
04126                return NULL;
04127                }
04128             p->dialing = 1;
04129             return &p->subs[index].f;
04130          }
04131          switch (p->sig) {
04132          case SIG_FXOLS:
04133          case SIG_FXOGS:
04134          case SIG_FXOKS:
04135             switch (ast->_state) {
04136             case AST_STATE_RINGING:
04137                dahdi_enable_ec(p);
04138                dahdi_train_ec(p);
04139                p->subs[index].f.frametype = AST_FRAME_CONTROL;
04140                p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04141                /* Make sure it stops ringing */
04142                dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
04143                ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
04144                if (p->cidspill) {
04145                   /* Cancel any running CallerID spill */
04146                   free(p->cidspill);
04147                   p->cidspill = NULL;
04148                }
04149                p->dialing = 0;
04150                p->callwaitcas = 0;
04151                if (p->confirmanswer) {
04152                   /* Ignore answer if "confirm answer" is enabled */
04153                   p->subs[index].f.frametype = AST_FRAME_NULL;
04154                   p->subs[index].f.subclass = 0;
04155                } else if (!ast_strlen_zero(p->dop.dialstr)) {
04156                   /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
04157                   res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04158                   if (res < 0) {
04159                      ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04160                      p->dop.dialstr[0] = '\0';
04161                      return NULL;
04162                   } else {
04163                      ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
04164                      p->subs[index].f.frametype = AST_FRAME_NULL;
04165                      p->subs[index].f.subclass = 0;
04166                      p->dialing = 1;
04167                   }
04168                   p->dop.dialstr[0] = '\0';
04169                   ast_setstate(ast, AST_STATE_DIALING);
04170                } else
04171                   ast_setstate(ast, AST_STATE_UP);
04172                return &p->subs[index].f;
04173             case AST_STATE_DOWN:
04174                ast_setstate(ast, AST_STATE_RING);
04175                ast->rings = 1;
04176                p->subs[index].f.frametype = AST_FRAME_CONTROL;
04177                p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
04178                ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
04179                return &p->subs[index].f;
04180             case AST_STATE_UP:
04181                /* Make sure it stops ringing */
04182                dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
04183                /* Okay -- probably call waiting*/
04184                if (ast_bridged_channel(p->owner))
04185                   ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04186                p->subs[index].needunhold = 1;
04187                break;
04188             case AST_STATE_RESERVED:
04189                /* Start up dialtone */
04190                if (has_voicemail(p))
04191                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
04192                else
04193                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
04194                break;
04195             default:
04196                ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
04197             }
04198             break;
04199          case SIG_FXSLS:
04200          case SIG_FXSGS:
04201          case SIG_FXSKS:
04202             if (ast->_state == AST_STATE_RING) {
04203                p->ringt = p->ringt_base;
04204             }
04205 
04206             /* Fall through */
04207          case SIG_EM:
04208          case SIG_EM_E1:
04209          case SIG_EMWINK:
04210          case SIG_FEATD:
04211          case SIG_FEATDMF:
04212          case SIG_FEATDMF_TA:
04213          case SIG_E911:
04214          case SIG_FGC_CAMA:
04215          case SIG_FGC_CAMAMF:
04216          case SIG_FEATB:
04217          case SIG_SF:
04218          case SIG_SFWINK:
04219          case SIG_SF_FEATD:
04220          case SIG_SF_FEATDMF:
04221          case SIG_SF_FEATB:
04222             if (ast->_state == AST_STATE_PRERING)
04223                ast_setstate(ast, AST_STATE_RING);
04224             if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
04225                if (option_debug)
04226                   ast_log(LOG_DEBUG, "Ring detected\n");
04227                p->subs[index].f.frametype = AST_FRAME_CONTROL;
04228                p->subs[index].f.subclass = AST_CONTROL_RING;
04229             } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
04230                if (option_debug)
04231                   ast_log(LOG_DEBUG, "Line answered\n");
04232                if (p->confirmanswer) {
04233                   p->subs[index].f.frametype = AST_FRAME_NULL;
04234                   p->subs[index].f.subclass = 0;
04235                } else {
04236                   p->subs[index].f.frametype = AST_FRAME_CONTROL;
04237                   p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04238                   ast_setstate(ast, AST_STATE_UP);
04239                }
04240             } else if (ast->_state != AST_STATE_RING)
04241                ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
04242             break;
04243          default:
04244             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
04245          }
04246          break;
04247 #ifdef DAHDI_EVENT_RINGBEGIN
04248       case DAHDI_EVENT_RINGBEGIN:
04249          switch (p->sig) {
04250          case SIG_FXSLS:
04251          case SIG_FXSGS:
04252          case SIG_FXSKS:
04253             if (ast->_state == AST_STATE_RING) {
04254                p->ringt = p->ringt_base;
04255             }
04256             break;
04257          }
04258          break;
04259 #endif         
04260       case DAHDI_EVENT_RINGEROFF:
04261          if (p->inalarm) break;
04262          if ((p->radio || (p->oprmode < 0))) break;
04263          ast->rings++;
04264          if ((ast->rings > p->cidrings) && (p->cidspill)) {
04265             ast_log(LOG_WARNING, "Didn't finish Caller-ID spill.  Cancelling.\n");
04266             free(p->cidspill);
04267             p->cidspill = NULL;
04268             p->callwaitcas = 0;
04269          }
04270          p->subs[index].f.frametype = AST_FRAME_CONTROL;
04271          p->subs[index].f.subclass = AST_CONTROL_RINGING;
04272          break;
04273       case DAHDI_EVENT_RINGERON:
04274          break;
04275       case DAHDI_EVENT_NOALARM:
04276          p->inalarm = 0;
04277 #ifdef HAVE_PRI
04278          /* Extremely unlikely but just in case */
04279          if (p->bearer)
04280             p->bearer->inalarm = 0;
04281 #endif            
04282          if (!p->unknown_alarm) {
04283             ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
04284             manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
04285                "Channel: %d\r\n", p->channel);
04286          } else {
04287             p->unknown_alarm = 0;
04288          }
04289          break;
04290       case DAHDI_EVENT_WINKFLASH:
04291          if (p->inalarm) break;
04292          if (p->radio) break;
04293          if (p->oprmode < 0) break;
04294          if (p->oprmode > 1)
04295          {
04296             struct dahdi_params par;
04297 
04298             if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
04299             {
04300                if (!par.rxisoffhook)
04301                {
04302                   /* Make sure it stops ringing */
04303                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04304                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
04305                   save_conference(p);
04306                   tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04307                }
04308             }
04309             break;
04310          }
04311          /* Remember last time we got a flash-hook */
04312          gettimeofday(&p->flashtime, NULL);
04313          switch (mysig) {
04314          case SIG_FXOLS:
04315          case SIG_FXOGS:
04316          case SIG_FXOKS:
04317             ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
04318                index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
04319             p->callwaitcas = 0;
04320 
04321             if (index != SUB_REAL) {
04322                ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
04323                goto winkflashdone;
04324             }
04325             
04326             if (p->subs[SUB_CALLWAIT].owner) {
04327                /* Swap to call-wait */
04328                swap_subs(p, SUB_REAL, SUB_CALLWAIT);
04329                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04330                p->owner = p->subs[SUB_REAL].owner;
04331                ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
04332                if (p->owner->_state == AST_STATE_RINGING) {
04333                   ast_setstate(p->owner, AST_STATE_UP);
04334                   p->subs[SUB_REAL].needanswer = 1;
04335                }
04336                p->callwaitingrepeat = 0;
04337                p->cidcwexpire = 0;
04338                /* Start music on hold if appropriate */
04339                if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
04340                   ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
04341                      S_OR(p->mohsuggest, NULL),
04342                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04343                }
04344                p->subs[SUB_CALLWAIT].needhold = 1;
04345                if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04346                   ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
04347                      S_OR(p->mohsuggest, NULL),
04348                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04349                }
04350                p->subs[SUB_REAL].needunhold = 1;
04351             } else if (!p->subs[SUB_THREEWAY].owner) {
04352                char cid_num[256];
04353                char cid_name[256];
04354 
04355                if (!p->threewaycalling) {
04356                   /* Just send a flash if no 3-way calling */
04357                   p->subs[SUB_REAL].needflash = 1;
04358                   goto winkflashdone;
04359                } else if (!check_for_conference(p)) {
04360                   if (p->dahditrcallerid && p->owner) {
04361                      if (p->owner->cid.cid_num)
04362                         ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
04363                      if (p->owner->cid.cid_name)
04364                         ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
04365                   }
04366                   /* XXX This section needs much more error checking!!! XXX */
04367                   /* Start a 3-way call if feasible */
04368                   if (!((ast->pbx) ||
04369                         (ast->_state == AST_STATE_UP) ||
04370                         (ast->_state == AST_STATE_RING))) {
04371                      ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
04372                         goto winkflashdone;
04373                   }
04374                   if (alloc_sub(p, SUB_THREEWAY)) {
04375                      ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
04376                      goto winkflashdone;
04377                   }
04378                   /* Make new channel */
04379                   chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
04380                   if (p->dahditrcallerid) {
04381                      if (!p->origcid_num)
04382                         p->origcid_num = ast_strdup(p->cid_num);
04383                      if (!p->origcid_name)
04384                         p->origcid_name = ast_strdup(p->cid_name);
04385                      ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
04386                      ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
04387                   }
04388                   /* Swap things around between the three-way and real call */
04389                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
04390                   /* Disable echo canceller for better dialing */
04391                   dahdi_disable_ec(p);
04392                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
04393                   if (res)
04394                      ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
04395                   p->owner = chan;
04396                   pthread_attr_init(&attr);
04397                   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04398                   if (!chan) {
04399                      ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
04400                   } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
04401                      ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
04402                      res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
04403                      dahdi_enable_ec(p);
04404                      ast_hangup(chan);
04405                   } else {
04406                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
04407                      int way3bridge = 0, cdr3way = 0;
04408                      
04409                      if (!other) {
04410                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
04411                      } else
04412                         way3bridge = 1;
04413                      
04414                      if (p->subs[SUB_THREEWAY].owner->cdr)
04415                         cdr3way = 1;
04416                      
04417                      if (option_verbose > 2) 
04418                         ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
04419                      /* Start music on hold if appropriate */
04420                      if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04421                         ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
04422                            S_OR(p->mohsuggest, NULL),
04423                            !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04424                      }
04425                      p->subs[SUB_THREEWAY].needhold = 1;
04426                   }
04427                   pthread_attr_destroy(&attr);
04428                }
04429             } else {
04430                /* Already have a 3 way call */
04431                if (p->subs[SUB_THREEWAY].inthreeway) {
04432                   /* Call is already up, drop the last person */
04433                   if (option_debug)
04434                      ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
04435                   /* If the primary call isn't answered yet, use it */
04436                   if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
04437                      /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
04438                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
04439                      p->owner = p->subs[SUB_REAL].owner;
04440                   }
04441                   /* Drop the last call and stop the conference */
04442                   if (option_verbose > 2)
04443                      ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
04444                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04445                   p->subs[SUB_REAL].inthreeway = 0;
04446                   p->subs[SUB_THREEWAY].inthreeway = 0;
04447                } else {
04448                   /* Lets see what we're up to */
04449                   if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 
04450                       (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
04451                      int otherindex = SUB_THREEWAY;
04452                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
04453                      int way3bridge = 0, cdr3way = 0;
04454                      
04455                      if (!other) {
04456                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
04457                      } else
04458                         way3bridge = 1;
04459                      
04460                      if (p->subs[SUB_THREEWAY].owner->cdr)
04461                         cdr3way = 1;
04462 
04463                      if (option_verbose > 2)
04464                         ast_verbose(VERBOSE_PREFIX_3 "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
04465                      /* Put them in the threeway, and flip */
04466                      p->subs[SUB_THREEWAY].inthreeway = 1;
04467                      p->subs[SUB_REAL].inthreeway = 1;
04468                      if (ast->_state == AST_STATE_UP) {
04469                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
04470                         otherindex = SUB_REAL;
04471                      }
04472                      if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
04473                         ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
04474                      p->subs[otherindex].needunhold = 1;
04475                      p->owner = p->subs[SUB_REAL].owner;
04476                      if (ast->_state == AST_STATE_RINGING) {
04477                         ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
04478                         res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04479                         res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04480                      }
04481                   } else {
04482                      if (option_verbose > 2)
04483                         ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
04484                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
04485                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04486                      p->owner = p->subs[SUB_REAL].owner;
04487                      if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
04488                         ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04489                      p->subs[SUB_REAL].needunhold = 1;
04490                      dahdi_enable_ec(p);
04491                   }
04492                      
04493                }
04494             }
04495          winkflashdone:              
04496             update_conf(p);
04497             break;
04498          case SIG_EM:
04499          case SIG_EM_E1:
04500          case SIG_EMWINK:
04501          case SIG_FEATD:
04502          case SIG_SF:
04503          case SIG_SFWINK:
04504          case SIG_SF_FEATD:
04505          case SIG_FXSLS:
04506          case SIG_FXSGS:
04507             if (p->dialing)
04508                ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
04509             else
04510                ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
04511             break;
04512          case SIG_FEATDMF_TA:
04513             switch (p->whichwink) {
04514             case 0:
04515                ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
04516                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
04517                break;
04518             case 1:
04519                ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
04520                break;
04521             case 2:
04522                ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
04523                return NULL;
04524             }
04525             p->whichwink++;
04526             /* Fall through */
04527          case SIG_FEATDMF:
04528          case SIG_E911:
04529          case SIG_FGC_CAMAMF:
04530          case SIG_FGC_CAMA:
04531          case SIG_FEATB:
04532          case SIG_SF_FEATDMF:
04533          case SIG_SF_FEATB:
04534             /* FGD MF *Must* wait for wink */
04535             if (!ast_strlen_zero(p->dop.dialstr)) {
04536                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04537                if (res < 0) {
04538                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04539                   p->dop.dialstr[0] = '\0';
04540                   return NULL;
04541                } else 
04542                   ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
04543             }
04544             p->dop.dialstr[0] = '\0';
04545             break;
04546          default:
04547             ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
04548          }
04549          break;
04550       case DAHDI_EVENT_HOOKCOMPLETE:
04551          if (p->inalarm) break;
04552          if ((p->radio || (p->oprmode < 0))) break;
04553          switch (mysig) {
04554          case SIG_FXSLS:  /* only interesting for FXS */
04555          case SIG_FXSGS:
04556          case SIG_FXSKS:
04557          case SIG_EM:
04558          case SIG_EM_E1:
04559          case SIG_EMWINK:
04560          case SIG_FEATD:
04561          case SIG_SF:
04562          case SIG_SFWINK:
04563          case SIG_SF_FEATD:
04564             if (!ast_strlen_zero(p->dop.dialstr)) {
04565                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04566                if (res < 0) {
04567                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04568                   p->dop.dialstr[0] = '\0';
04569                   return NULL;
04570                } else 
04571                   ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
04572             }
04573             p->dop.dialstr[0] = '\0';
04574             p->dop.op = DAHDI_DIAL_OP_REPLACE;
04575             break;
04576          case SIG_FEATDMF:
04577          case SIG_FEATDMF_TA:
04578          case SIG_E911:
04579          case SIG_FGC_CAMA:
04580          case SIG_FGC_CAMAMF:
04581          case SIG_FEATB:
04582          case SIG_SF_FEATDMF:
04583          case SIG_SF_FEATB:
04584             ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
04585             break;
04586          default:
04587             break;
04588          }
04589          break;
04590       case DAHDI_EVENT_POLARITY:
04591          /*
04592           * If we get a Polarity Switch event, check to see
04593           * if we should change the polarity state and
04594           * mark the channel as UP or if this is an indication
04595           * of remote end disconnect.
04596           */
04597          if (p->polarity == POLARITY_IDLE) {
04598             p->polarity = POLARITY_REV;
04599             if (p->answeronpolarityswitch &&
04600                 ((ast->_state == AST_STATE_DIALING) ||
04601                 (ast->_state == AST_STATE_RINGING))) {
04602                ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
04603                ast_setstate(p->owner, AST_STATE_UP);
04604                if (p->hanguponpolarityswitch) {
04605                   gettimeofday(&p->polaritydelaytv, NULL);
04606                }
04607             } else
04608                ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
04609          } 
04610          /* Removed else statement from here as it was preventing hangups from ever happening*/
04611          /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
04612          if (p->hanguponpolarityswitch &&
04613             (p->polarityonanswerdelay > 0) &&
04614                 (p->polarity == POLARITY_REV) &&
04615             ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
04616                                 /* Added log_debug information below to provide a better indication of what is going on */
04617             ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
04618          
04619             if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
04620                ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
04621                ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
04622                p->polarity = POLARITY_IDLE;
04623             } else {
04624                ast_log(LOG_DEBUG, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
04625             }
04626          } else {
04627             p->polarity = POLARITY_IDLE;
04628             ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
04629          }
04630                         /* Added more log_debug information below to provide a better indication of what is going on */
04631          ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
04632          break;
04633       default:
04634          ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
04635    }
04636    return &p->subs[index].f;
04637 }

static int dahdi_hangup ( struct ast_channel ast  )  [static]

Definition at line 2513 of file chan_dahdi.c.

References ast_channel::_state, ast_bridged_channel(), ast_channel_setoption(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_dsp_digitmode(), ast_dsp_free(), ast_log(), ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), AST_OPTION_AUDIO_MODE, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, ast_queue_control(), ast_queue_control_data(), AST_STATE_RESERVED, AST_STATE_UP, ast_strlen_zero(), ast_verbose(), dahdi_pvt::callwaitcas, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingrepeat, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cidcwexpire, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_confmute(), dahdi_disable_ec(), dahdi_get_index(), dahdi_set_hook(), dahdi_setlinear(), dahdi_pvt::destroy, destroy_channel(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::didtdd, dahdi_pvt::digital, dahdi_pvt::distinctivering, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, dahdi_pvt::dtmfrelax, errno, dahdi_pvt::exten, dahdi_pvt::faxhandled, free, dahdi_pvt::guardtime, ast_channel::hangupcause, dahdi_pvt::hidecallerid, iflist, dahdi_pvt::ignoredtmf, dahdi_subchannel::inthreeway, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mohsuggest, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcallerid, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needringing, dahdi_pvt::next, dahdi_pvt::onhooktime, dahdi_pvt::oprmode, option_debug, option_verbose, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_getvar_helper(), dahdi_pvt::permcallwaiting, dahdi_pvt::permhidecallerid, dahdi_pvt::polarity, POLARITY_IDLE, dahdi_pvt::prev, dahdi_pvt::pulsedial, dahdi_pvt::radio, dahdi_pvt::rdnis, reset_conf(), restart_monitor(), dahdi_pvt::restartpending, restore_gains(), dahdi_pvt::ringt, S_OR, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, dahdi_pvt::span, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, unalloc_sub(), update_conf(), and VERBOSE_PREFIX_3.

02514 {
02515    int res;
02516    int index,x, law;
02517    /*static int restore_gains(struct dahdi_pvt *p);*/
02518    struct dahdi_pvt *p = ast->tech_pvt;
02519    struct dahdi_pvt *tmp = NULL;
02520    struct dahdi_pvt *prev = NULL;
02521    struct dahdi_params par;
02522 
02523    if (option_debug)
02524       ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
02525    if (!ast->tech_pvt) {
02526       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
02527       return 0;
02528    }
02529    
02530    ast_mutex_lock(&p->lock);
02531    
02532    index = dahdi_get_index(ast, p, 1);
02533 
02534    if (p->sig == SIG_PRI) {
02535       x = 1;
02536       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
02537    }
02538 
02539    x = 0;
02540    dahdi_confmute(p, 0);
02541    restore_gains(p);
02542    if (p->origcid_num) {
02543       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
02544       free(p->origcid_num);
02545       p->origcid_num = NULL;
02546    }  
02547    if (p->origcid_name) {
02548       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
02549       free(p->origcid_name);
02550       p->origcid_name = NULL;
02551    }  
02552    if (p->dsp)
02553       ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
02554    if (p->exten)
02555       p->exten[0] = '\0';
02556 
02557    if (option_debug)
02558       ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
02559       p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
02560    p->ignoredtmf = 0;
02561    
02562    if (index > -1) {
02563       /* Real channel, do some fixup */
02564       p->subs[index].owner = NULL;
02565       p->subs[index].needanswer = 0;
02566       p->subs[index].needflash = 0;
02567       p->subs[index].needringing = 0;
02568       p->subs[index].needbusy = 0;
02569       p->subs[index].needcongestion = 0;
02570       p->subs[index].linear = 0;
02571       p->subs[index].needcallerid = 0;
02572       p->polarity = POLARITY_IDLE;
02573       dahdi_setlinear(p->subs[index].dfd, 0);
02574       if (index == SUB_REAL) {
02575          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
02576             ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
02577             if (p->subs[SUB_CALLWAIT].inthreeway) {
02578                /* We had flipped over to answer a callwait and now it's gone */
02579                ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
02580                /* Move to the call-wait, but un-own us until they flip back. */
02581                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02582                unalloc_sub(p, SUB_CALLWAIT);
02583                p->owner = NULL;
02584             } else {
02585                /* The three way hung up, but we still have a call wait */
02586                ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
02587                swap_subs(p, SUB_THREEWAY, SUB_REAL);
02588                unalloc_sub(p, SUB_THREEWAY);
02589                if (p->subs[SUB_REAL].inthreeway) {
02590                   /* This was part of a three way call.  Immediately make way for
02591                      another call */
02592                   ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02593                   p->owner = p->subs[SUB_REAL].owner;
02594                } else {
02595                   /* This call hasn't been completed yet...  Set owner to NULL */
02596                   ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02597                   p->owner = NULL;
02598                }
02599                p->subs[SUB_REAL].inthreeway = 0;
02600             }
02601          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
02602             /* Move to the call-wait and switch back to them. */
02603             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02604             unalloc_sub(p, SUB_CALLWAIT);
02605             p->owner = p->subs[SUB_REAL].owner;
02606             if (p->owner->_state != AST_STATE_UP)
02607                p->subs[SUB_REAL].needanswer = 1;
02608             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
02609                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
02610          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
02611             swap_subs(p, SUB_THREEWAY, SUB_REAL);
02612             unalloc_sub(p, SUB_THREEWAY);
02613             if (p->subs[SUB_REAL].inthreeway) {
02614                /* This was part of a three way call.  Immediately make way for
02615                   another call */
02616                ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02617                p->owner = p->subs[SUB_REAL].owner;
02618             } else {
02619                /* This call hasn't been completed yet...  Set owner to NULL */
02620                ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02621                p->owner = NULL;
02622             }
02623             p->subs[SUB_REAL].inthreeway = 0;
02624          }
02625       } else if (index == SUB_CALLWAIT) {
02626          /* Ditch the holding callwait call, and immediately make it availabe */
02627          if (p->subs[SUB_CALLWAIT].inthreeway) {
02628             /* This is actually part of a three way, placed on hold.  Place the third part
02629                on music on hold now */
02630             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
02631                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 
02632                   S_OR(p->mohsuggest, NULL),
02633                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02634             }
02635             p->subs[SUB_THREEWAY].inthreeway = 0;
02636             /* Make it the call wait now */
02637             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
02638             unalloc_sub(p, SUB_THREEWAY);
02639          } else
02640             unalloc_sub(p, SUB_CALLWAIT);
02641       } else if (index == SUB_THREEWAY) {
02642          if (p->subs[SUB_CALLWAIT].inthreeway) {
02643             /* The other party of the three way call is currently in a call-wait state.
02644                Start music on hold for them, and take the main guy out of the third call */
02645             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
02646                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 
02647                   S_OR(p->mohsuggest, NULL),
02648                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02649             }
02650             p->subs[SUB_CALLWAIT].inthreeway = 0;
02651          }
02652          p->subs[SUB_REAL].inthreeway = 0;
02653          /* If this was part of a three way call index, let us make
02654             another three way call */
02655          unalloc_sub(p, SUB_THREEWAY);
02656       } else {
02657          /* This wasn't any sort of call, but how are we an index? */
02658          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
02659       }
02660    }
02661 
02662    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
02663       p->owner = NULL;
02664       p->ringt = 0;
02665       p->distinctivering = 0;
02666       p->confirmanswer = 0;
02667       p->cidrings = 1;
02668       p->outgoing = 0;
02669       p->digital = 0;
02670       p->faxhandled = 0;
02671       p->pulsedial = 0;
02672       p->onhooktime = time(NULL);
02673 #ifdef HAVE_PRI
02674       p->proceeding = 0;
02675       p->progress = 0;
02676       p->alerting = 0;
02677       p->setup_ack = 0;
02678 #endif      
02679       if (p->dsp) {
02680          ast_dsp_free(p->dsp);
02681          p->dsp = NULL;
02682       }
02683 
02684       law = DAHDI_LAW_DEFAULT;
02685       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02686       if (res < 0) 
02687          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02688       /* Perform low level hangup if no owner left */
02689 #ifdef HAVE_PRI
02690       if (p->pri) {
02691 #ifdef SUPPORT_USERUSER
02692          const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
02693 #endif
02694 
02695          /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
02696          if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
02697             if (!pri_grab(p, p->pri)) {
02698                if (p->alreadyhungup) {
02699                   ast_log(LOG_DEBUG, "Already hungup...  Calling hangup once, and clearing call\n");
02700 
02701 #ifdef SUPPORT_USERUSER
02702                   pri_call_set_useruser(p->call, useruser);
02703 #endif
02704 
02705                   pri_hangup(p->pri->pri, p->call, -1);
02706                   p->call = NULL;
02707                   if (p->bearer) 
02708                      p->bearer->call = NULL;
02709                } else {
02710                   const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
02711                   int icause = ast->hangupcause ? ast->hangupcause : -1;
02712                   ast_log(LOG_DEBUG, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
02713 
02714 #ifdef SUPPORT_USERUSER
02715                   pri_call_set_useruser(p->call, useruser);
02716 #endif
02717 
02718                   p->alreadyhungup = 1;
02719                   if (p->bearer)
02720                      p->bearer->alreadyhungup = 1;
02721                   if (cause) {
02722                      if (atoi(cause))
02723                         icause = atoi(cause);
02724                   }
02725                   pri_hangup(p->pri->pri, p->call, icause);
02726                }
02727                if (res < 0) 
02728                   ast_log(LOG_WARNING, "pri_disconnect failed\n");
02729                pri_rel(p->pri);        
02730             } else {
02731                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
02732                res = -1;
02733             }
02734          } else {
02735             if (p->bearer)
02736                ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
02737             p->call = NULL;
02738             res = 0;
02739          }
02740       }
02741 #endif
02742       if (p->sig && (p->sig != SIG_PRI))
02743          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
02744       if (res < 0) {
02745          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
02746       }
02747       switch (p->sig) {
02748       case SIG_FXOGS:
02749       case SIG_FXOLS:
02750       case SIG_FXOKS:
02751          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02752          if (!res) {
02753 #if 0
02754             ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
02755 #endif
02756             /* If they're off hook, try playing congestion */
02757             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
02758                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
02759             else
02760                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
02761          }
02762          break;
02763       case SIG_FXSGS:
02764       case SIG_FXSLS:
02765       case SIG_FXSKS:
02766          /* Make sure we're not made available for at least two seconds assuming
02767             we were actually used for an inbound or outbound call. */
02768          if (ast->_state != AST_STATE_RESERVED) {
02769             time(&p->guardtime);
02770             p->guardtime += 2;
02771          }
02772          break;
02773       default:
02774          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
02775       }
02776       if (p->cidspill)
02777          free(p->cidspill);
02778       if (p->sig)
02779          dahdi_disable_ec(p);
02780       x = 0;
02781       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
02782       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
02783       p->didtdd = 0;
02784       p->cidspill = NULL;
02785       p->callwaitcas = 0;
02786       p->callwaiting = p->permcallwaiting;
02787       p->hidecallerid = p->permhidecallerid;
02788       p->dialing = 0;
02789       p->rdnis[0] = '\0';
02790       update_conf(p);
02791       reset_conf(p);
02792       /* Restore data mode */
02793       if (p->sig == SIG_PRI) {
02794          x = 0;
02795          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
02796       }
02797 #ifdef HAVE_PRI
02798       if (p->bearer) {
02799          ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
02800          /* Free up the bearer channel as well, and
02801             don't use its file descriptor anymore */
02802          update_conf(p->bearer);
02803          reset_conf(p->bearer);
02804          p->bearer->owner = NULL;
02805          p->bearer->realcall = NULL;
02806          p->bearer = NULL;
02807          p->subs[SUB_REAL].dfd = -1;
02808          p->pri = NULL;
02809       }
02810 #endif
02811       if (num_restart_pending == 0)
02812          restart_monitor();
02813    }
02814 
02815    p->callwaitingrepeat = 0;
02816    p->cidcwexpire = 0;
02817    p->oprmode = 0;
02818    ast->tech_pvt = NULL;
02819    ast_mutex_unlock(&p->lock);
02820    ast_module_unref(ast_module_info->self);
02821    if (option_verbose > 2) 
02822       ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
02823 
02824    ast_mutex_lock(&iflock);
02825 
02826    if (p->restartpending) {
02827       num_restart_pending--;
02828    }
02829 
02830    tmp = iflist;
02831    prev = NULL;
02832    if (p->destroy) {
02833       while (tmp) {
02834          if (tmp == p) {
02835             destroy_channel(prev, tmp, 0);
02836             break;
02837          } else {
02838             prev = tmp;
02839             tmp = tmp->next;
02840          }
02841       }
02842    }
02843    ast_mutex_unlock(&iflock);
02844    return 0;
02845 }

static int dahdi_indicate ( struct ast_channel chan,
int  condition,
const void *  data,
size_t  datalen 
) [static]

Definition at line 5153 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, AST_CAUSE_CONGESTION, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_USER_BUSY, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_SOFTHANGUP_DEV, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, dahdi_get_index(), dahdi_set_hook(), dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::dop, errno, func, ast_channel::hangupcause, ISTRUNK, dahdi_pvt::lock, LOG_DEBUG, dahdi_pvt::mohinterpret, option_debug, dahdi_pvt::outgoing, dahdi_pvt::priindication_oob, dahdi_pvt::radio, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, dahdi_pvt::span, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

05154 {
05155    struct dahdi_pvt *p = chan->tech_pvt;
05156    int res=-1;
05157    int index;
05158    int func = DAHDI_FLASH;
05159    ast_mutex_lock(&p->lock);
05160    index = dahdi_get_index(chan, p, 0);
05161    if (option_debug)
05162       ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
05163    if (index == SUB_REAL) {
05164       switch (condition) {
05165       case AST_CONTROL_BUSY:
05166 #ifdef HAVE_PRI
05167          if (p->priindication_oob && p->sig == SIG_PRI) {
05168             chan->hangupcause = AST_CAUSE_USER_BUSY;
05169             chan->_softhangup |= AST_SOFTHANGUP_DEV;
05170             res = 0;
05171          } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05172             if (p->pri->pri) {      
05173                if (!pri_grab(p, p->pri)) {
05174                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05175                   pri_rel(p->pri);
05176                }
05177                else
05178                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05179             }
05180             p->progress = 1;
05181             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
05182          } else
05183 #endif
05184             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
05185          break;
05186       case AST_CONTROL_RINGING:
05187 #ifdef HAVE_PRI
05188          if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
05189             if (p->pri->pri) {      
05190                if (!pri_grab(p, p->pri)) {
05191                   pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05192                   pri_rel(p->pri);
05193                }
05194                else
05195                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05196             }
05197             p->alerting = 1;
05198          }
05199 #endif
05200          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
05201          if (chan->_state != AST_STATE_UP) {
05202             if ((chan->_state != AST_STATE_RING) ||
05203                ((p->sig != SIG_FXSKS) &&
05204                 (p->sig != SIG_FXSLS) &&
05205                 (p->sig != SIG_FXSGS)))
05206                ast_setstate(chan, AST_STATE_RINGING);
05207          }
05208          break;
05209       case AST_CONTROL_PROCEEDING:
05210          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
05211 #ifdef HAVE_PRI
05212          if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05213             if (p->pri->pri) {      
05214                if (!pri_grab(p, p->pri)) {
05215                   pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05216                   pri_rel(p->pri);
05217                }
05218                else
05219                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05220             }
05221             p->proceeding = 1;
05222          }
05223 #endif
05224          /* don't continue in ast_indicate */
05225          res = 0;
05226          break;
05227       case AST_CONTROL_PROGRESS:
05228          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
05229 #ifdef HAVE_PRI
05230          p->digital = 0;   /* Digital-only calls isn't allows any inband progress messages */
05231          if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05232             if (p->pri->pri) {      
05233                if (!pri_grab(p, p->pri)) {
05234                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05235                   pri_rel(p->pri);
05236                }
05237                else
05238                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05239             }
05240             p->progress = 1;
05241          }
05242 #endif
05243          /* don't continue in ast_indicate */
05244          res = 0;
05245          break;
05246       case AST_CONTROL_CONGESTION:
05247          chan->hangupcause = AST_CAUSE_CONGESTION;
05248 #ifdef HAVE_PRI
05249          if (p->priindication_oob && p->sig == SIG_PRI) {
05250             chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
05251             chan->_softhangup |= AST_SOFTHANGUP_DEV;
05252             res = 0;
05253          } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05254             if (p->pri) {     
05255                if (!pri_grab(p, p->pri)) {
05256                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05257                   pri_rel(p->pri);
05258                } else
05259                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05260             }
05261             p->progress = 1;
05262             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05263          } else
05264 #endif
05265             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05266          break;
05267       case AST_CONTROL_HOLD:
05268 #ifdef HAVE_PRI
05269          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05270             if (!pri_grab(p, p->pri)) {
05271                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
05272                pri_rel(p->pri);
05273             } else
05274                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
05275          } else
05276 #endif
05277             ast_moh_start(chan, data, p->mohinterpret);
05278          break;
05279       case AST_CONTROL_UNHOLD:
05280 #ifdef HAVE_PRI
05281          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05282             if (!pri_grab(p, p->pri)) {
05283                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
05284                pri_rel(p->pri);
05285             } else
05286                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
05287          } else
05288 #endif
05289             ast_moh_stop(chan);
05290          break;
05291       case AST_CONTROL_RADIO_KEY:
05292          if (p->radio) 
05293              res =  dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05294          res = 0;
05295          break;
05296       case AST_CONTROL_RADIO_UNKEY:
05297          if (p->radio)
05298              res =  dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
05299          res = 0;
05300          break;
05301       case AST_CONTROL_FLASH:
05302          /* flash hookswitch */
05303          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
05304             /* Clear out the dial buffer */
05305             p->dop.dialstr[0] = '\0';
05306             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
05307                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
05308                   chan->name, strerror(errno));
05309             } else
05310                res = 0;
05311          } else
05312             res = 0;
05313          break;
05314       case AST_CONTROL_SRCUPDATE:
05315          res = 0;
05316          break;
05317       case -1:
05318          res = tone_zone_play_tone(p->subs[index].dfd, -1);
05319          break;
05320       }
05321    } else
05322       res = 0;
05323    ast_mutex_unlock(&p->lock);
05324    return res;
05325 }

static void dahdi_link ( struct dahdi_pvt slave,
struct dahdi_pvt master 
) [static]

Definition at line 3192 of file chan_dahdi.c.

References ast_log(), LOG_WARNING, and master.

Referenced by dahdi_bridge().

03192                                                                           {
03193    int x;
03194    if (!slave || !master) {
03195       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
03196       return;
03197    }
03198    for (x = 0; x < MAX_SLAVES; x++) {
03199       if (!master->slaves[x]) {
03200          master->slaves[x] = slave;
03201          break;
03202       }
03203    }
03204    if (x >= MAX_SLAVES) {
03205       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
03206       master->slaves[MAX_SLAVES - 1] = slave;
03207    }
03208    if (slave->master) 
03209       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
03210    slave->master = master;
03211    
03212    ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
03213 }

static struct ast_channel * dahdi_new ( struct dahdi_pvt ,
int  ,
int  ,
int  ,
int  ,
int   
) [static]

Definition at line 5327 of file chan_dahdi.c.

References accountcode, dahdi_pvt::accountcode, dahdi_pvt::adsi, ast_channel::adsicpe, ast_channel::amaflags, dahdi_pvt::amaflags, AST_ADSI_UNAVAILABLE, ast_channel_alloc(), ast_dsp_digitmode(), ast_dsp_new(), ast_dsp_set_busy_compare(), ast_dsp_set_busy_count(), ast_dsp_set_busy_pattern(), ast_dsp_set_call_progress_zone(), ast_dsp_set_features(), ast_dsp_set_threshold(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_random(), ast_safe_string_alloc(), AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_transfercapability2str(), dahdi_pvt::busycompare, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::call_forward, dahdi_pvt::callgroup, ast_channel::callgroup, dahdi_pvt::callingpres, dahdi_pvt::callprogress, CANBUSYDETECT, CANPROGRESSDETECT, CHAN_PSEUDO, chan_tech, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, dahdi_pvt::cid_name, dahdi_pvt::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, dahdi_pvt::cid_ton, ast_callerid::cid_ton, ast_channel::context, dahdi_pvt::context, dahdi_chan_name, dahdi_chan_name_len, dahdi_confmute(), dahdi_setlinear(), dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::dnid, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, DSP_PROGRESS_TALK, dahdi_pvt::dtmfrelax, errno, ast_channel::exten, dahdi_pvt::exten, dahdi_pvt::fake_event, ast_channel::fds, free, global_jbconf, dahdi_pvt::hardwaredtmf, language, dahdi_pvt::language, dahdi_subchannel::linear, LOG_DEBUG, ast_channel::nativeformats, NEED_MFDETECT, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::pickupgroup, ast_channel::pickupgroup, PRI_TRANS_CAP_DIGITAL, ast_channel::rawreadformat, ast_channel::rawwriteformat, dahdi_pvt::rdnis, ast_channel::readformat, ast_channel::rings, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSKS, SIG_PRI, dahdi_pvt::silencethreshold, SUB_REAL, dahdi_pvt::subs, ast_channel::tech, ast_channel::tech_pvt, ast_channel::transfercapability, and ast_channel::writeformat.

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

05328 {
05329    struct ast_channel *tmp;
05330    int deflaw;
05331    int res;
05332    int x,y;
05333    int features;
05334    char *b2 = NULL;
05335    struct dahdi_params ps;
05336    char chanprefix[*dahdi_chan_name_len + 4];
05337 
05338    if (i->subs[index].owner) {
05339       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
05340       return NULL;
05341    }
05342    y = 1;
05343    do {
05344       if (b2)
05345          free(b2);
05346 #ifdef HAVE_PRI
05347       if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
05348          b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
05349       else
05350 #endif
05351       if (i->channel == CHAN_PSEUDO)
05352          b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
05353       else  
05354          b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
05355       for (x = 0; x < 3; x++) {
05356          if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6)))
05357             break;
05358       }
05359       y++;
05360    } while (x < 3);
05361    strcpy(chanprefix, dahdi_chan_name);
05362    strcat(chanprefix, "/%s");
05363    tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
05364    if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */
05365       free(b2);
05366    if (!tmp)
05367       return NULL;
05368    tmp->tech = chan_tech;
05369    ps.channo = i->channel;
05370    res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
05371    if (res) {
05372       ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
05373       ps.curlaw = DAHDI_LAW_MULAW;
05374    }
05375    if (ps.curlaw == DAHDI_LAW_ALAW)
05376       deflaw = AST_FORMAT_ALAW;
05377    else
05378       deflaw = AST_FORMAT_ULAW;
05379    if (law) {
05380       if (law == DAHDI_LAW_ALAW)
05381          deflaw = AST_FORMAT_ALAW;
05382       else
05383          deflaw = AST_FORMAT_ULAW;
05384    }
05385    tmp->fds[0] = i->subs[index].dfd;
05386    tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
05387    /* Start out assuming ulaw since it's smaller :) */
05388    tmp->rawreadformat = deflaw;
05389    tmp->readformat = deflaw;
05390    tmp->rawwriteformat = deflaw;
05391    tmp->writeformat = deflaw;
05392    i->subs[index].linear = 0;
05393    dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
05394    features = 0;
05395    if (index == SUB_REAL) {
05396       if (i->busydetect && CANBUSYDETECT(i))
05397          features |= DSP_FEATURE_BUSY_DETECT;
05398       if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
05399          features |= DSP_FEATURE_CALL_PROGRESS;
05400       if ((!i->outgoing && (i->callprogress & 4)) || 
05401           (i->outgoing && (i->callprogress & 2))) {
05402          features |= DSP_FEATURE_FAX_DETECT;
05403       }
05404 #ifdef DAHDI_TONEDETECT
05405       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
05406       if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
05407 #endif      
05408          i->hardwaredtmf = 0;
05409          features |= DSP_FEATURE_DTMF_DETECT;
05410 #ifdef DAHDI_TONEDETECT
05411       } else if (NEED_MFDETECT(i)) {
05412          i->hardwaredtmf = 1;
05413          features |= DSP_FEATURE_DTMF_DETECT;
05414       }
05415 #endif
05416    }
05417    if (features) {
05418       if (i->dsp) {
05419          ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
05420       } else {
05421          if (i->channel != CHAN_PSEUDO)
05422             i->dsp = ast_dsp_new();
05423          else
05424             i->dsp = NULL;
05425          if (i->dsp) {
05426             i->dsp_features = features;
05427 #ifdef HAVE_PRI
05428             /* We cannot do progress detection until receives PROGRESS message */
05429             if (i->outgoing && (i->sig == SIG_PRI)) {
05430                /* Remember requested DSP features, don't treat
05431                   talking as ANSWER */
05432                i->dsp_features = features & ~DSP_PROGRESS_TALK;
05433                features = 0;
05434             }
05435 #endif
05436             ast_dsp_set_features(i->dsp, features);
05437             ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
05438             if (!ast_strlen_zero(progzone))
05439                ast_dsp_set_call_progress_zone(i->dsp, progzone);
05440             if (i->busydetect && CANBUSYDETECT(i)) {
05441                if(i->silencethreshold > 0)
05442                   ast_dsp_set_threshold(i->dsp, i->silencethreshold);
05443                ast_dsp_set_busy_count(i->dsp, i->busycount);
05444                if(i->busytonelength > 0)
05445                   ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
05446                if((i->busytonelength == i->busyquietlength) && i->busycompare)
05447                   ast_dsp_set_busy_compare(i->dsp, i->busycompare);
05448             }
05449          }
05450       }
05451    }
05452       
05453    if (state == AST_STATE_RING)
05454       tmp->rings = 1;
05455    tmp->tech_pvt = i;
05456    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
05457       /* Only FXO signalled stuff can be picked up */
05458       tmp->callgroup = i->callgroup;
05459       tmp->pickupgroup = i->pickupgroup;
05460    }
05461    if (!ast_strlen_zero(i->language))
05462       ast_string_field_set(tmp, language, i->language);
05463    if (!i->owner)
05464       i->owner = tmp;
05465    if (!ast_strlen_zero(i->accountcode))
05466       ast_string_field_set(tmp, accountcode, i->accountcode);
05467    if (i->amaflags)
05468       tmp->amaflags = i->amaflags;
05469    i->subs[index].owner = tmp;
05470    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
05471    ast_string_field_set(tmp, call_forward, i->call_forward);
05472    /* If we've been told "no ADSI" then enforce it */
05473    if (!i->adsi)
05474       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
05475    if (!ast_strlen_zero(i->exten))
05476       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
05477    if (!ast_strlen_zero(i->rdnis))
05478       tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
05479    if (!ast_strlen_zero(i->dnid))
05480       tmp->cid.cid_dnid = ast_strdup(i->dnid);
05481 
05482    /* Don't use ast_set_callerid() here because it will
05483     * generate a needless NewCallerID event */
05484 #ifdef PRI_ANI
05485    if (!ast_strlen_zero(i->cid_ani))
05486       tmp->cid.cid_ani = ast_strdup(i->cid_ani);
05487    else  
05488       tmp->cid.cid_ani = ast_strdup(i->cid_num);
05489 #else
05490    tmp->cid.cid_ani = ast_strdup(i->cid_num);
05491 #endif
05492    tmp->cid.cid_pres = i->callingpres;
05493    tmp->cid.cid_ton = i->cid_ton;
05494 #ifdef HAVE_PRI
05495    tmp->transfercapability = transfercapability;
05496    pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
05497    if (transfercapability & PRI_TRANS_CAP_DIGITAL)
05498       i->digital = 1;
05499    /* Assume calls are not idle calls unless we're told differently */
05500    i->isidlecall = 0;
05501    i->alreadyhungup = 0;
05502 #endif
05503    /* clear the fake event in case we posted one before we had ast_channel */
05504    i->fake_event = 0;
05505    /* Assure there is no confmute on this channel */
05506    dahdi_confmute(i, 0);
05507    /* Configure the new channel jb */
05508    ast_jb_configure(tmp, &global_jbconf);
05509    if (startpbx) {
05510       if (ast_pbx_start(tmp)) {
05511          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
05512          ast_hangup(tmp);
05513          i->owner = NULL;
05514          return NULL;
05515       }
05516    }
05517 
05518    ast_module_ref(ast_module_info->self);
05519    
05520    return tmp;
05521 }

static int dahdi_open ( char *  fn  )  [static]

Definition at line 906 of file chan_dahdi.c.

References ast_log(), errno, LOG_WARNING, and READ_SIZE.

Referenced by alloc_sub(), chandup(), and mkintf().

00907 {
00908    int fd;
00909    int isnum;
00910    int chan = 0;
00911    int bs;
00912    int x;
00913    isnum = 1;
00914    for (x = 0; x < strlen(fn); x++) {
00915       if (!isdigit(fn[x])) {
00916          isnum = 0;
00917          break;
00918       }
00919    }
00920    if (isnum) {
00921       chan = atoi(fn);
00922       if (chan < 1) {
00923          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
00924          return -1;
00925       }
00926 #ifdef HAVE_ZAPTEL
00927       fn = "/dev/zap/channel";
00928 #else
00929       fn = "/dev/dahdi/channel";
00930 #endif
00931    }
00932    fd = open(fn, O_RDWR | O_NONBLOCK);
00933    if (fd < 0) {
00934       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
00935       return -1;
00936    }
00937    if (chan) {
00938       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
00939          x = errno;
00940          close(fd);
00941          errno = x;
00942          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
00943          return -1;
00944       }
00945    }
00946    bs = READ_SIZE;
00947    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
00948       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
00949       x = errno;
00950       close(fd);
00951       errno = x;
00952       return -1;
00953    }
00954    return fd;
00955 }

static void dahdi_queue_frame ( struct dahdi_pvt p,
struct ast_frame f,
void *  pri 
) [static]

Definition at line 850 of file chan_dahdi.c.

References ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_frame(), DEADLOCK_AVOIDANCE, f, dahdi_pvt::lock, ast_channel::lock, and dahdi_pvt::owner.

Referenced by __action_dialoffhook().

00852 {
00853    /* We must unlock the PRI to avoid the possibility of a deadlock */
00854 #ifdef HAVE_PRI
00855    if (pri)
00856       ast_mutex_unlock(&pri->lock);
00857 #endif      
00858    for (;;) {
00859       if (p->owner) {
00860          if (ast_mutex_trylock(&p->owner->lock)) {
00861             DEADLOCK_AVOIDANCE(&p->lock);
00862          } else {
00863             ast_queue_frame(p->owner, f);
00864             ast_mutex_unlock(&p->owner->lock);
00865             break;
00866          }
00867       } else
00868          break;
00869    }
00870 #ifdef HAVE_PRI
00871    if (pri)
00872       ast_mutex_lock(&pri->lock);
00873 #endif      
00874 }

static struct ast_frame * dahdi_read ( struct ast_channel ast  )  [static]

Definition at line 4757 of file chan_dahdi.c.

References __dahdi_exception(), ast_channel::_state, ast_clear_flag, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_dsp_process(), AST_FLAG_BLOCKING, AST_FLAG_EXCEPTION, AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_getformatname(), ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_set_callerid(), ast_set_flag, ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_verbose(), dahdi_subchannel::buffer, dahdi_pvt::busydetect, dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitingrepeat, dahdi_pvt::callwaitrings, dahdi_pvt::channel, CHECK_BLOCKING, dahdi_pvt::cidcwexpire, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_callwait(), dahdi_get_index(), dahdi_handle_dtmfup(), dahdi_setlinear(), ast_frame::data, ast_frame::datalen, DEADLOCK_AVOIDANCE, ast_frame::delivery, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dsp, errno, dahdi_subchannel::f, f, dahdi_pvt::fake_event, dahdi_pvt::firstradio, ast_frame::frametype, dahdi_pvt::ignoredtmf, dahdi_pvt::inalarm, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_subchannel::linear, ast_channel::lock, dahdi_pvt::lock, LOG_DEBUG, ast_frame::mallocd, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcallerid, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, option_verbose, dahdi_pvt::outgoing, dahdi_pvt::overlapdial, dahdi_pvt::owner, dahdi_pvt::pulsedial, dahdi_pvt::radio, ast_channel::rawreadformat, READ_SIZE, restore_conference(), ast_channel::rings, dahdi_pvt::ringt, S_OR, ast_frame::samples, send_callerid(), dahdi_pvt::sig, SIG_PRI, ast_frame::src, SUB_CALLWAIT, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_feed(), ast_channel::tech_pvt, and VERBOSE_PREFIX_3.

04758 {
04759    struct dahdi_pvt *p = ast->tech_pvt;
04760    int res;
04761    int index;
04762    void *readbuf;
04763    struct ast_frame *f;
04764 
04765    while (ast_mutex_trylock(&p->lock)) {
04766       DEADLOCK_AVOIDANCE(&ast->lock);
04767    }
04768 
04769    index = dahdi_get_index(ast, p, 0);
04770    
04771    /* Hang up if we don't really exist */
04772    if (index < 0) {
04773       ast_log(LOG_WARNING, "We dont exist?\n");
04774       ast_mutex_unlock(&p->lock);
04775       return NULL;
04776    }
04777    
04778    if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
04779 
04780    p->subs[index].f.frametype = AST_FRAME_NULL;
04781    p->subs[index].f.datalen = 0;
04782    p->subs[index].f.samples = 0;
04783    p->subs[index].f.mallocd = 0;
04784    p->subs[index].f.offset = 0;
04785    p->subs[index].f.subclass = 0;
04786    p->subs[index].f.delivery = ast_tv(0,0);
04787    p->subs[index].f.src = "dahdi_read";
04788    p->subs[index].f.data = NULL;
04789    
04790    /* make sure it sends initial key state as first frame */
04791    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
04792    {
04793       struct dahdi_params ps;
04794 
04795       ps.channo = p->channel;
04796       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
04797          ast_mutex_unlock(&p->lock);
04798          return NULL;
04799       }
04800       p->firstradio = 1;
04801       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04802       if (ps.rxisoffhook)
04803       {
04804          p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
04805       }
04806       else
04807       {
04808          p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
04809       }
04810       ast_mutex_unlock(&p->lock);
04811       return &p->subs[index].f;
04812    }
04813    if (p->ringt == 1) {
04814       ast_mutex_unlock(&p->lock);
04815       return NULL;
04816    }
04817    else if (p->ringt > 0) 
04818       p->ringt--;
04819 
04820    if (p->subs[index].needringing) {
04821       /* Send ringing frame if requested */
04822       p->subs[index].needringing = 0;
04823       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04824       p->subs[index].f.subclass = AST_CONTROL_RINGING;
04825       ast_setstate(ast, AST_STATE_RINGING);
04826       ast_mutex_unlock(&p->lock);
04827       return &p->subs[index].f;
04828    }
04829 
04830    if (p->subs[index].needbusy) {
04831       /* Send busy frame if requested */
04832       p->subs[index].needbusy = 0;
04833       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04834       p->subs[index].f.subclass = AST_CONTROL_BUSY;
04835       ast_mutex_unlock(&p->lock);
04836       return &p->subs[index].f;
04837    }
04838 
04839    if (p->subs[index].needcongestion) {
04840       /* Send congestion frame if requested */
04841       p->subs[index].needcongestion = 0;
04842       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04843       p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
04844       ast_mutex_unlock(&p->lock);
04845       return &p->subs[index].f;
04846    }
04847 
04848    if (p->subs[index].needcallerid) {
04849       ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
04850                      S_OR(p->lastcid_name, NULL),
04851                      S_OR(p->lastcid_num, NULL)
04852                      );
04853       p->subs[index].needcallerid = 0;
04854    }
04855    
04856    if (p->subs[index].needanswer) {
04857       /* Send answer frame if requested */
04858       p->subs[index].needanswer = 0;
04859       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04860       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04861       ast_mutex_unlock(&p->lock);
04862       return &p->subs[index].f;
04863    }  
04864    
04865    if (p->subs[index].needflash) {
04866       /* Send answer frame if requested */
04867       p->subs[index].needflash = 0;
04868       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04869       p->subs[index].f.subclass = AST_CONTROL_FLASH;
04870       ast_mutex_unlock(&p->lock);
04871       return &p->subs[index].f;
04872    }  
04873    
04874    if (p->subs[index].needhold) {
04875       /* Send answer frame if requested */
04876       p->subs[index].needhold = 0;
04877       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04878       p->subs[index].f.subclass = AST_CONTROL_HOLD;
04879       ast_mutex_unlock(&p->lock);
04880       ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
04881       return &p->subs[index].f;
04882    }  
04883    
04884    if (p->subs[index].needunhold) {
04885       /* Send answer frame if requested */
04886       p->subs[index].needunhold = 0;
04887       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04888       p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
04889       ast_mutex_unlock(&p->lock);
04890       ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
04891       return &p->subs[index].f;
04892    }  
04893    
04894    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
04895       if (!p->subs[index].linear) {
04896          p->subs[index].linear = 1;
04897          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
04898          if (res) 
04899             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
04900       }
04901    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
04902          (ast->rawreadformat == AST_FORMAT_ALAW)) {
04903       if (p->subs[index].linear) {
04904          p->subs[index].linear = 0;
04905          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
04906          if (res) 
04907             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
04908       }
04909    } else {
04910       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
04911       ast_mutex_unlock(&p->lock);
04912       return NULL;
04913    }
04914    readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
04915    CHECK_BLOCKING(ast);
04916    res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
04917    ast_clear_flag(ast, AST_FLAG_BLOCKING);
04918    /* Check for hangup */
04919    if (res < 0) {
04920       f = NULL;
04921       if (res == -1)  {
04922          if (errno == EAGAIN) {
04923             /* Return "NULL" frame if there is nobody there */
04924             ast_mutex_unlock(&p->lock);
04925             return &p->subs[index].f;
04926          } else if (errno == ELAST) {
04927             f = __dahdi_exception(ast);
04928          } else
04929             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
04930       }
04931       ast_mutex_unlock(&p->lock);
04932       return f;
04933    }
04934    if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
04935       ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
04936       f = __dahdi_exception(ast);
04937       ast_mutex_unlock(&p->lock);
04938       return f;
04939    }
04940    if (p->tdd) { /* if in TDD mode, see if we receive that */
04941       int c;
04942 
04943       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
04944       if (c < 0) {
04945          ast_log(LOG_DEBUG,"tdd_feed failed\n");
04946          ast_mutex_unlock(&p->lock);
04947          return NULL;
04948       }
04949       if (c) { /* if a char to return */
04950          p->subs[index].f.subclass = 0;
04951          p->subs[index].f.frametype = AST_FRAME_TEXT;
04952          p->subs[index].f.mallocd = 0;
04953          p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
04954          p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
04955          p->subs[index].f.datalen = 1;
04956          *((char *) p->subs[index].f.data) = c;
04957          ast_mutex_unlock(&p->lock);
04958          return &p->subs[index].f;
04959       }
04960    }
04961    /* Ensure the CW timer decrements only on a single subchannel */
04962    if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
04963       p->callwaitingrepeat--;
04964    }
04965    if (p->cidcwexpire)
04966       p->cidcwexpire--;
04967    /* Repeat callwaiting */
04968    if (p->callwaitingrepeat == 1) {
04969       p->callwaitrings++;
04970       dahdi_callwait(ast);
04971    }
04972    /* Expire CID/CW */
04973    if (p->cidcwexpire == 1) {
04974       if (option_verbose > 2)
04975          ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
04976       restore_conference(p);
04977    }
04978    if (p->subs[index].linear) {
04979       p->subs[index].f.datalen = READ_SIZE * 2;
04980    } else 
04981       p->subs[index].f.datalen = READ_SIZE;
04982 
04983    /* Handle CallerID Transmission */
04984    if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
04985       send_callerid(p);
04986    }
04987 
04988    p->subs[index].f.frametype = AST_FRAME_VOICE;
04989    p->subs[index].f.subclass = ast->rawreadformat;
04990    p->subs[index].f.samples = READ_SIZE;
04991    p->subs[index].f.mallocd = 0;
04992    p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
04993    p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
04994 #if 0
04995    ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
04996 #endif   
04997    if (p->dialing || /* Transmitting something */
04998       (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
04999       ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
05000       ) {
05001       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
05002          don't send anything */
05003       p->subs[index].f.frametype = AST_FRAME_NULL;
05004       p->subs[index].f.subclass = 0;
05005       p->subs[index].f.samples = 0;
05006       p->subs[index].f.mallocd = 0;
05007       p->subs[index].f.offset = 0;
05008       p->subs[index].f.data = NULL;
05009       p->subs[index].f.datalen= 0;
05010    }
05011    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect  || p->callprogress) && !index) {
05012       /* Perform busy detection. etc on the dahdi line */
05013       f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
05014       if (f) {
05015          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
05016             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
05017                /* Treat this as a "hangup" instead of a "busy" on the assumption that
05018                   a busy  */
05019                f = NULL;
05020             }
05021          } else if (f->frametype == AST_FRAME_DTMF) {
05022 #ifdef HAVE_PRI
05023             if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
05024                /* Don't accept in-band DTMF when in overlap dial mode */
05025                f->frametype = AST_FRAME_NULL;
05026                f->subclass = 0;
05027             }
05028 #endif            
05029             /* DSP clears us of being pulse */
05030             p->pulsedial = 0;
05031          }
05032       }
05033    } else 
05034       f = &p->subs[index].f; 
05035 
05036    if (f && (f->frametype == AST_FRAME_DTMF))
05037       dahdi_handle_dtmfup(ast, index, &f);
05038 
05039    /* If we have a fake_event, trigger exception to handle it */
05040    if (p->fake_event)
05041       ast_set_flag(ast, AST_FLAG_EXCEPTION);
05042 
05043    ast_mutex_unlock(&p->lock);
05044    return f;
05045 }

static struct ast_channel * dahdi_request ( const char *  type,
int  format,
void *  data,
int *  cause 
) [static]

Definition at line 7965 of file chan_dahdi.c.

References alloc_sub(), AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CDR_CALLWAIT, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RESERVED, ast_strdupa, AST_TRANS_CAP_DIGITAL, ast_verbose(), available(), busy, ast_channel::cdrflags, CHAN_PSEUDO, chandup(), dahdi_pvt::channel, dahdi_pvt::confirmanswer, dahdi_new(), dahdi_pvt::digital, dahdi_pvt::distinctivering, iflist, dahdi_pvt::inalarm, lock, LOG_DEBUG, LOG_NOTICE, dahdi_pvt::next, option_debug, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::prev, restart_monitor(), round_robin, s, dahdi_pvt::sig, SIG_FXSKS, strsep(), SUB_CALLWAIT, SUB_REAL, dahdi_pvt::subs, and ast_channel::transfercapability.

07966 {
07967    ast_group_t groupmatch = 0;
07968    int channelmatch = -1;
07969    int roundrobin = 0;
07970    int callwait = 0;
07971    int busy = 0;
07972    struct dahdi_pvt *p;
07973    struct ast_channel *tmp = NULL;
07974    char *dest=NULL;
07975    int x;
07976    char *s;
07977    char opt=0;
07978    int res=0, y=0;
07979    int backwards = 0;
07980 #ifdef HAVE_PRI
07981    int crv;
07982    int bearer = -1;
07983    int trunkgroup;
07984    struct dahdi_pri *pri=NULL;
07985 #endif   
07986    struct dahdi_pvt *exit, *start, *end;
07987    ast_mutex_t *lock;
07988    int channelmatched = 0;
07989    int groupmatched = 0;
07990    
07991    /* Assume we're locking the iflock */
07992    lock = &iflock;
07993    start = iflist;
07994    end = ifend;
07995    if (data) {
07996       dest = ast_strdupa((char *)data);
07997    } else {
07998       ast_log(LOG_WARNING, "Channel requested with no data\n");
07999       return NULL;
08000    }
08001    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
08002       /* Retrieve the group number */
08003       char *stringp=NULL;
08004       stringp=dest + 1;
08005       s = strsep(&stringp, "/");
08006       if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
08007          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
08008          return NULL;
08009       }
08010       groupmatch = ((ast_group_t) 1 << x);
08011       if (toupper(dest[0]) == 'G') {
08012          if (dest[0] == 'G') {
08013             backwards = 1;
08014             p = ifend;
08015          } else
08016             p = iflist;
08017       } else {
08018          if (dest[0] == 'R') {
08019             backwards = 1;
08020             p = round_robin[x]?round_robin[x]->prev:ifend;
08021             if (!p)
08022                p = ifend;
08023          } else {
08024             p = round_robin[x]?round_robin[x]->next:iflist;
08025             if (!p)
08026                p = iflist;
08027          }
08028          roundrobin = 1;
08029       }
08030    } else {
08031       char *stringp=NULL;
08032       stringp=dest;
08033       s = strsep(&stringp, "/");
08034       p = iflist;
08035       if (!strcasecmp(s, "pseudo")) {
08036          /* Special case for pseudo */
08037          x = CHAN_PSEUDO;
08038          channelmatch = x;
08039       } 
08040 #ifdef HAVE_PRI
08041       else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
08042          if ((trunkgroup < 1) || (crv < 1)) {
08043             ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
08044             return NULL;
08045          }
08046          res--;
08047          for (x = 0; x < NUM_SPANS; x++) {
08048             if (pris[x].trunkgroup == trunkgroup) {
08049                pri = pris + x;
08050                lock = &pri->lock;
08051                start = pri->crvs;
08052                end = pri->crvend;
08053                break;
08054             }
08055          }
08056          if (!pri) {
08057             ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
08058             return NULL;
08059          }
08060          channelmatch = crv;
08061          p = pris[x].crvs;
08062       }
08063 #endif   
08064       else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
08065          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
08066          return NULL;
08067       } else {
08068          channelmatch = x;
08069       }
08070    }
08071    /* Search for an unowned channel */
08072    ast_mutex_lock(lock);
08073    exit = p;
08074    while (p && !tmp) {
08075       if (roundrobin)
08076          round_robin[x] = p;
08077 #if 0
08078       ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
08079 #endif
08080 
08081       if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
08082          if (option_debug)
08083             ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
08084             if (p->inalarm) 
08085                goto next;
08086 
08087          callwait = (p->owner != NULL);
08088 #ifdef HAVE_PRI
08089          if (pri && (p->subs[SUB_REAL].dfd < 0)) {
08090             if (p->sig != SIG_FXSKS) {
08091                /* Gotta find an actual channel to use for this
08092                   CRV if this isn't a callwait */
08093                bearer = pri_find_empty_chan(pri, 0);
08094                if (bearer < 0) {
08095                   ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
08096                   p = NULL;
08097                   break;
08098                }
08099                pri_assign_bearer(p, pri, pri->pvts[bearer]);
08100             } else {
08101                if (alloc_sub(p, 0)) {
08102                   ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
08103                   p = NULL;
08104                   break;
08105                } else
08106                   ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
08107                p->pri = pri;
08108             }
08109          }
08110 #endif         
08111          if (p->channel == CHAN_PSEUDO) {
08112             p = chandup(p);
08113             if (!p) {
08114                break;
08115             }
08116          }
08117          if (p->owner) {
08118             if (alloc_sub(p, SUB_CALLWAIT)) {
08119                p = NULL;
08120                break;
08121             }
08122          }
08123          p->outgoing = 1;
08124          tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
08125 #ifdef HAVE_PRI
08126          if (p->bearer) {
08127             /* Log owner to bearer channel, too */
08128             p->bearer->owner = tmp;
08129          }
08130 #endif         
08131          /* Make special notes */
08132          if (res > 1) {
08133             if (opt == 'c') {
08134                /* Confirm answer */
08135                p->confirmanswer = 1;
08136             } else if (opt == 'r') {
08137                /* Distinctive ring */
08138                if (res < 3)
08139                   ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
08140                else
08141                   p->distinctivering = y;
08142             } else if (opt == 'd') {
08143                /* If this is an ISDN call, make it digital */
08144                p->digital = 1;
08145                if (tmp)
08146                   tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
08147             } else {
08148                ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
08149             }
08150          }
08151          /* Note if the call is a call waiting call */
08152          if (tmp && callwait)
08153             tmp->cdrflags |= AST_CDR_CALLWAIT;
08154          break;
08155       }
08156 next:
08157       if (backwards) {
08158          p = p->prev;
08159          if (!p)
08160             p = end;
08161       } else {
08162          p = p->next;
08163          if (!p)
08164             p = start;
08165       }
08166       /* stop when you roll to the one that we started from */
08167       if (p == exit)
08168          break;
08169    }
08170    ast_mutex_unlock(lock);
08171    restart_monitor();
08172    if (callwait)
08173       *cause = AST_CAUSE_BUSY;
08174    else if (!tmp) {
08175       if (channelmatched) {
08176          if (busy)
08177             *cause = AST_CAUSE_BUSY;
08178       } else if (groupmatched) {
08179          *cause = AST_CAUSE_CONGESTION;
08180       }
08181    }
08182       
08183    return tmp;
08184 }

static int dahdi_restart ( void   )  [static]

Definition at line 10091 of file chan_dahdi.c.

References ast_active_channels(), ast_cond_wait(), ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_verbose(), dahdi_softhangup_all(), destroy_all_channels(), dahdi_subchannel::dfd, iflist, lock, master, dahdi_pvt::next, option_debug, option_verbose, dahdi_pvt::owner, setup_dahdi(), and dahdi_pvt::subs.

Referenced by __action_restart(), and dahdi_restart_cmd().

10092 {
10093 #if defined(HAVE_PRI)
10094    int i, j;
10095 #endif
10096    int cancel_code;
10097    struct dahdi_pvt *p;
10098 
10099    ast_mutex_lock(&restart_lock);
10100  
10101    if (option_verbose)
10102       ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
10103    dahdi_softhangup_all();
10104    if (option_verbose > 3)
10105       ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
10106 
10107    #if defined(HAVE_PRI)
10108    for (i = 0; i < NUM_SPANS; i++) {
10109       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
10110          cancel_code = pthread_cancel(pris[i].master);
10111          pthread_kill(pris[i].master, SIGURG);
10112          if (option_debug > 3)
10113             ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
10114             pthread_join(pris[i].master, NULL);
10115          if (option_debug > 3)
10116             ast_verbose("Joined thread of span %d\n", i);
10117       }
10118     }
10119    #endif
10120 
10121     ast_mutex_lock(&monlock);
10122     if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10123       cancel_code = pthread_cancel(monitor_thread);
10124       pthread_kill(monitor_thread, SIGURG);
10125       if (option_debug > 3)
10126          ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
10127         pthread_join(monitor_thread, NULL);
10128       if (option_debug > 3)
10129          ast_verbose("Joined monitor thread\n");
10130     }
10131    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
10132 
10133    ast_mutex_lock(&ss_thread_lock);
10134    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
10135       int x = DAHDI_FLASH;
10136       if (option_debug > 2)
10137          ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
10138 
10139       for (p = iflist; p; p = p->next) {
10140          if (p->owner)
10141             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */    
10142       }
10143       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
10144    }
10145 
10146    /* ensure any created channels before monitor threads were stopped are hungup */
10147    dahdi_softhangup_all();
10148    if (option_verbose > 3)
10149       ast_verbose("Final softhangup of all DAHDI channels complete.\n");
10150    destroy_all_channels();
10151    if (option_debug)
10152       ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
10153 
10154     ast_mutex_unlock(&monlock);
10155 
10156    #ifdef HAVE_PRI
10157    for (i = 0; i < NUM_SPANS; i++) {
10158       for (j = 0; j < NUM_DCHANS; j++)
10159             dahdi_close_pri_fd(&(pris[i]), j);
10160    }
10161 
10162    memset(pris, 0, sizeof(pris));
10163    for (i = 0; i < NUM_SPANS; i++) {
10164       ast_mutex_init(&pris[i].lock);
10165       pris[i].offset = -1;
10166       pris[i].master = AST_PTHREADT_NULL;
10167       for (j = 0; j < NUM_DCHANS; j++)
10168          pris[i].fds[j] = -1;
10169    }
10170    pri_set_error(dahdi_pri_error);
10171    pri_set_message(dahdi_pri_message);
10172    #endif
10173 
10174    if (setup_dahdi(2) != 0) {
10175       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
10176       ast_mutex_unlock(&ss_thread_lock);
10177       return 1;
10178    }
10179    ast_mutex_unlock(&ss_thread_lock);
10180    ast_mutex_unlock(&restart_lock);
10181    return 0;
10182 }

static int dahdi_restart_cmd ( int  fd,
int  argc,
char **  argv 
) [static]

Definition at line 10184 of file chan_dahdi.c.

References dahdi_restart(), RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

10185 {
10186    if (argc != 2) {
10187       return RESULT_SHOWUSAGE;
10188    }
10189 
10190    if (dahdi_restart() != 0)
10191       return RESULT_FAILURE;
10192    return RESULT_SUCCESS;
10193 }

static int dahdi_ring_phone ( struct dahdi_pvt p  )  [static]

Definition at line 3567 of file chan_dahdi.c.

References ast_log(), errno, SUB_REAL, and dahdi_pvt::subs.

Referenced by __dahdi_exception(), and dahdi_handle_event().

03568 {
03569    int x;
03570    int res;
03571    /* Make sure our transmit state is on hook */
03572    x = 0;
03573    x = DAHDI_ONHOOK;
03574    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03575    do {
03576       x = DAHDI_RING;
03577       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03578       if (res) {
03579          switch (errno) {
03580          case EBUSY:
03581          case EINTR:
03582             /* Wait just in case */
03583             usleep(10000);
03584             continue;
03585          case EINPROGRESS:
03586             res = 0;
03587             break;
03588          default:
03589             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
03590             res = 0;
03591          }
03592       }
03593    } while (res);
03594    return res;
03595 }

static int dahdi_sendtext ( struct ast_channel c,
const char *  text 
) [static]

Definition at line 11921 of file chan_dahdi.c.

References ASCII_BYTES_PER_CHAR, ast_check_hangup(), ast_free, AST_LAW, ast_log(), ast_malloc, dahdi_pvt::channel, dahdi_get_index(), dahdi_subchannel::dfd, END_SILENCE_LEN, errno, pollfd::events, pollfd::fd, free, HEADER_LEN, HEADER_MS, LOG_ERROR, dahdi_pvt::mate, option_debug, poll(), POLLOUT, PUT_CLID, PUT_CLID_MARKMS, READ_SIZE, pollfd::revents, dahdi_pvt::subs, dahdi_pvt::tdd, TDD_BYTES_PER_CHAR, tdd_generate(), ast_channel::tech_pvt, and TRAILER_MS.

11922 {
11923 #define  END_SILENCE_LEN 400
11924 #define  HEADER_MS 50
11925 #define  TRAILER_MS 5
11926 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
11927 #define  ASCII_BYTES_PER_CHAR 80
11928 
11929    unsigned char *buf,*mybuf;
11930    struct dahdi_pvt *p = c->tech_pvt;
11931    struct pollfd fds[1];
11932    int size,res,fd,len,x;
11933    int bytes=0;
11934    /* Initial carrier (imaginary) */
11935    float cr = 1.0;
11936    float ci = 0.0;
11937    float scont = 0.0;
11938    int index;
11939 
11940    index = dahdi_get_index(c, p, 0);
11941    if (index < 0) {
11942       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
11943       return -1;
11944    }
11945    if (!text[0]) return(0); /* if nothing to send, dont */
11946    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
11947    if (p->mate) 
11948       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
11949    else
11950       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
11951    if (!buf)
11952       return -1;
11953    mybuf = buf;
11954    if (p->mate) {
11955       int codec = AST_LAW(p);
11956       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
11957          PUT_CLID_MARKMS;
11958       }
11959       /* Put actual message */
11960       for (x = 0; text[x]; x++) {
11961          PUT_CLID(text[x]);
11962       }
11963       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
11964          PUT_CLID_MARKMS;
11965       }
11966       len = bytes;
11967       buf = mybuf;
11968    } else {
11969       len = tdd_generate(p->tdd, buf, text);
11970       if (len < 1) {
11971          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
11972          free(mybuf);
11973          return -1;
11974       }
11975    }
11976    memset(buf + len, 0x7f, END_SILENCE_LEN);
11977    len += END_SILENCE_LEN;
11978    fd = p->subs[index].dfd;
11979    while (len) {
11980       if (ast_check_hangup(c)) {
11981          free(mybuf);
11982          return -1;
11983       }
11984       size = len;
11985       if (size > READ_SIZE)
11986          size = READ_SIZE;
11987       fds[0].fd = fd;
11988       fds[0].events = POLLOUT | POLLPRI;
11989       fds[0].revents = 0;
11990       res = poll(fds, 1, -1);
11991       if (!res) {
11992          ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
11993          continue;
11994       }
11995         /* if got exception */
11996       if (fds[0].revents & POLLPRI) {
11997          ast_free(mybuf);
11998          return -1;
11999       }
12000       if (!(fds[0].revents & POLLOUT)) {
12001          ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
12002          continue;
12003       }
12004       res = write(fd, buf, size);
12005       if (res != size) {
12006          if (res == -1) {
12007             free(mybuf);
12008             return -1;
12009          }
12010          if (option_debug)
12011             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
12012          break;
12013       }
12014       len -= size;
12015       buf += size;
12016    }
12017    free(mybuf);
12018    return(0);
12019 }

static int dahdi_set_hook ( int  fd,
int  hs 
) [inline, static]

Definition at line 1667 of file chan_dahdi.c.

References ast_log(), errno, and LOG_WARNING.

Referenced by __dahdi_exception(), dahdi_answer(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_wink(), handle_init_event(), and ss_thread().

01668 {
01669    int x, res;
01670 
01671    x = hs;
01672    res = ioctl(fd, DAHDI_HOOK, &x);
01673 
01674    if (res < 0) {
01675       if (errno == EINPROGRESS)
01676          return 0;
01677       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
01678       /* will expectedly fail if phone is off hook during operation, such as during a restart */
01679    }
01680 
01681    return res;
01682 }

static int dahdi_setlinear ( int  dfd,
int  linear 
) [static]

Definition at line 977 of file chan_dahdi.c.

Referenced by dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_write(), send_callerid(), and ss_thread().

00978 {
00979    int res;
00980    res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
00981    if (res)
00982       return res;
00983    return 0;
00984 }

static int dahdi_setoption ( struct ast_channel chan,
int  option,
void *  data,
int  datalen 
) [static]

Definition at line 2932 of file chan_dahdi.c.

References ast_check_hangup(), ast_dsp_digitmode(), ast_log(), AST_OPTION_AUDIO_MODE, AST_OPTION_ECHOCAN, AST_OPTION_OPRMODE, AST_OPTION_RELAXDTMF, AST_OPTION_RXGAIN, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, AST_OPTION_TXGAIN, ast_tdd_gen_ecdisa(), dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_subchannel::dfd, dahdi_pvt::didtdd, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, errno, pollfd::events, pollfd::fd, dahdi_pvt::law, len, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mate, oprmode::mode, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, option_debug, oprmode::peer, poll(), POLLOUT, POLLPRI, READ_SIZE, pollfd::revents, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_free(), tdd_new(), ast_channel::tech_pvt, and dahdi_pvt::txgain.

02933 {
02934    char *cp;
02935    signed char *scp;
02936    int x;
02937    int index;
02938    struct dahdi_pvt *p = chan->tech_pvt, *pp;
02939    struct oprmode *oprmode;
02940    
02941 
02942    /* all supported options require data */
02943    if (!data || (datalen < 1)) {
02944       errno = EINVAL;
02945       return -1;
02946    }
02947 
02948    switch (option) {
02949    case AST_OPTION_TXGAIN:
02950       scp = (signed char *) data;
02951       index = dahdi_get_index(chan, p, 0);
02952       if (index < 0) {
02953          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
02954          return -1;
02955       }
02956       if (option_debug)
02957          ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
02958       return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
02959    case AST_OPTION_RXGAIN:
02960       scp = (signed char *) data;
02961       index = dahdi_get_index(chan, p, 0);
02962       if (index < 0) {
02963          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
02964          return -1;
02965       }
02966       if (option_debug)
02967          ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
02968       return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
02969    case AST_OPTION_TONE_VERIFY:
02970       if (!p->dsp)
02971          break;
02972       cp = (char *) data;
02973       switch (*cp) {
02974       case 1:
02975          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
02976          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
02977          break;
02978       case 2:
02979          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
02980          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
02981          break;
02982       default:
02983          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
02984          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
02985          break;
02986       }
02987       break;
02988    case AST_OPTION_TDD:
02989       /* turn on or off TDD */
02990       cp = (char *) data;
02991       p->mate = 0;
02992       if (!*cp) { /* turn it off */
02993          if (option_debug)
02994             ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
02995          if (p->tdd)
02996             tdd_free(p->tdd);
02997          p->tdd = 0;
02998          break;
02999       }
03000       ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
03001          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
03002       dahdi_disable_ec(p);
03003       /* otherwise, turn it on */
03004       if (!p->didtdd) { /* if havent done it yet */
03005          unsigned char mybuf[41000], *buf;
03006          int size, res, fd, len;
03007          struct pollfd fds[1];
03008 
03009          buf = mybuf;
03010          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
03011          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
03012          len = 40000;
03013          index = dahdi_get_index(chan, p, 0);
03014          if (index < 0) {
03015             ast_log(LOG_WARNING, "No index in TDD?\n");
03016             return -1;
03017          }
03018          fd = p->subs[index].dfd;
03019          while (len) {
03020             if (ast_check_hangup(chan))
03021                return -1;
03022             size = len;
03023             if (size > READ_SIZE)
03024                size = READ_SIZE;
03025             fds[0].fd = fd;
03026             fds[0].events = POLLPRI | POLLOUT;
03027             fds[0].revents = 0;
03028             res = poll(fds, 1, -1);
03029             if (!res) {
03030                ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
03031                continue;
03032             }
03033             /* if got exception */
03034             if (fds[0].revents & POLLPRI)
03035                return -1;
03036             if (!(fds[0].revents & POLLOUT)) {
03037                ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
03038                continue;
03039             }
03040             res = write(fd, buf, size);
03041             if (res != size) {
03042                if (res == -1) return -1;
03043                ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
03044                break;
03045             }
03046             len -= size;
03047             buf += size;
03048          }
03049          p->didtdd = 1; /* set to have done it now */    
03050       }
03051       if (*cp == 2) { /* Mate mode */
03052          if (p->tdd)
03053             tdd_free(p->tdd);
03054          p->tdd = 0;
03055          p->mate = 1;
03056          break;
03057       }     
03058       if (!p->tdd) { /* if we dont have one yet */
03059          p->tdd = tdd_new(); /* allocate one */
03060       }     
03061       break;
03062    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
03063       if (!p->dsp)
03064          break;
03065       cp = (char *) data;
03066       ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
03067          *cp ? "ON" : "OFF", (int) *cp, chan->name);
03068                 p->dtmfrelax = 0;
03069                 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
03070                 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03071       break;
03072    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
03073       cp = (char *) data;
03074       if (!*cp) {    
03075          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
03076          x = 0;
03077          dahdi_disable_ec(p);
03078       } else {    
03079          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
03080          x = 1;
03081       }
03082       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
03083          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
03084       break;
03085    case AST_OPTION_OPRMODE:  /* Operator services mode */
03086       oprmode = (struct oprmode *) data;
03087       pp = oprmode->peer->tech_pvt;
03088       p->oprmode = pp->oprmode = 0;
03089       /* setup peers */
03090       p->oprpeer = pp;
03091       pp->oprpeer = p;
03092       /* setup modes, if any */
03093       if (oprmode->mode) 
03094       {
03095          pp->oprmode = oprmode->mode;
03096          p->oprmode = -oprmode->mode;
03097       }
03098       ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
03099          oprmode->mode, chan->name,oprmode->peer->name);;
03100       break;
03101    case AST_OPTION_ECHOCAN:
03102       cp = (char *) data;
03103       if (*cp) {
03104          ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
03105          dahdi_enable_ec(p);
03106       } else {
03107          ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
03108          dahdi_disable_ec(p);
03109       }
03110       break;
03111    }
03112    errno = 0;
03113 
03114    return 0;
03115 }

static int dahdi_show_channel ( int  fd,
int  argc,
char **  argv 
) [static]

Definition at line 10256 of file chan_dahdi.c.

References ast_cli(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_ton, dahdi_pvt::confno, dahdi_pvt::context, dahdi_pvt::destroy, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dsp, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, dahdi_pvt::exten, dahdi_pvt::faxhandled, iflist, dahdi_pvt::inalarm, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, ISTRUNK, dahdi_pvt::law, dahdi_subchannel::linear, lock, dahdi_pvt::master, dahdi_pvt::next, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::propconfno, dahdi_pvt::pulsedial, dahdi_pvt::radio, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, dahdi_pvt::sig, sig2str, dahdi_pvt::slaves, dahdi_pvt::span, SUB_CALLWAIT, SUB_THREEWAY, and dahdi_pvt::subs.

10257 {
10258    int channel;
10259    struct dahdi_pvt *tmp = NULL;
10260    struct dahdi_confinfo ci;
10261    struct dahdi_params ps;
10262    int x;
10263    ast_mutex_t *lock;
10264    struct dahdi_pvt *start;
10265 #ifdef HAVE_PRI
10266    char *c;
10267    int trunkgroup;
10268    struct dahdi_pri *pri=NULL;
10269 #endif
10270 
10271    lock = &iflock;
10272    start = iflist;
10273 
10274    if (argc != 4)
10275       return RESULT_SHOWUSAGE;
10276 #ifdef HAVE_PRI
10277    if ((c = strchr(argv[3], ':'))) {
10278       if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2)
10279          return RESULT_SHOWUSAGE;
10280       if ((trunkgroup < 1) || (channel < 1))
10281          return RESULT_SHOWUSAGE;
10282       for (x = 0; x < NUM_SPANS; x++) {
10283          if (pris[x].trunkgroup == trunkgroup) {
10284             pri = pris + x;
10285             break;
10286          }
10287       }
10288       if (pri) {
10289          start = pri->crvs;
10290          lock = &pri->lock;
10291       } else {
10292          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10293          return RESULT_FAILURE;
10294       }
10295    } else
10296 #endif
10297       channel = atoi(argv[3]);
10298 
10299    ast_mutex_lock(lock);
10300    tmp = start;
10301    while (tmp) {
10302       if (tmp->channel == channel) {
10303 #ifdef HAVE_PRI
10304          if (pri) 
10305             ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
10306          else
10307 #endif         
10308          ast_cli(fd, "Channel: %d\n", tmp->channel);
10309          ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
10310          ast_cli(fd, "Span: %d\n", tmp->span);
10311          ast_cli(fd, "Extension: %s\n", tmp->exten);
10312          ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
10313          ast_cli(fd, "Context: %s\n", tmp->context);
10314          ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
10315          ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
10316          ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
10317          ast_cli(fd, "Destroy: %d\n", tmp->destroy);
10318          ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
10319          ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
10320          ast_cli(fd, "Radio: %d\n", tmp->radio);
10321          ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
10322          ast_cli(fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? tmp->subs[SUB_REAL].owner->name : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");
10323          ast_cli(fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? tmp->subs[SUB_CALLWAIT].owner->name : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : "");
10324          ast_cli(fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? tmp->subs[SUB_THREEWAY].owner->name : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : "");
10325          ast_cli(fd, "Confno: %d\n", tmp->confno);
10326          ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
10327          ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
10328          ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
10329          ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
10330          ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
10331          ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
10332          ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
10333          ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
10334          ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
10335          if (tmp->master)
10336             ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
10337          for (x = 0; x < MAX_SLAVES; x++) {
10338             if (tmp->slaves[x])
10339                ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
10340          }
10341 #ifdef HAVE_PRI
10342          if (tmp->pri) {
10343             ast_cli(fd, "PRI Flags: ");
10344             if (tmp->resetting)
10345                ast_cli(fd, "Resetting ");
10346             if (tmp->call)
10347                ast_cli(fd, "Call ");
10348             if (tmp->bearer)
10349                ast_cli(fd, "Bearer ");
10350             ast_cli(fd, "\n");
10351             if (tmp->logicalspan) 
10352                ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
10353             else
10354                ast_cli(fd, "PRI Logical Span: Implicit\n");
10355          }
10356             
10357 #endif
10358          memset(&ci, 0, sizeof(ci));
10359          ps.channo = tmp->channel;
10360          if (tmp->subs[SUB_REAL].dfd > -1) {
10361             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
10362                ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
10363             }
10364 #ifdef DAHDI_GETCONFMUTE
10365             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
10366                ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
10367             }
10368 #endif
10369             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
10370                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
10371             } else {
10372                ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
10373             }
10374          }
10375          if (ISTRUNK(tmp)) {
10376             ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");  
10377             if (!ast_strlen_zero(progzone))
10378                ast_cli(fd, "Progress Zone: %s\n", progzone);
10379             ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");  
10380             if(tmp->busydetect) {
10381                ast_cli(fd, "Busy Count: %d\n", tmp->busycount);
10382                if(tmp->busytonelength > 0) {
10383                   ast_cli(fd, "Busy Pattern:\n");
10384                   ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
10385                   if (tmp->busyquietlength > 0) 
10386                      ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
10387                   else 
10388                      ast_cli(fd, " -- Detect Tone Only\n");
10389                   if(tmp->busyfuzziness > 0)
10390                      ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
10391                }
10392             }
10393          }
10394          ast_mutex_unlock(lock);
10395          return RESULT_SUCCESS;
10396       }
10397       tmp = tmp->next;
10398    }
10399    
10400    ast_cli(fd, "Unable to find given channel %d\n", channel);
10401    ast_mutex_unlock(lock);
10402    return RESULT_FAILURE;
10403 }

static int dahdi_show_channels ( int  fd,
int  argc,
char **  argv 
) [static]

Definition at line 10195 of file chan_dahdi.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, dahdi_pvt::context, dahdi_pvt::exten, FORMAT, FORMAT2, iflist, dahdi_pvt::language, lock, dahdi_pvt::mohinterpret, dahdi_pvt::next, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

10196 {
10197 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10198 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10199    struct dahdi_pvt *tmp = NULL;
10200    char tmps[20] = "";
10201    ast_mutex_t *lock;
10202    struct dahdi_pvt *start;
10203 #ifdef HAVE_PRI
10204    int trunkgroup;
10205    struct dahdi_pri *pri = NULL;
10206    int x;
10207 #endif
10208 
10209    lock = &iflock;
10210    start = iflist;
10211 
10212 #ifdef HAVE_PRI
10213    if (argc == 4) {
10214       if ((trunkgroup = atoi(argv[3])) < 1)
10215          return RESULT_SHOWUSAGE;
10216       for (x = 0; x < NUM_SPANS; x++) {
10217          if (pris[x].trunkgroup == trunkgroup) {
10218             pri = pris + x;
10219             break;
10220          }
10221       }
10222       if (pri) {
10223          start = pri->crvs;
10224          lock = &pri->lock;
10225       } else {
10226          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10227          return RESULT_FAILURE;
10228       }
10229    } else
10230 #endif
10231    if (argc != 3)
10232       return RESULT_SHOWUSAGE;
10233 
10234    ast_mutex_lock(lock);
10235 #ifdef HAVE_PRI
10236    ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
10237 #else
10238    ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
10239 #endif   
10240    
10241    tmp = start;
10242    while (tmp) {
10243       if (tmp->channel > 0) {
10244          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
10245       } else
10246          ast_copy_string(tmps, "pseudo", sizeof(tmps));
10247       ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
10248       tmp = tmp->next;
10249    }
10250    ast_mutex_unlock(lock);
10251    return RESULT_SUCCESS;
10252 #undef FORMAT
10253 #undef FORMAT2
10254 }

static int dahdi_show_status ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 10436 of file chan_dahdi.c.

References alarms, ast_cli(), ast_log(), errno, FORMAT, FORMAT2, and RESULT_FAILURE.

10436                                                              {
10437    #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10438    #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10439 
10440    int span;
10441    int res;
10442    char alarms[50];
10443 
10444    int ctl;
10445    struct dahdi_spaninfo s;
10446 
10447 #ifdef HAVE_ZAPTEL
10448    if ((ctl = open("/dev/zap/ctl", O_RDWR)) < 0) {
10449       ast_log(LOG_WARNING, "Unable to open /dev/zap/ctl: %s\n", strerror(errno));
10450       ast_cli(fd, "No Zaptel interface found.\n");
10451       return RESULT_FAILURE;
10452    }
10453 #else
10454    if ((ctl = open("/dev/dahdi/ctl", O_RDWR)) < 0) {
10455       ast_log(LOG_WARNING, "Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
10456       ast_cli(fd, "No DAHDI interface found.\n");
10457       return RESULT_FAILURE;
10458    }
10459 #endif
10460    ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10461 
10462    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
10463       s.spanno = span;
10464       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
10465       if (res) {
10466          continue;
10467       }
10468       alarms[0] = '\0';
10469       if (s.alarms > 0) {
10470          if (s.alarms & DAHDI_ALARM_BLUE)
10471             strcat(alarms, "BLU/");
10472          if (s.alarms & DAHDI_ALARM_YELLOW)
10473             strcat(alarms, "YEL/");
10474          if (s.alarms & DAHDI_ALARM_RED)
10475             strcat(alarms, "RED/");
10476          if (s.alarms & DAHDI_ALARM_LOOPBACK)
10477             strcat(alarms, "LB/");
10478          if (s.alarms & DAHDI_ALARM_RECOVER)
10479             strcat(alarms, "REC/");
10480          if (s.alarms & DAHDI_ALARM_NOTOPEN)
10481             strcat(alarms, "NOP/");
10482          if (!strlen(alarms))
10483             strcat(alarms, "UUU/");
10484          if (strlen(alarms)) {
10485             /* Strip trailing / */
10486             alarms[strlen(alarms) - 1] = '\0';
10487          }
10488       } else {
10489          if (s.numchans)
10490             strcpy(alarms, "OK");
10491          else
10492             strcpy(alarms, "UNCONFIGURED");
10493       }
10494 
10495       ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
10496    }
10497    close(ctl);
10498 
10499    return RESULT_SUCCESS;
10500 #undef FORMAT
10501 #undef FORMAT2
10502 }

static char* dahdi_sig2str ( int  sig  )  [static]

Definition at line 1218 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_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, and SIG_SFWINK.

01219 {
01220    static char buf[256];
01221    switch (sig) {
01222    case SIG_EM:
01223       return "E & M Immediate";
01224    case SIG_EMWINK:
01225       return "E & M Wink";
01226    case SIG_EM_E1:
01227       return "E & M E1";
01228    case SIG_FEATD:
01229       return "Feature Group D (DTMF)";
01230    case SIG_FEATDMF:
01231       return "Feature Group D (MF)";
01232    case SIG_FEATDMF_TA:
01233       return "Feature Groud D (MF) Tandem Access";
01234    case SIG_FEATB:
01235       return "Feature Group B (MF)";
01236    case SIG_E911:
01237       return "E911 (MF)";
01238    case SIG_FGC_CAMA:
01239       return "FGC/CAMA (Dialpulse)";
01240    case SIG_FGC_CAMAMF:
01241       return "FGC/CAMA (MF)";
01242    case SIG_FXSLS:
01243       return "FXS Loopstart";
01244    case SIG_FXSGS:
01245       return "FXS Groundstart";
01246    case SIG_FXSKS:
01247       return "FXS Kewlstart";
01248    case SIG_FXOLS:
01249       return "FXO Loopstart";
01250    case SIG_FXOGS:
01251       return "FXO Groundstart";
01252    case SIG_FXOKS:
01253       return "FXO Kewlstart";
01254    case SIG_PRI:
01255       return "ISDN PRI";
01256    case SIG_SF:
01257       return "SF (Tone) Immediate";
01258    case SIG_SFWINK:
01259       return "SF (Tone) Wink";
01260    case SIG_SF_FEATD:
01261       return "SF (Tone) with Feature Group D (DTMF)";
01262    case SIG_SF_FEATDMF:
01263       return "SF (Tone) with Feature Group D (MF)";
01264    case SIG_SF_FEATB:
01265       return "SF (Tone) with Feature Group B (MF)";
01266    case SIG_GR303FXOKS:
01267       return "GR-303 with FXOKS";
01268    case SIG_GR303FXSKS:
01269       return "GR-303 with FXSKS";
01270    case 0:
01271       return "Pseudo";
01272    default:
01273       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
01274       return buf;
01275    }
01276 }

static void dahdi_softhangup_all ( void   )  [static]

Definition at line 10062 of file chan_dahdi.c.

References ast_channel_trylock, ast_channel_unlock, ast_mutex_lock(), ast_mutex_unlock(), AST_SOFTHANGUP_EXPLICIT, ast_softhangup_nolock(), ast_verbose(), iflist, dahdi_pvt::lock, dahdi_pvt::next, option_debug, dahdi_pvt::owner, and dahdi_pvt::restartpending.

Referenced by dahdi_restart().

10063 {
10064    struct dahdi_pvt *p;
10065 retry:
10066    ast_mutex_lock(&iflock);
10067     for (p = iflist; p; p = p->next) {
10068       ast_mutex_lock(&p->lock);
10069         if (p->owner && !p->restartpending) {
10070          if (ast_channel_trylock(p->owner)) {
10071             if (option_debug > 2)
10072                ast_verbose("Avoiding deadlock\n");
10073             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
10074             ast_mutex_unlock(&p->lock);
10075             ast_mutex_unlock(&iflock);
10076             goto retry;
10077          }
10078          if (option_debug > 2)
10079             ast_verbose("Softhanging up on %s\n", p->owner->name);
10080          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
10081          p->restartpending = 1;
10082          num_restart_pending++;
10083          ast_channel_unlock(p->owner);
10084       }
10085       ast_mutex_unlock(&p->lock);
10086     }
10087    ast_mutex_unlock(&iflock);
10088 }

static void dahdi_train_ec ( struct dahdi_pvt p  )  [static]

Definition at line 1499 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, dahdi_pvt::echocancel, dahdi_pvt::echotraining, errno, LOG_DEBUG, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_answer(), and dahdi_handle_event().

01500 {
01501    int x;
01502    int res;
01503    if (p && p->echocancel && p->echotraining) {
01504       x = p->echotraining;
01505       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
01506       if (res)
01507          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
01508       else {
01509          ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
01510       }
01511    } else
01512       ast_log(LOG_DEBUG, "No echo training requested\n");
01513 }

static void dahdi_unlink ( struct dahdi_pvt slave,
struct dahdi_pvt master,
int  needlock 
) [static]

Definition at line 3136 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_trylock(), conf_del(), DEADLOCK_AVOIDANCE, dahdi_pvt::lock, LOG_DEBUG, master, and SUB_REAL.

Referenced by dahdi_bridge(), and dahdi_fixup().

03137 {
03138    /* Unlink a specific slave or all slaves/masters from a given master */
03139    int x;
03140    int hasslaves;
03141    if (!master)
03142       return;
03143    if (needlock) {
03144       ast_mutex_lock(&master->lock);
03145       if (slave) {
03146          while (ast_mutex_trylock(&slave->lock)) {
03147             DEADLOCK_AVOIDANCE(&master->lock);
03148          }
03149       }
03150    }
03151    hasslaves = 0;
03152    for (x = 0; x < MAX_SLAVES; x++) {
03153       if (master->slaves[x]) {
03154          if (!slave || (master->slaves[x] == slave)) {
03155             /* Take slave out of the conference */
03156             ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
03157             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
03158             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
03159             master->slaves[x]->master = NULL;
03160             master->slaves[x] = NULL;
03161          } else
03162             hasslaves = 1;
03163       }
03164       if (!hasslaves)
03165          master->inconference = 0;
03166    }
03167    if (!slave) {
03168       if (master->master) {
03169          /* Take master out of the conference */
03170          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
03171          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
03172          hasslaves = 0;
03173          for (x = 0; x < MAX_SLAVES; x++) {
03174             if (master->master->slaves[x] == master)
03175                master->master->slaves[x] = NULL;
03176             else if (master->master->slaves[x])
03177                hasslaves = 1;
03178          }
03179          if (!hasslaves)
03180             master->master->inconference = 0;
03181       }
03182       master->master = NULL;
03183    }
03184    update_conf(master);
03185    if (needlock) {
03186       if (slave)
03187          ast_mutex_unlock(&slave->lock);
03188       ast_mutex_unlock(&master->lock);
03189    }
03190 }

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

Avoid the silly dahdi_waitevent which ignores a bunch of events.

Definition at line 265 of file chan_dahdi.c.

Referenced by ss_thread().

00266 {
00267    int i, j = 0;
00268    i = DAHDI_IOMUX_SIGEVENT;
00269    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00270       return -1;
00271    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00272       return -1;
00273    return j;
00274 }

static int dahdi_wink ( struct dahdi_pvt p,
int  index 
) [static]

Definition at line 5543 of file chan_dahdi.c.

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

Referenced by ss_thread().

05544 {
05545    int j;
05546    dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
05547    for (;;)
05548    {
05549          /* set bits of interest */
05550       j = DAHDI_IOMUX_SIGEVENT;
05551           /* wait for some happening */
05552       if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
05553          /* exit loop if we have it */
05554       if (j & DAHDI_IOMUX_SIGEVENT) break;
05555    }
05556      /* get the event info */
05557    if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
05558    return 0;
05559 }

static int dahdi_write ( struct ast_channel ast,
struct ast_frame frame 
) [static]

Definition at line 5070 of file chan_dahdi.c.

References AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, dahdi_pvt::cidspill, dahdi_get_index(), dahdi_setlinear(), ast_frame::data, ast_frame::datalen, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::digital, errno, ast_frame::frametype, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, my_dahdi_write(), option_debug, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::sig, SIG_PRI, dahdi_pvt::span, ast_frame::subclass, dahdi_pvt::subs, and ast_channel::tech_pvt.

05071 {
05072    struct dahdi_pvt *p = ast->tech_pvt;
05073    int res;
05074    int index;
05075    index = dahdi_get_index(ast, p, 0);
05076    if (index < 0) {
05077       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
05078       return -1;
05079    }
05080 
05081 #if 0
05082 #ifdef HAVE_PRI
05083    ast_mutex_lock(&p->lock);
05084    if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05085       if (p->pri->pri) {      
05086          if (!pri_grab(p, p->pri)) {
05087                pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05088                pri_rel(p->pri);
05089          } else
05090                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05091       }
05092       p->proceeding=1;
05093    }
05094    ast_mutex_unlock(&p->lock);
05095 #endif
05096 #endif
05097    /* Write a frame of (presumably voice) data */
05098    if (frame->frametype != AST_FRAME_VOICE) {
05099       if (frame->frametype != AST_FRAME_IMAGE)
05100          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
05101       return 0;
05102    }
05103    if ((frame->subclass != AST_FORMAT_SLINEAR) && 
05104        (frame->subclass != AST_FORMAT_ULAW) &&
05105        (frame->subclass != AST_FORMAT_ALAW)) {
05106       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
05107       return -1;
05108    }
05109    if (p->dialing) {
05110       if (option_debug)
05111          ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
05112       return 0;
05113    }
05114    if (!p->owner) {
05115       if (option_debug)
05116          ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
05117       return 0;
05118    }
05119    if (p->cidspill) {
05120       if (option_debug)
05121          ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
05122       return 0;
05123    }
05124    /* Return if it's not valid data */
05125    if (!frame->data || !frame->datalen)
05126       return 0;
05127 
05128    if (frame->subclass == AST_FORMAT_SLINEAR) {
05129       if (!p->subs[index].linear) {
05130          p->subs[index].linear = 1;
05131          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05132          if (res)
05133             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
05134       }
05135       res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
05136    } else {
05137       /* x-law already */
05138       if (p->subs[index].linear) {
05139          p->subs[index].linear = 0;
05140          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05141          if (res)
05142             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
05143       }
05144       res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
05145    }
05146    if (res < 0) {
05147       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05148       return -1;
05149    } 
05150    return 0;
05151 }

static void destroy_all_channels ( void   )  [static]

Definition at line 2339 of file chan_dahdi.c.

References ast_free, ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), dahdi_pvt::channel, dahdi_pvt::cidspill, destroy_dahdi_pvt(), iflist, dahdi_pvt::next, option_verbose, and VERBOSE_PREFIX_2.

Referenced by __unload_module(), and dahdi_restart().

02340 {
02341    int x;
02342    struct dahdi_pvt *p, *pl;
02343 
02344    while (num_restart_pending) {
02345       usleep(1);
02346    }
02347 
02348    ast_mutex_lock(&iflock);
02349    /* Destroy all the interfaces and free their memory */
02350    p = iflist;
02351    while (p) {
02352       /* Free any callerid */
02353       if (p->cidspill)
02354          ast_free(p->cidspill);
02355       pl = p;
02356       p = p->next;
02357       x = pl->channel;
02358       /* Free associated memory */
02359       if (pl)
02360          destroy_dahdi_pvt(&pl);
02361       if (option_verbose > 2) 
02362          ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
02363    }
02364    iflist = NULL;
02365    ifcount = 0;
02366    ast_mutex_unlock(&iflock);
02367 }

static int destroy_channel ( struct dahdi_pvt prev,
struct dahdi_pvt cur,
int  now 
) [static]

Definition at line 2289 of file chan_dahdi.c.

References destroy_dahdi_pvt(), iflist, dahdi_pvt::next, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::prev, and dahdi_pvt::subs.

Referenced by dahdi_destroy_channel_bynum(), and dahdi_hangup().

02290 {
02291    int owned = 0;
02292    int i = 0;
02293 
02294    if (!now) {
02295       if (cur->owner) {
02296          owned = 1;
02297       }
02298 
02299       for (i = 0; i < 3; i++) {
02300          if (cur->subs[i].owner) {
02301             owned = 1;
02302          }
02303       }
02304       if (!owned) {
02305          if (prev) {
02306             prev->next = cur->next;
02307             if (prev->next)
02308                prev->next->prev = prev;
02309             else
02310                ifend = prev;
02311          } else {
02312             iflist = cur->next;
02313             if (iflist)
02314                iflist->prev = NULL;
02315             else
02316                ifend = NULL;
02317          }
02318          destroy_dahdi_pvt(&cur);
02319       }
02320    } else {
02321       if (prev) {
02322          prev->next = cur->next;
02323          if (prev->next)
02324             prev->next->prev = prev;
02325          else
02326             ifend = prev;
02327       } else {
02328          iflist = cur->next;
02329          if (iflist)
02330             iflist->prev = NULL;
02331          else
02332             ifend = NULL;
02333       }
02334       destroy_dahdi_pvt(&cur);
02335    }
02336    return 0;
02337 }

static void destroy_dahdi_pvt ( struct dahdi_pvt **  pvt  )  [static]

Definition at line 2271 of file chan_dahdi.c.

References ast_mutex_destroy(), ast_smdi_interface_unref(), dahdi_close_sub(), free, dahdi_pvt::lock, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::prev, dahdi_pvt::smdi_iface, SUB_REAL, ast_channel::tech_pvt, and dahdi_pvt::use_smdi.

Referenced by chandup(), destroy_all_channels(), destroy_channel(), and mkintf().

02272 {
02273    struct dahdi_pvt *p = *pvt;
02274    /* Remove channel from the list */
02275    if (p->prev)
02276       p->prev->next = p->next;
02277    if (p->next)
02278       p->next->prev = p->prev;
02279    if (p->use_smdi)
02280       ast_smdi_interface_unref(p->smdi_iface);
02281    ast_mutex_destroy(&p->lock);
02282    dahdi_close_sub(p, SUB_REAL);
02283    if (p->owner)
02284       p->owner->tech_pvt = NULL;
02285    free(p);
02286    *pvt = NULL;
02287 }

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 1042 of file chan_dahdi.c.

Referenced by dahdi_digit_begin().

01043 {
01044    if (isdigit(digit))
01045       return DAHDI_TONE_DTMF_BASE + (digit - '0');
01046    else if (digit >= 'A' && digit <= 'D')
01047       return DAHDI_TONE_DTMF_A + (digit - 'A');
01048    else if (digit >= 'a' && digit <= 'd')
01049       return DAHDI_TONE_DTMF_A + (digit - 'a');
01050    else if (digit == '*')
01051       return DAHDI_TONE_DTMF_s;
01052    else if (digit == '#')
01053       return DAHDI_TONE_DTMF_p;
01054    else
01055       return -1;
01056 }

static void disable_dtmf_detect ( struct dahdi_pvt p  )  [static]

Definition at line 3215 of file chan_dahdi.c.

References ast_dsp_set_features(), dahdi_pvt::dsp, DSP_FEATURE_DTMF_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::hardwaredtmf, dahdi_pvt::ignoredtmf, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_bridge().

03216 {
03217 #ifdef DAHDI_TONEDETECT
03218    int val;
03219 #endif
03220 
03221    p->ignoredtmf = 1;
03222 
03223 #ifdef DAHDI_TONEDETECT
03224    val = 0;
03225    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
03226 #endif      
03227    if (!p->hardwaredtmf && p->dsp) {
03228       p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
03229       ast_dsp_set_features(p->dsp, p->dsp_features);
03230    }
03231 }

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

Definition at line 6949 of file chan_dahdi.c.

References ast_calloc, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::cidspill, pollfd::events, pollfd::fd, free, iflist, last, LOG_DEBUG, dahdi_pvt::next, dahdi_pvt::owner, POLLIN, POLLPRI, dahdi_pvt::radio, pollfd::revents, dahdi_pvt::sig, SUB_REAL, and dahdi_pvt::subs.

Referenced by restart_monitor().

06950 {
06951    int count, res, res2, spoint, pollres=0;
06952    struct dahdi_pvt *i;
06953    struct dahdi_pvt *last = NULL;
06954    time_t thispass = 0, lastpass = 0;
06955    int found;
06956    char buf[1024];
06957    struct pollfd *pfds=NULL;
06958    int lastalloc = -1;
06959    /* This thread monitors all the frame relay interfaces which are not yet in use
06960       (and thus do not have a separate thread) indefinitely */
06961    /* From here on out, we die whenever asked */
06962 #if 0
06963    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
06964       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
06965       return NULL;
06966    }
06967    ast_log(LOG_DEBUG, "Monitor starting...\n");
06968 #endif
06969    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
06970 
06971    for (;;) {
06972       /* Lock the interface list */
06973       ast_mutex_lock(&iflock);
06974       if (!pfds || (lastalloc != ifcount)) {
06975          if (pfds) {
06976             free(pfds);
06977             pfds = NULL;
06978          }
06979          if (ifcount) {
06980             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
06981                ast_mutex_unlock(&iflock);
06982                return NULL;
06983             }
06984          }
06985          lastalloc = ifcount;
06986       }
06987       /* Build the stuff we're going to poll on, that is the socket of every
06988          dahdi_pvt that does not have an associated owner channel */
06989       count = 0;
06990       i = iflist;
06991       while (i) {
06992          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
06993             if (!i->owner && !i->subs[SUB_REAL].owner) {
06994                /* This needs to be watched, as it lacks an owner */
06995                pfds[count].fd = i->subs[SUB_REAL].dfd;
06996                pfds[count].events = POLLPRI;
06997                pfds[count].revents = 0;
06998                /* Message waiting or r2 channels also get watched for reading */
06999                if (i->cidspill)
07000                   pfds[count].events |= POLLIN;
07001                count++;
07002             }
07003          }
07004          i = i->next;
07005       }
07006       /* Okay, now that we know what to do, release the interface lock */
07007       ast_mutex_unlock(&iflock);
07008       
07009       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
07010       pthread_testcancel();
07011       /* Wait at least a second for something to happen */
07012       res = poll(pfds, count, 1000);
07013       pthread_testcancel();
07014       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
07015 
07016       /* Okay, poll has finished.  Let's see what happened.  */
07017       if (res < 0) {
07018          if ((errno != EAGAIN) && (errno != EINTR))
07019             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
07020          continue;
07021       }
07022       /* Alright, lock the interface list again, and let's look and see what has
07023          happened */
07024       ast_mutex_lock(&iflock);
07025       found = 0;
07026       spoint = 0;
07027       lastpass = thispass;
07028       thispass = time(NULL);
07029       i = iflist;
07030       while (i) {
07031          if (thispass != lastpass) {
07032             if (!found && ((i == last) || ((i == iflist) && !last))) {
07033                last = i;
07034                if (last) {
07035                   if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
07036                      (last->sig & __DAHDI_SIG_FXO)) {
07037                      res = ast_app_has_voicemail(last->mailbox, NULL);
07038                      if (last->msgstate != res) {
07039                         int x;
07040                         ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
07041                         x = DAHDI_FLUSH_BOTH;
07042                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
07043                         if (res2)
07044                            ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
07045                         if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
07046                            /* Turn on on hook transfer for 4 seconds */
07047                            x = 4000;
07048                            ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
07049                            last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
07050                            last->cidpos = 0;
07051                            last->msgstate = res;
07052                            last->onhooktime = thispass;
07053                         }
07054                         found ++;
07055                      }
07056                   }
07057                   last = last->next;
07058                }
07059             }
07060          }
07061          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
07062             if (i->radio && !i->owner)
07063             {
07064                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
07065                if (res)
07066                {
07067                   if (option_debug)
07068                      ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
07069                   /* Don't hold iflock while handling init events */
07070                   ast_mutex_unlock(&iflock);
07071                   handle_init_event(i, res);
07072                   ast_mutex_lock(&iflock);   
07073                }
07074                i = i->next;
07075                continue;
07076             }              
07077             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
07078             if (pollres & POLLIN) {
07079                if (i->owner || i->subs[SUB_REAL].owner) {
07080 #ifdef HAVE_PRI
07081                   if (!i->pri)
07082 #endif                  
07083                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
07084                   i = i->next;
07085                   continue;
07086                }
07087                if (!i->cidspill) {
07088                   ast_log(LOG_WARNING, "Whoa....  I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
07089                   i = i->next;
07090                   continue;
07091                }
07092                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
07093                if (res > 0) {
07094                   /* We read some number of bytes.  Write an equal amount of data */
07095                   if (res > i->cidlen - i->cidpos) 
07096                      res = i->cidlen - i->cidpos;
07097                   res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res);
07098                   if (res2 > 0) {
07099                      i->cidpos += res2;
07100                      if (i->cidpos >= i->cidlen) {
07101                         free(i->cidspill);
07102                         i->cidspill = 0;
07103                         i->cidpos = 0;
07104                         i->cidlen = 0;
07105                      }
07106                   } else {
07107                      ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
07108                      i->msgstate = -1;
07109                   }
07110                } else {
07111                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
07112                }
07113             }
07114             if (pollres & POLLPRI) {
07115                if (i->owner || i->subs[SUB_REAL].owner) {
07116 #ifdef HAVE_PRI
07117                   if (!i->pri)
07118 #endif                  
07119                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
07120                   i = i->next;
07121                   continue;
07122                }
07123                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
07124                if (option_debug)
07125                   ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
07126                /* Don't hold iflock while handling init events */
07127                ast_mutex_unlock(&iflock);
07128                handle_init_event(i, res);
07129                ast_mutex_lock(&iflock);   
07130             }
07131          }
07132          i=i->next;
07133       }
07134       ast_mutex_unlock(&iflock);
07135    }
07136    /* Never reached */
07137    return NULL;
07138    
07139 }

static void enable_dtmf_detect ( struct dahdi_pvt p  )  [static]

Definition at line 3233 of file chan_dahdi.c.

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

Referenced by dahdi_bridge().

03234 {
03235 #ifdef DAHDI_TONEDETECT
03236    int val;
03237 #endif
03238 
03239    if (p->channel == CHAN_PSEUDO)
03240       return;
03241 
03242    p->ignoredtmf = 0;
03243 
03244 #ifdef DAHDI_TONEDETECT
03245    val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
03246    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
03247 #endif      
03248    if (!p->hardwaredtmf && p->dsp) {
03249       p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
03250       ast_dsp_set_features(p->dsp, p->dsp_features);
03251    }
03252 }

static char* event2str ( int  event  )  [static]

Definition at line 1199 of file chan_dahdi.c.

Referenced by __dahdi_exception(), dahdi_handle_event(), and ss_thread().

01200 {
01201    static char buf[256];
01202    if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
01203       return events[event];
01204    sprintf(buf, "Event %d", event); /* safe */
01205    return buf;
01206 }

static void fill_rxgain ( struct dahdi_gains *  g,
float  gain,
int  law 
) [static]

Definition at line 1564 of file chan_dahdi.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_rxgain().

01565 {
01566    int j;
01567    int k;
01568    float linear_gain = pow(10.0, gain / 20.0);
01569 
01570    switch (law) {
01571    case DAHDI_LAW_ALAW:
01572       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01573          if (gain) {
01574             k = (int) (((float) AST_ALAW(j)) * linear_gain);
01575             if (k > 32767) k = 32767;
01576             if (k < -32767) k = -32767;
01577             g->rxgain[j] = AST_LIN2A(k);
01578          } else {
01579             g->rxgain[j] = j;
01580          }
01581       }
01582       break;
01583    case DAHDI_LAW_MULAW:
01584       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01585          if (gain) {
01586             k = (int) (((float) AST_MULAW(j)) * linear_gain);
01587             if (k > 32767) k = 32767;
01588             if (k < -32767) k = -32767;
01589             g->rxgain[j] = AST_LIN2MU(k);
01590          } else {
01591             g->rxgain[j] = j;
01592          }
01593       }
01594       break;
01595    }
01596 }

static void fill_txgain ( struct dahdi_gains *  g,
float  gain,
int  law 
) [static]

Definition at line 1530 of file chan_dahdi.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_txgain().

01531 {
01532    int j;
01533    int k;
01534    float linear_gain = pow(10.0, gain / 20.0);
01535 
01536    switch (law) {
01537    case DAHDI_LAW_ALAW:
01538       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01539          if (gain) {
01540             k = (int) (((float) AST_ALAW(j)) * linear_gain);
01541             if (k > 32767) k = 32767;
01542             if (k < -32767) k = -32767;
01543             g->txgain[j] = AST_LIN2A(k);
01544          } else {
01545             g->txgain[j] = j;
01546          }
01547       }
01548       break;
01549    case DAHDI_LAW_MULAW:
01550       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01551          if (gain) {
01552             k = (int) (((float) AST_MULAW(j)) * linear_gain);
01553             if (k > 32767) k = 32767;
01554             if (k < -32767) k = -32767;
01555             g->txgain[j] = AST_LIN2MU(k);
01556          } else {
01557             g->txgain[j] = j;
01558          }
01559       }
01560       break;
01561    }
01562 }

static struct dahdi_pvt* find_channel ( int  channel  )  [static]

Definition at line 10602 of file chan_dahdi.c.

References dahdi_pvt::channel, iflist, and dahdi_pvt::next.

Referenced by __action_dialoffhook(), __action_dnd(), __action_transfer(), and __action_transferhangup().

10603 {
10604    struct dahdi_pvt *p = iflist;
10605    while (p) {
10606       if (p->channel == channel) {
10607          break;
10608       }
10609       p = p->next;
10610    }
10611    return p;
10612 }

static int get_alarms ( struct dahdi_pvt p  )  [static]

Definition at line 3675 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, errno, dahdi_pvt::span, SUB_REAL, and dahdi_pvt::subs.

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

03676 {
03677    int res;
03678    struct dahdi_spaninfo zi;
03679 #if defined(HAVE_DAHDI) || defined(HAVE_ZAPTEL_CHANALARMS)
03680    /*
03681     * The conditional compilation is needed only in asterisk-1.4 for
03682     * backward compatibility with old zaptel drivers that don't have
03683     * a DAHDI_PARAMS.chan_alarms field.
03684     */
03685    struct dahdi_params params;
03686 #endif
03687 
03688    memset(&zi, 0, sizeof(zi));
03689    zi.spanno = p->span;
03690 
03691    /* First check for span alarms */
03692    if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) {
03693       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
03694       return 0;
03695    }
03696    if (zi.alarms != DAHDI_ALARM_NONE)
03697       return zi.alarms;
03698 #if defined(HAVE_DAHDI) || defined(HAVE_ZAPTEL_CHANALARMS)
03699    /* No alarms on the span. Check for channel alarms. */
03700    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
03701       return params.chan_alarms;
03702    /* ioctl failed */
03703    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
03704 #endif
03705    return DAHDI_ALARM_NONE;
03706 }

static void handle_alarms ( struct dahdi_pvt p,
int  alarms 
) [static]

Definition at line 3779 of file chan_dahdi.c.

References alarm2str(), ast_log(), dahdi_pvt::channel, EVENT_FLAG_SYSTEM, manager_event(), and dahdi_pvt::unknown_alarm.

Referenced by dahdi_handle_event(), and handle_init_event().

03780 {
03781    const char *alarm_str = alarm2str(alarms);
03782    
03783    /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code
03784     * doesn't know what to do with it.  Don't confuse users with log messages. */
03785    if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
03786       p->unknown_alarm = 1;
03787       return;
03788    } else {
03789       p->unknown_alarm = 0;
03790    }
03791    
03792    ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
03793    manager_event(EVENT_FLAG_SYSTEM, "Alarm",
03794             "Alarm: %s\r\n"
03795             "Channel: %d\r\n",
03796             alarm_str, p->channel);
03797 }

static int handle_dahdi_show_cadences ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 10409 of file chan_dahdi.c.

References ast_cli(), COLOR_BLACK, COLOR_GREEN, COLOR_MAGENTA, and term_color().

10410 {
10411    int i, j;
10412    for (i = 0; i < num_cadence; i++) {
10413       char output[1024];
10414       char tmp[16], tmp2[64];
10415       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
10416       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
10417 
10418       for (j = 0; j < 16; j++) {
10419          if (cadences[i].ringcadence[j] == 0)
10420             break;
10421          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
10422          if (cidrings[i] * 2 - 1 == j)
10423             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
10424          else
10425             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
10426          if (j != 0)
10427             strncat(output, ",", sizeof(output) - strlen(output) - 1);
10428          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
10429       }
10430       ast_cli(fd,"%s\n",output);
10431    }
10432    return 0;
10433 }

static int handle_init_event ( struct dahdi_pvt i,
int  event 
) [static]

Definition at line 6741 of file chan_dahdi.c.

References ast_hangup(), ast_log(), ast_pthread_create, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, ast_verbose(), dahdi_pvt::channel, dahdi_pvt::cid_start, CID_START_POLARITY, dahdi_pvt::cidspill, dahdi_destroy_channel_bynum(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_new(), dahdi_set_hook(), errno, EVENT_FLAG_SYSTEM, free, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::immediate, dahdi_pvt::inalarm, LOG_NOTICE, manager_event(), dahdi_pvt::polarity, POLARITY_REV, dahdi_pvt::radio, 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_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, ss_thread(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::unknown_alarm, and VERBOSE_PREFIX_2.

06742 {
06743    int res;
06744    pthread_t threadid;
06745    pthread_attr_t attr;
06746    struct ast_channel *chan;
06747    pthread_attr_init(&attr);
06748    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06749    /* Handle an event on a given channel for the monitor thread. */
06750    switch (event) {
06751    case DAHDI_EVENT_NONE:
06752    case DAHDI_EVENT_BITSCHANGED:
06753       break;
06754    case DAHDI_EVENT_WINKFLASH:
06755    case DAHDI_EVENT_RINGOFFHOOK:
06756       if (i->inalarm) break;
06757       if (i->radio) break;
06758       /* Got a ring/answer.  What kind of channel are we? */
06759       switch (i->sig) {
06760       case SIG_FXOLS:
06761       case SIG_FXOGS:
06762       case SIG_FXOKS:
06763          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06764          if (res && (errno == EBUSY))
06765             break;
06766          if (i->cidspill) {
06767             /* Cancel VMWI spill */
06768             free(i->cidspill);
06769             i->cidspill = NULL;
06770          }
06771          if (i->immediate) {
06772             dahdi_enable_ec(i);
06773             /* The channel is immediately up.  Start right away */
06774             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06775             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
06776             if (!chan) {
06777                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
06778                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06779                if (res < 0)
06780                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06781             }
06782          } else {
06783             /* Check for callerid, digits, etc */
06784             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
06785             if (chan) {
06786                if (has_voicemail(i))
06787                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
06788                else
06789                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
06790                if (res < 0) 
06791                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
06792                if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06793                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06794                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06795                   if (res < 0)
06796                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06797                   ast_hangup(chan);
06798                }
06799             } else
06800                ast_log(LOG_WARNING, "Unable to create channel\n");
06801          }
06802          break;
06803       case SIG_FXSLS:
06804       case SIG_FXSGS:
06805       case SIG_FXSKS:
06806             i->ringt = i->ringt_base;
06807             /* Fall through */
06808       case SIG_EMWINK:
06809       case SIG_FEATD:
06810       case SIG_FEATDMF:
06811       case SIG_FEATDMF_TA:
06812       case SIG_E911:
06813       case SIG_FGC_CAMA:
06814       case SIG_FGC_CAMAMF:
06815       case SIG_FEATB:
06816       case SIG_EM:
06817       case SIG_EM_E1:
06818       case SIG_SFWINK:
06819       case SIG_SF_FEATD:
06820       case SIG_SF_FEATDMF:
06821       case SIG_SF_FEATB:
06822       case SIG_SF:
06823             /* Check for callerid, digits, etc */
06824             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
06825             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06826                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06827                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06828                if (res < 0)
06829                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06830                ast_hangup(chan);
06831             } else if (!chan) {
06832                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
06833             }
06834             break;
06835       default:
06836          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
06837          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06838          if (res < 0)
06839                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06840          return -1;
06841       }
06842       break;
06843    case DAHDI_EVENT_NOALARM:
06844       i->inalarm = 0;
06845       if (!i->unknown_alarm) {
06846          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
06847          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
06848                   "Channel: %d\r\n", i->channel);
06849       } else {
06850          i->unknown_alarm = 0;
06851       }
06852       break;
06853    case DAHDI_EVENT_ALARM:
06854       i->inalarm = 1;
06855       res = get_alarms(i);
06856       handle_alarms(i, res);
06857       /* fall thru intentionally */
06858    case DAHDI_EVENT_ONHOOK:
06859       if (i->radio)
06860          break;
06861       /* Back on hook.  Hang up. */
06862       switch (i->sig) {
06863       case SIG_FXOLS:
06864       case SIG_FXOGS:
06865       case SIG_FEATD:
06866       case SIG_FEATDMF:
06867       case SIG_FEATDMF_TA:
06868       case SIG_E911:
06869       case SIG_FGC_CAMA:
06870       case SIG_FGC_CAMAMF:
06871       case SIG_FEATB:
06872       case SIG_EM:
06873       case SIG_EM_E1:
06874       case SIG_EMWINK:
06875       case SIG_SF_FEATD:
06876       case SIG_SF_FEATDMF:
06877       case SIG_SF_FEATB:
06878       case SIG_SF:
06879       case SIG_SFWINK:
06880       case SIG_FXSLS:
06881       case SIG_FXSGS:
06882       case SIG_FXSKS:
06883       case SIG_GR303FXSKS:
06884          dahdi_disable_ec(i);
06885          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
06886          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06887          break;
06888       case SIG_GR303FXOKS:
06889       case SIG_FXOKS:
06890          dahdi_disable_ec(i);
06891          /* Diddle the battery for the zhone */
06892 #ifdef ZHONE_HACK
06893          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06894          usleep(1);
06895 #endif         
06896          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
06897          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06898          break;
06899       case SIG_PRI:
06900          dahdi_disable_ec(i);
06901          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
06902          break;
06903       default:
06904          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
06905          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
06906          return -1;
06907       }
06908       break;
06909    case DAHDI_EVENT_POLARITY:
06910       switch (i->sig) {
06911       case SIG_FXSLS:
06912       case SIG_FXSKS:
06913       case SIG_FXSGS:
06914          /* We have already got a PR before the channel was 
06915             created, but it wasn't handled. We need polarity 
06916             to be REV for remote hangup detection to work. 
06917             At least in Spain */
06918          if (i->hanguponpolarityswitch)
06919             i->polarity = POLARITY_REV;
06920 
06921          if (i->cid_start == CID_START_POLARITY) {
06922             i->polarity = POLARITY_REV;
06923             ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
06924                    "CID detection on channel %d\n",
06925                    i->channel);
06926             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
06927             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06928                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06929             }
06930          }
06931          break;
06932       default:
06933          ast_log(LOG_WARNING, "handle_init_event detected "
06934             "polarity reversal on non-FXO (SIG_FXS) "
06935             "interface %d\n", i->channel);
06936       }
06937       break;
06938    case DAHDI_EVENT_REMOVED: /* destroy channel */
06939       ast_log(LOG_NOTICE, 
06940             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 
06941             i->channel);
06942       dahdi_destroy_channel_bynum(i->channel);
06943       break;
06944    }
06945    pthread_attr_destroy(&attr);
06946    return 0;
06947 }

static int has_voicemail ( struct dahdi_pvt p  )  [static]

Definition at line 1762 of file chan_dahdi.c.

References ast_app_has_voicemail(), and dahdi_pvt::mailbox.

Referenced by dahdi_handle_event(), do_monitor(), handle_hd_hf(), handle_init_event(), handle_request(), load_module(), mgcp_hangup(), mgcp_request(), and vm_execmain().

01763 {
01764 
01765    return ast_app_has_voicemail(p->mailbox, NULL);
01766 }

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

Definition at line 1318 of file chan_dahdi.c.

References dahdi_pvt::channel, dahdi_pvt::confno, and dahdi_subchannel::curconf.

Referenced by conf_del().

01319 {
01320    /* If they're listening to our channel, they're ours */  
01321    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
01322       return 1;
01323    /* If they're a talker on our (allocated) conference, they're ours */
01324    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
01325       return 1;
01326    return 0;
01327 }

static int isslavenative ( struct dahdi_pvt p,
struct dahdi_pvt **  out 
) [static]

Definition at line 1351 of file chan_dahdi.c.

References dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, MAX_SLAVES, dahdi_pvt::slaves, and dahdi_pvt::subs.

Referenced by update_conf().

01352 {
01353    int x;
01354    int useslavenative;
01355    struct dahdi_pvt *slave = NULL;
01356    /* Start out optimistic */
01357    useslavenative = 1;
01358    /* Update conference state in a stateless fashion */
01359    for (x = 0; x < 3; x++) {
01360       /* Any three-way calling makes slave native mode *definitely* out
01361          of the question */
01362       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
01363          useslavenative = 0;
01364    }
01365    /* If we don't have any 3-way calls, check to see if we have
01366       precisely one slave */
01367    if (useslavenative) {
01368       for (x = 0; x < MAX_SLAVES; x++) {
01369          if (p->slaves[x]) {
01370             if (slave) {
01371                /* Whoops already have a slave!  No 
01372                   slave native and stop right away */
01373                slave = NULL;
01374                useslavenative = 0;
01375                break;
01376             } else {
01377                /* We have one slave so far */
01378                slave = p->slaves[x];
01379             }
01380          }
01381       }
01382    }
01383    /* If no slave, slave native definitely out */
01384    if (!slave)
01385       useslavenative = 0;
01386    else if (slave->law != p->law) {
01387       useslavenative = 0;
01388       slave = NULL;
01389    }
01390    if (out)
01391       *out = slave;
01392    return useslavenative;
01393 }

static int load_module ( void   )  [static]

Definition at line 11864 of file chan_dahdi.c.

References __unload_module(), ast_channel_register(), ast_cli_register_multiple(), ast_cond_init(), ast_log(), AST_MODULE_LOAD_DECLINE, ast_mutex_init(), AST_PTHREADT_NULL, ast_register_application(), ast_string_field_init, ast_string_field_set, CHAN_DAHDI_PLUS_ZAP_MODE, chan_tech, dahdi_chan_mode, dahdi_cli, dahdi_tech, inuse, local_astman_register, lock, LOG_ERROR, name, round_robin, setup_dahdi(), ast_channel_tech::type, and zap_tech.

11865 {
11866    int res;
11867 
11868 #ifdef HAVE_PRI
11869    int y,i;
11870    memset(pris, 0, sizeof(pris));
11871    for (y = 0; y < NUM_SPANS; y++) {
11872       ast_mutex_init(&pris[y].lock);
11873       pris[y].offset = -1;
11874       pris[y].master = AST_PTHREADT_NULL;
11875       for (i = 0; i < NUM_DCHANS; i++)
11876          pris[y].fds[i] = -1;
11877    }
11878    pri_set_error(dahdi_pri_error);
11879    pri_set_message(dahdi_pri_message);
11880    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
11881       ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
11882          dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
11883    }
11884    ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
11885       zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
11886 #endif
11887    if ((res = setup_dahdi(0))) {
11888       return AST_MODULE_LOAD_DECLINE;
11889    }
11890    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
11891       chan_tech = &dahdi_tech;
11892    } else {
11893       chan_tech = &zap_tech;
11894    }
11895    if (ast_channel_register(chan_tech)) {
11896       ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
11897       __unload_module();
11898       return -1;
11899    }
11900 #ifdef HAVE_PRI
11901    ast_string_field_init(&inuse, 16);
11902    ast_string_field_set(&inuse, name, "GR-303InUse");
11903    ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
11904 #endif   
11905    ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
11906    
11907    memset(round_robin, 0, sizeof(round_robin));
11908    local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
11909    local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
11910    local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
11911    local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
11912    local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
11913    local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
11914    local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
11915 
11916    ast_cond_init(&ss_thread_complete, NULL);
11917 
11918    return res;
11919 }

static struct dahdi_pvt* mkintf ( int  channel,
const struct dahdi_chan_conf conf,
struct dahdi_pri *  pri,
int  reloading 
) [static]

Definition at line 7299 of file chan_dahdi.c.

References ast_calloc, ast_log(), ast_mutex_init(), ast_strlen_zero(), dahdi_chan_conf::chan, CHAN_PSEUDO, dahdi_open(), destroy_dahdi_pvt(), errno, free, iflist, LOG_ERROR, MAX_CHANNELS, dahdi_pvt::next, dahdi_pvt::prev, dahdi_pvt::sig, sig2str, SIG_FXOKS, SIG_FXSKS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, and SUB_REAL.

Referenced by build_channels().

07300 {
07301    /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
07302    struct dahdi_pvt *tmp = NULL, *tmp2,  *prev = NULL;
07303    char fn[80];
07304 #if 1
07305    struct dahdi_bufferinfo bi;
07306 #endif
07307    int res;
07308    int span=0;
07309    int here = 0;
07310    int x;
07311    struct dahdi_pvt **wlist;
07312    struct dahdi_pvt **wend;
07313    struct dahdi_params p;
07314 
07315    wlist = &iflist;
07316    wend = &ifend;
07317 
07318 #ifdef HAVE_PRI
07319    if (pri) {
07320       wlist = &pri->crvs;
07321       wend = &pri->crvend;
07322    }
07323 #endif
07324 
07325    tmp2 = *wlist;
07326    prev = NULL;
07327 
07328    while (tmp2) {
07329       if (!tmp2->destroy) {
07330          if (tmp2->channel == channel) {
07331             tmp = tmp2;
07332             here = 1;
07333             break;
07334          }
07335          if (tmp2->channel > channel) {
07336             break;
07337          }
07338       }
07339       prev = tmp2;
07340       tmp2 = tmp2->next;
07341    }
07342 
07343    if (!here && reloading != 1) {
07344       if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
07345          if (tmp)
07346             free(tmp);
07347          return NULL;
07348       }
07349       ast_mutex_init(&tmp->lock);
07350       ifcount++;
07351       for (x = 0; x < 3; x++)
07352          tmp->subs[x].dfd = -1;
07353       tmp->channel = channel;
07354    }
07355 
07356    if (tmp) {
07357       int chan_sig = conf->chan.sig;
07358       if (!here) {
07359          if ((channel != CHAN_PSEUDO) && !pri) {
07360             int count = 0;
07361             snprintf(fn, sizeof(fn), "%d", channel);
07362             /* Open non-blocking */
07363             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
07364             while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) { /* the kernel may not call dahdi_release fast enough for the open flagbit to be cleared in time */
07365                usleep(1);
07366                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
07367                count++;
07368             }
07369             /* Allocate a DAHDI structure */
07370             if (tmp->subs[SUB_REAL].dfd < 0) {
07371                ast_log(LOG_ERROR, "Unable to open channel %d: %s\nhere = %d, tmp->channel = %d, channel = %d\n", channel, strerror(errno), here, tmp->channel, channel);
07372                destroy_dahdi_pvt(&tmp);
07373                return NULL;
07374             }
07375             memset(&p, 0, sizeof(p));
07376             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
07377             if (res < 0) {
07378                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
07379                destroy_dahdi_pvt(&tmp);
07380                return NULL;
07381             }
07382             if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
07383                ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(conf->chan.sig), sig2str(p.sigtype));
07384                destroy_dahdi_pvt(&tmp);
07385                return NULL;
07386             }
07387             tmp->law = p.curlaw;
07388             tmp->span = p.spanno;
07389             span = p.spanno - 1;
07390          } else {
07391             if (channel == CHAN_PSEUDO)
07392                chan_sig = 0;
07393             else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
07394                ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
07395                return NULL;
07396             }
07397          }
07398 #ifdef HAVE_PRI
07399          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
07400             int offset;
07401             int myswitchtype;
07402             int matchesdchan;
07403             int x,y;
07404             offset = 0;
07405             if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
07406                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
07407                destroy_dahdi_pvt(&tmp);
07408                return NULL;
07409             }
07410             if (span >= NUM_SPANS) {
07411                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
07412                destroy_dahdi_pvt(&tmp);
07413                return NULL;
07414             } else {
07415                struct dahdi_spaninfo si;
07416                si.spanno = 0;
07417                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
07418                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
07419                   destroy_dahdi_pvt(&tmp);
07420                   return NULL;
07421                }
07422                /* Store the logical span first based upon the real span */
07423                tmp->logicalspan = pris[span].prilogicalspan;
07424                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
07425                if (span < 0) {
07426                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
07427                   destroy_dahdi_pvt(&tmp);
07428                   return NULL;
07429                }
07430                if (chan_sig == SIG_PRI)
07431                   myswitchtype = conf->pri.switchtype;
07432                else
07433                   myswitchtype = PRI_SWITCH_GR303_TMC;
07434                /* Make sure this isn't a d-channel */
07435                matchesdchan=0;
07436                for (x = 0; x < NUM_SPANS; x++) {
07437                   for (y = 0; y < NUM_DCHANS; y++) {
07438                      if (pris[x].dchannels[y] == tmp->channel) {
07439                         matchesdchan = 1;
07440                         break;
07441                      }
07442                   }
07443                }
07444                offset = p.chanpos;
07445                if (!matchesdchan) {
07446                   if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
07447                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
07448                      destroy_dahdi_pvt(&tmp);
07449                      return NULL;
07450                   }
07451                   if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
07452                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
07453                      destroy_dahdi_pvt(&tmp);
07454                      return NULL;
07455                   }
07456                   if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
07457                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
07458                      destroy_dahdi_pvt(&tmp);
07459                      return NULL;
07460                   }
07461                   if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
07462                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
07463                      destroy_dahdi_pvt(&tmp);
07464                      return NULL;
07465                   }
07466                   if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
07467                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
07468                      destroy_dahdi_pvt(&tmp);
07469                      return NULL;
07470                   }
07471                   if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
07472                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
07473                      destroy_dahdi_pvt(&tmp);
07474                      return NULL;
07475                   }
07476                   if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
07477                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
07478                      destroy_dahdi_pvt(&tmp);
07479                      return NULL;
07480                   }
07481                   if (pris[span].numchans >= MAX_CHANNELS) {
07482                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
07483                         pris[span].trunkgroup);
07484                      destroy_dahdi_pvt(&tmp);
07485                      return NULL;
07486                   }
07487                   pris[span].nodetype = conf->pri.nodetype;
07488                   pris[span].switchtype = myswitchtype;
07489                   pris[span].nsf = conf->pri.nsf;
07490                   pris[span].dialplan = conf->pri.dialplan;
07491                   pris[span].localdialplan = conf->pri.localdialplan;
07492                   pris[span].pvts[pris[span].numchans++] = tmp;
07493                   pris[span].minunused = conf->pri.minunused;
07494                   pris[span].minidle = conf->pri.minidle;
07495                   pris[span].overlapdial = conf->pri.overlapdial;
07496 #ifdef HAVE_PRI_INBANDDISCONNECT
07497                   pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
07498 #endif
07499                   pris[span].facilityenable = conf->pri.facilityenable;
07500                   ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
07501                   ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
07502                   ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
07503                   ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
07504                   ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
07505                   ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
07506                   ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
07507                   pris[span].resetinterval = conf->pri.resetinterval;
07508                   
07509                   tmp->pri = &pris[span];
07510                   tmp->prioffset = offset;
07511                   tmp->call = NULL;
07512                } else {
07513                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
07514                   destroy_dahdi_pvt(&tmp);
07515                   return NULL;
07516                }
07517             }
07518          } else {
07519             tmp->prioffset = 0;
07520          }
07521 #endif
07522       } else {
07523          chan_sig = tmp->sig;
07524          memset(&p, 0, sizeof(p));
07525          if (tmp->subs[SUB_REAL].dfd > -1)
07526             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
07527       }
07528       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
07529       switch (chan_sig) {
07530       case SIG_FXSKS:
07531       case SIG_FXSLS:
07532       case SIG_EM:
07533       case SIG_EM_E1:
07534       case SIG_EMWINK:
07535       case SIG_FEATD:
07536       case SIG_FEATDMF:
07537       case SIG_FEATDMF_TA:
07538       case SIG_FEATB:
07539       case SIG_E911:
07540       case SIG_SF:
07541       case SIG_SFWINK:
07542       case SIG_FGC_CAMA:
07543       case SIG_FGC_CAMAMF:
07544       case SIG_SF_FEATD:
07545       case SIG_SF_FEATDMF:
07546       case SIG_SF_FEATB:
07547          p.starttime = 250;
07548          break;
07549       }
07550 
07551       if (tmp->radio) {
07552          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
07553          p.channo = channel;
07554          p.rxwinktime = 1;
07555          p.rxflashtime = 1;
07556          p.starttime = 1;
07557          p.debouncetime = 5;
07558       }
07559       if (!tmp->radio) {
07560          p.channo = channel;
07561          /* Override timing settings based on config file */
07562          if (conf->timing.prewinktime >= 0)
07563             p.prewinktime = conf->timing.prewinktime;
07564          if (conf->timing.preflashtime >= 0)
07565             p.preflashtime = conf->timing.preflashtime;
07566          if (conf->timing.winktime >= 0)
07567             p.winktime = conf->timing.winktime;
07568          if (conf->timing.flashtime >= 0)
07569             p.flashtime = conf->timing.flashtime;
07570          if (conf->timing.starttime >= 0)
07571             p.starttime = conf->timing.starttime;
07572          if (conf->timing.rxwinktime >= 0)
07573             p.rxwinktime = conf->timing.rxwinktime;
07574          if (conf->timing.rxflashtime >= 0)
07575             p.rxflashtime = conf->timing.rxflashtime;
07576          if (conf->timing.debouncetime >= 0)
07577             p.debouncetime = conf->timing.debouncetime;
07578       }
07579       
07580       /* dont set parms on a pseudo-channel (or CRV) */
07581       if (tmp->subs[SUB_REAL].dfd >= 0)
07582       {
07583          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
07584          if (res < 0) {
07585             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
07586             destroy_dahdi_pvt(&tmp);
07587             return NULL;
07588          }
07589       }
07590 #if 1
07591       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
07592          memset(&bi, 0, sizeof(bi));
07593          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
07594          if (!res) {
07595             bi.txbufpolicy = conf->chan.buf_policy;
07596             bi.rxbufpolicy = conf->chan.buf_policy;
07597             bi.numbufs = conf->chan.buf_no;
07598             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
07599             if (res < 0) {
07600                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
07601             }
07602          } else
07603             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
07604       }
07605 #endif
07606       tmp->immediate = conf->chan.immediate;
07607       tmp->transfertobusy = conf->chan.transfertobusy;
07608       tmp->sig = chan_sig;
07609       tmp->outsigmod = conf->chan.outsigmod;
07610       tmp->ringt_base = ringt_base;
07611       tmp->firstradio = 0;
07612       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
07613          tmp->permcallwaiting = conf->chan.callwaiting;
07614       else
07615          tmp->permcallwaiting = 0;
07616       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
07617       tmp->destroy = 0;
07618       tmp->drings = drings;
07619       tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
07620       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
07621       tmp->threewaycalling = conf->chan.threewaycalling;
07622       tmp->adsi = conf->chan.adsi;
07623       tmp->use_smdi = conf->chan.use_smdi;
07624       tmp->permhidecallerid = conf->chan.hidecallerid;
07625       tmp->callreturn = conf->chan.callreturn;
07626       tmp->echocancel = conf->chan.echocancel;
07627       tmp->echotraining = conf->chan.echotraining;
07628       tmp->pulse = conf->chan.pulse;
07629       if (tmp->echocancel)
07630          tmp->echocanbridged = conf->chan.echocanbridged;
07631       else {
07632          if (conf->chan.echocanbridged)
07633             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
07634          tmp->echocanbridged = 0;
07635       }
07636       tmp->busydetect = conf->chan.busydetect;
07637       tmp->busycount = conf->chan.busycount;
07638       tmp->busycompare = conf->chan.busycompare;
07639       tmp->busytonelength = conf->chan.busytonelength;
07640       tmp->busyquietlength = conf->chan.busyquietlength;
07641       tmp->busyfuzziness = conf->chan.busyfuzziness;
07642       tmp->silencethreshold = conf->chan.silencethreshold;
07643       tmp->callprogress = conf->chan.callprogress;
07644       tmp->cancallforward = conf->chan.cancallforward;
07645       tmp->dtmfrelax = conf->chan.dtmfrelax;
07646       tmp->callwaiting = tmp->permcallwaiting;
07647       tmp->hidecallerid = tmp->permhidecallerid;
07648       tmp->channel = channel;
07649       tmp->stripmsd = conf->chan.stripmsd;
07650       tmp->use_callerid = conf->chan.use_callerid;
07651       tmp->cid_signalling = conf->chan.cid_signalling;
07652       tmp->cid_start = conf->chan.cid_start;
07653       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
07654       tmp->restrictcid = conf->chan.restrictcid;
07655       tmp->use_callingpres = conf->chan.use_callingpres;
07656       tmp->priindication_oob = conf->chan.priindication_oob;
07657       tmp->priexclusive = conf->chan.priexclusive;
07658       if (tmp->usedistinctiveringdetection) {
07659          if (!tmp->use_callerid) {
07660             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
07661             tmp->use_callerid = 1;
07662          }
07663       }
07664 
07665       if (tmp->cid_signalling == CID_SIG_SMDI) {
07666          if (!tmp->use_smdi) {
07667             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
07668             tmp->use_smdi = 1;
07669          }
07670       }
07671       if (tmp->use_smdi) {
07672          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
07673          if (!(tmp->smdi_iface)) {
07674             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
07675             tmp->use_smdi = 0;
07676          }
07677       }
07678 
07679       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
07680       tmp->amaflags = conf->chan.amaflags;
07681       if (!here) {
07682          tmp->confno = -1;
07683          tmp->propconfno = -1;
07684       }
07685       tmp->canpark = conf->chan.canpark;
07686       tmp->transfer = conf->chan.transfer;
07687       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
07688       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
07689       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
07690       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
07691       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
07692       ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
07693       tmp->cid_ton = 0;
07694       ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
07695       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
07696       tmp->msgstate = -1;
07697       tmp->group = conf->chan.group;
07698       tmp->callgroup = conf->chan.callgroup;
07699       tmp->pickupgroup= conf->chan.pickupgroup;
07700       tmp->rxgain = conf->chan.rxgain;
07701       tmp->txgain = conf->chan.txgain;
07702       tmp->tonezone = conf->chan.tonezone;
07703       tmp->onhooktime = time(NULL);
07704       if (tmp->subs[SUB_REAL].dfd > -1) {
07705          set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
07706          if (tmp->dsp)
07707             ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
07708          update_conf(tmp);
07709          if (!here) {
07710             if (chan_sig != SIG_PRI)
07711                /* Hang it up to be sure it's good */
07712                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07713          }
07714          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
07715 #ifdef HAVE_PRI
07716          /* the dchannel is down so put the channel in alarm */
07717          if (tmp->pri && !pri_is_up(tmp->pri)) {
07718             tmp->inalarm = 1;
07719          }
07720 #endif            
07721          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
07722             tmp->inalarm = 1;
07723             handle_alarms(tmp, res);
07724          } else {
07725             /* yes, this looks strange... the unknown_alarm flag is only used to
07726                control whether an 'alarm cleared' message gets generated when we
07727                get an indication that the channel is no longer in alarm status.
07728                however, the channel *could* be in an alarm status that we aren't
07729                aware of (since get_alarms() only reports span alarms, not channel
07730                alarms). setting this flag will cause any potential 'alarm cleared'
07731                message to be suppressed, but if a real alarm occurs before that
07732                happens, this flag will get cleared by it and the situation will
07733                be normal.
07734             */
07735             tmp->unknown_alarm = 1;
07736          }
07737       }
07738 
07739       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
07740       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
07741       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
07742       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
07743 
07744    }
07745    if (tmp && !here) {
07746       /* nothing on the iflist */
07747       if (!*wlist) {
07748          *wlist = tmp;
07749          tmp->prev = NULL;
07750          tmp->next = NULL;
07751          *wend = tmp;
07752       } else {
07753          /* at least one member on the iflist */
07754          struct dahdi_pvt *working = *wlist;
07755 
07756          /* check if we maybe have to put it on the begining */
07757          if (working->channel > tmp->channel) {
07758             tmp->next = *wlist;
07759             tmp->prev = NULL;
07760             (*wlist)->prev = tmp;
07761             *wlist = tmp;
07762          } else {
07763          /* go through all the members and put the member in the right place */
07764             while (working) {
07765                /* in the middle */
07766                if (working->next) {
07767                   if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
07768                      tmp->next = working->next;
07769                      tmp->prev = working;
07770                      working->next->prev = tmp;
07771                      working->next = tmp;
07772                      break;
07773                   }
07774                } else {
07775                /* the last */
07776                   if (working->channel < tmp->channel) {
07777                      working->next = tmp;
07778                      tmp->next = NULL;
07779                      tmp->prev = working;
07780                      *wend = tmp;
07781                      break;
07782                   }
07783                }
07784                working = working->next;
07785             }
07786          }
07787       }
07788    }
07789    return tmp;
07790 }

static int my_dahdi_write ( struct dahdi_pvt p,
unsigned char *  buf,
int  len,
int  index,
int  linear 
) [static]

Definition at line 5047 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, errno, LOG_DEBUG, option_debug, READ_SIZE, and dahdi_pvt::subs.

Referenced by dahdi_write().

05048 {
05049    int sent=0;
05050    int size;
05051    int res;
05052    int fd;
05053    fd = p->subs[index].dfd;
05054    while (len) {
05055       size = len;
05056       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
05057          size = (linear ? READ_SIZE * 2 : READ_SIZE);
05058       res = write(fd, buf, size);
05059       if (res != size) {
05060          if (option_debug)
05061             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05062          return sent;
05063       }
05064       len -= size;
05065       buf += size;
05066    }
05067    return sent;
05068 }

static int my_getsigstr ( struct ast_channel chan,
char *  str,
const char *  term,
int  ms 
) [static]

Definition at line 5524 of file chan_dahdi.c.

References ast_waitfordigit().

Referenced by ss_thread().

05525 {
05526    char c;
05527 
05528    *str = 0; /* start with empty output buffer */
05529    for (;;)
05530    {
05531       /* Wait for the first digit (up to specified ms). */
05532       c = ast_waitfordigit(chan, ms);
05533       /* if timeout, hangup or error, return as such */
05534       if (c < 1)
05535          return c;
05536       *str++ = c;
05537       *str = 0;
05538       if (strchr(term, c))
05539          return 1;
05540    }
05541 }

static int process_dahdi ( struct dahdi_chan_conf confp,
const char *  cat,
struct ast_variable v,
int  reload,
int  skipchannels 
) [static]

Definition at line 11003 of file chan_dahdi.c.

References dahdi_pvt::accountcode, dahdi_pvt::adsi, dahdi_pvt::amaflags, dahdi_pvt::answeronpolarityswitch, ast_callerid_split(), ast_cdr_amaflags2int(), ast_get_group(), ast_jb_read_conf(), ast_log(), ast_strlen_zero(), ast_true(), ast_verbose(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, build_channels(), dahdi_pvt::busycompare, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::callgroup, dahdi_pvt::callprogress, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, dahdi_pvt::cancallforward, dahdi_pvt::canpark, dahdi_chan_conf::chan, dahdi_pvt::cid_name, dahdi_pvt::cid_num, CID_SIG_BELL, CID_SIG_DTMF, CID_SIG_SMDI, CID_SIG_V23, CID_SIG_V23_JP, dahdi_pvt::cid_signalling, dahdi_pvt::cid_start, CID_START_POLARITY, CID_START_RING, dahdi_pvt::context, ringContextData::contextData, dahdi_pvt::dahditrcallerid, drings, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echotraining, global_jbconf, dahdi_pvt::group, dahdi_pvt::hanguponpolarityswitch, HAVE_PRI, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pvt::immediate, dahdi_pvt::language, ast_variable::lineno, LOG_ERROR, dahdi_pvt::mailbox, MAX_CHANLIST_LEN, dahdi_pvt::mohinterpret, dahdi_pvt::mohsuggest, ast_variable::name, ast_variable::next, option_verbose, dahdi_pvt::outsigmod, dahdi_pvt::pickupgroup, dahdi_pvt::polarityonanswerdelay, dahdi_pvt::priexclusive, dahdi_pvt::priindication_oob, dahdi_pvt::pulse, dahdi_pvt::radio, READ_SIZE, dahdi_pvt::restrictcid, distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::rxgain, dahdi_pvt::sendcalleridafter, dahdi_pvt::sig, 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_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SFWINK, dahdi_pvt::silencethreshold, dahdi_chan_conf::smdi_port, dahdi_pvt::stripmsd, strsep(), dahdi_pvt::threewaycalling, dahdi_chan_conf::timing, dahdi_pvt::tonezone, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, dahdi_pvt::txgain, dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, dahdi_pvt::use_smdi, dahdi_pvt::usedistinctiveringdetection, ast_variable::value, and VERBOSE_PREFIX_3.

Referenced by setup_dahdi().

11004 {
11005    struct dahdi_pvt *tmp;
11006    int y;
11007    int found_pseudo = 0;
11008         char dahdichan[MAX_CHANLIST_LEN] = {};
11009 
11010    for (; v; v = v->next) {
11011       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
11012          continue;
11013 
11014       /* Create the interface list */
11015       if (!strcasecmp(v->name, "channel")
11016 #ifdef HAVE_PRI
11017           || !strcasecmp(v->name, "crv")
11018 #endif         
11019          ) {
11020          int iscrv;
11021          if (skipchannels)
11022             continue;
11023          iscrv = !strcasecmp(v->name, "crv");
11024          if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
11025                return -1;
11026       } else if (!strcasecmp(v->name, "buffers")) {
11027          int res;
11028          char policy[8] = "";
11029          res = sscanf(v->value, "%d,%s", &confp->chan.buf_no, policy);
11030          if (res != 2) {
11031             ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
11032             confp->chan.buf_no = numbufs;
11033             continue;
11034          }
11035          if (confp->chan.buf_no < 0)
11036             confp->chan.buf_no = numbufs;
11037          if (!strcasecmp(policy, "full")) {
11038             confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
11039          } else if (!strcasecmp(policy, "half")) {
11040             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE /* TODO: change to HALF_FULL */;
11041          } else if (!strcasecmp(policy, "immediate")) {
11042             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
11043          } else {
11044             ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
11045          }
11046       } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) {
11047          ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
11048          if (v->name[0] == 'z' || v->name[0] == 'Z') {
11049             ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat);
11050          }
11051       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
11052          if (ast_true(v->value))
11053             confp->chan.usedistinctiveringdetection = 1;
11054       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
11055          if (ast_true(v->value))
11056             distinctiveringaftercid = 1;
11057       } else if (!strcasecmp(v->name, "dring1context")) {
11058          ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
11059       } else if (!strcasecmp(v->name, "dring2context")) {
11060          ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
11061       } else if (!strcasecmp(v->name, "dring3context")) {
11062          ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
11063       } else if (!strcasecmp(v->name, "dring1")) {
11064          sscanf(v->value, "%d,%d,%d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
11065       } else if (!strcasecmp(v->name, "dring2")) {
11066          sscanf(v->value, "%d,%d,%d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
11067       } else if (!strcasecmp(v->name, "dring3")) {
11068          sscanf(v->value, "%d,%d,%d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
11069       } else if (!strcasecmp(v->name, "usecallerid")) {
11070          confp->chan.use_callerid = ast_true(v->value);
11071       } else if (!strcasecmp(v->name, "cidsignalling")) {
11072          if (!strcasecmp(v->value, "bell"))
11073             confp->chan.cid_signalling = CID_SIG_BELL;
11074          else if (!strcasecmp(v->value, "v23"))
11075             confp->chan.cid_signalling = CID_SIG_V23;
11076          else if (!strcasecmp(v->value, "dtmf"))
11077             confp->chan.cid_signalling = CID_SIG_DTMF;
11078          else if (!strcasecmp(v->value, "smdi"))
11079             confp->chan.cid_signalling = CID_SIG_SMDI;
11080          else if (!strcasecmp(v->value, "v23_jp"))
11081             confp->chan.cid_signalling = CID_SIG_V23_JP;
11082          else if (ast_true(v->value))
11083             confp->chan.cid_signalling = CID_SIG_BELL;
11084       } else if (!strcasecmp(v->name, "cidstart")) {
11085          if (!strcasecmp(v->value, "ring"))
11086             confp->chan.cid_start = CID_START_RING;
11087          else if (!strcasecmp(v->value, "polarity"))
11088             confp->chan.cid_start = CID_START_POLARITY;
11089          else if (ast_true(v->value))
11090             confp->chan.cid_start = CID_START_RING;
11091       } else if (!strcasecmp(v->name, "threewaycalling")) {
11092          confp->chan.threewaycalling = ast_true(v->value);
11093       } else if (!strcasecmp(v->name, "cancallforward")) {
11094          confp->chan.cancallforward = ast_true(v->value);
11095       } else if (!strcasecmp(v->name, "relaxdtmf")) {
11096          if (ast_true(v->value)) 
11097             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
11098          else
11099             confp->chan.dtmfrelax = 0;
11100       } else if (!strcasecmp(v->name, "mailbox")) {
11101          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
11102       } else if (!strcasecmp(v->name, "hasvoicemail")) {
11103          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
11104             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
11105          }
11106       } else if (!strcasecmp(v->name, "adsi")) {
11107          confp->chan.adsi = ast_true(v->value);
11108       } else if (!strcasecmp(v->name, "usesmdi")) {
11109          confp->chan.use_smdi = ast_true(v->value);
11110       } else if (!strcasecmp(v->name, "smdiport")) {
11111          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
11112       } else if (!strcasecmp(v->name, "transfer")) {
11113          confp->chan.transfer = ast_true(v->value);
11114       } else if (!strcasecmp(v->name, "canpark")) {
11115          confp->chan.canpark = ast_true(v->value);
11116       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
11117          confp->chan.echocanbridged = ast_true(v->value);
11118       } else if (!strcasecmp(v->name, "busydetect")) {
11119          confp->chan.busydetect = ast_true(v->value);
11120       } else if (!strcasecmp(v->name, "busycount")) {
11121          confp->chan.busycount = atoi(v->value);
11122       } else if (!strcasecmp(v->name, "silencethreshold")) {
11123          confp->chan.silencethreshold = atoi(v->value);
11124       } else if (!strcasecmp(v->name, "busycompare")) {
11125          confp->chan.busycompare = ast_true(v->value);
11126       } else if (!strcasecmp(v->name, "busypattern")) {
11127          int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
11128          if (count == 1)
11129             confp->chan.busyquietlength = 0;
11130          else if (count < 1)
11131             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n");
11132       } else if (!strcasecmp(v->name, "busyfuzziness")) {
11133          confp->chan.busyfuzziness = atoi(v->value);
11134       } else if (!strcasecmp(v->name, "callprogress")) {
11135          if (ast_true(v->value))
11136             confp->chan.callprogress |= 1;
11137          else
11138             confp->chan.callprogress &= ~1;
11139       } else if (!strcasecmp(v->name, "faxdetect")) {
11140          if (!strcasecmp(v->value, "incoming")) {
11141             confp->chan.callprogress |= 4;
11142             confp->chan.callprogress &= ~2;
11143          } else if (!strcasecmp(v->value, "outgoing")) {
11144             confp->chan.callprogress &= ~4;
11145             confp->chan.callprogress |= 2;
11146          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
11147             confp->chan.callprogress |= 6;
11148          else
11149             confp->chan.callprogress &= ~6;
11150       } else if (!strcasecmp(v->name, "echocancel")) {
11151          if (!ast_strlen_zero(v->value)) {
11152             y = atoi(v->value);
11153          } else
11154             y = 0;
11155          if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
11156             confp->chan.echocancel = y;
11157          else {
11158             confp->chan.echocancel = ast_true(v->value);
11159             if (confp->chan.echocancel)
11160                confp->chan.echocancel=128;
11161          }
11162       } else if (!strcasecmp(v->name, "echotraining")) {
11163          if (sscanf(v->value, "%d", &y) == 1) {
11164             if ((y < 10) || (y > 4000)) {
11165                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);              
11166             } else {
11167                confp->chan.echotraining = y;
11168             }
11169          } else if (ast_true(v->value)) {
11170             confp->chan.echotraining = 400;
11171          } else
11172             confp->chan.echotraining = 0;
11173       } else if (!strcasecmp(v->name, "hidecallerid")) {
11174          confp->chan.hidecallerid = ast_true(v->value);
11175       } else if (!strcasecmp(v->name, "hidecalleridname")) {
11176          confp->chan.hidecalleridname = ast_true(v->value);
11177       } else if (!strcasecmp(v->name, "pulsedial")) {
11178          confp->chan.pulse = ast_true(v->value);
11179       } else if (!strcasecmp(v->name, "callreturn")) {
11180          confp->chan.callreturn = ast_true(v->value);
11181       } else if (!strcasecmp(v->name, "callwaiting")) {
11182          confp->chan.callwaiting = ast_true(v->value);
11183       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
11184          confp->chan.callwaitingcallerid = ast_true(v->value);
11185       } else if (!strcasecmp(v->name, "context")) {
11186          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
11187       } else if (!strcasecmp(v->name, "language")) {
11188          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
11189       } else if (!strcasecmp(v->name, "progzone")) {
11190          ast_copy_string(progzone, v->value, sizeof(progzone));
11191       } else if (!strcasecmp(v->name, "mohinterpret") 
11192          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
11193          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
11194       } else if (!strcasecmp(v->name, "mohsuggest")) {
11195          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
11196       } else if (!strcasecmp(v->name, "stripmsd")) {
11197          confp->chan.stripmsd = atoi(v->value);
11198       } else if (!strcasecmp(v->name, "jitterbuffers")) {
11199          numbufs = atoi(v->value);
11200       } else if (!strcasecmp(v->name, "group")) {
11201          confp->chan.group = ast_get_group(v->value);
11202       } else if (!strcasecmp(v->name, "callgroup")) {
11203          confp->chan.callgroup = ast_get_group(v->value);
11204       } else if (!strcasecmp(v->name, "pickupgroup")) {
11205          confp->chan.pickupgroup = ast_get_group(v->value);
11206       } else if (!strcasecmp(v->name, "immediate")) {
11207          confp->chan.immediate = ast_true(v->value);
11208       } else if (!strcasecmp(v->name, "transfertobusy")) {
11209          confp->chan.transfertobusy = ast_true(v->value);
11210       } else if (!strcasecmp(v->name, "rxgain")) {
11211          if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
11212             ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
11213          }
11214       } else if (!strcasecmp(v->name, "txgain")) {
11215          if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
11216             ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
11217          }
11218       } else if (!strcasecmp(v->name, "tonezone")) {
11219          if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
11220             ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
11221          }
11222       } else if (!strcasecmp(v->name, "callerid")) {
11223          if (!strcasecmp(v->value, "asreceived")) {
11224             confp->chan.cid_num[0] = '\0';
11225             confp->chan.cid_name[0] = '\0';
11226          } else {
11227             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
11228          } 
11229       } else if (!strcasecmp(v->name, "fullname")) {
11230          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
11231       } else if (!strcasecmp(v->name, "cid_number")) {
11232          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
11233       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
11234          confp->chan.dahditrcallerid = ast_true(v->value);
11235          if (strstr(v->name, "zap")) {
11236             ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat);
11237          }
11238       } else if (!strcasecmp(v->name, "restrictcid")) {
11239          confp->chan.restrictcid = ast_true(v->value);
11240       } else if (!strcasecmp(v->name, "usecallingpres")) {
11241          confp->chan.use_callingpres = ast_true(v->value);
11242       } else if (!strcasecmp(v->name, "accountcode")) {
11243          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
11244       } else if (!strcasecmp(v->name, "amaflags")) {
11245          y = ast_cdr_amaflags2int(v->value);
11246          if (y < 0) 
11247             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
11248          else
11249             confp->chan.amaflags = y;
11250       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
11251          confp->chan.polarityonanswerdelay = atoi(v->value);
11252       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
11253          confp->chan.answeronpolarityswitch = ast_true(v->value);
11254       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
11255          confp->chan.hanguponpolarityswitch = ast_true(v->value);
11256       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
11257          confp->chan.sendcalleridafter = atoi(v->value);
11258       } else if (reload != 1){ 
11259           if (!strcasecmp(v->name, "signalling")) {
11260             confp->chan.outsigmod = -1;
11261             if (!strcasecmp(v->value, "em")) {
11262                confp->chan.sig = SIG_EM;
11263             } else if (!strcasecmp(v->value, "em_e1")) {
11264                confp->chan.sig = SIG_EM_E1;
11265             } else if (!strcasecmp(v->value, "em_w")) {
11266                confp->chan.sig = SIG_EMWINK;
11267                confp->chan.radio = 0;
11268             } else if (!strcasecmp(v->value, "fxs_ls")) {
11269                confp->chan.sig = SIG_FXSLS;
11270                confp->chan.radio = 0;
11271             } else if (!strcasecmp(v->value, "fxs_gs")) {
11272                confp->chan.sig = SIG_FXSGS;
11273                confp->chan.radio = 0;
11274             } else if (!strcasecmp(v->value, "fxs_ks")) {
11275                confp->chan.sig = SIG_FXSKS;
11276                confp->chan.radio = 0;
11277             } else if (!strcasecmp(v->value, "fxo_ls")) {
11278                confp->chan.sig = SIG_FXOLS;
11279                confp->chan.radio = 0;
11280             } else if (!strcasecmp(v->value, "fxo_gs")) {
11281                confp->chan.sig = SIG_FXOGS;
11282                confp->chan.radio = 0;
11283             } else if (!strcasecmp(v->value, "fxo_ks")) {
11284                confp->chan.sig = SIG_FXOKS;
11285                confp->chan.radio = 0;
11286             } else if (!strcasecmp(v->value, "fxs_rx")) {
11287                confp->chan.sig = SIG_FXSKS;
11288                confp->chan.radio = 1;
11289             } else if (!strcasecmp(v->value, "fxo_rx")) {
11290                confp->chan.sig = SIG_FXOLS;
11291                confp->chan.radio = 1;
11292             } else if (!strcasecmp(v->value, "fxs_tx")) {
11293                confp->chan.sig = SIG_FXSLS;
11294                confp->chan.radio = 1;
11295             } else if (!strcasecmp(v->value, "fxo_tx")) {
11296                confp->chan.sig = SIG_FXOGS;
11297                confp->chan.radio = 1;
11298             } else if (!strcasecmp(v->value, "em_rx")) {
11299                confp->chan.sig = SIG_EM;
11300                confp->chan.radio = 1;
11301             } else if (!strcasecmp(v->value, "em_tx")) {
11302                confp->chan.sig = SIG_EM;
11303                confp->chan.radio = 1;
11304             } else if (!strcasecmp(v->value, "em_rxtx")) {
11305                confp->chan.sig = SIG_EM;
11306                confp->chan.radio = 2;
11307             } else if (!strcasecmp(v->value, "em_txrx")) {
11308                confp->chan.sig = SIG_EM;
11309                confp->chan.radio = 2;
11310             } else if (!strcasecmp(v->value, "sf")) {
11311                confp->chan.sig = SIG_SF;
11312                confp->chan.radio = 0;
11313             } else if (!strcasecmp(v->value, "sf_w")) {
11314                confp->chan.sig = SIG_SFWINK;
11315                confp->chan.radio = 0;
11316             } else if (!strcasecmp(v->value, "sf_featd")) {
11317                confp->chan.sig = SIG_FEATD;
11318                confp->chan.radio = 0;
11319             } else if (!strcasecmp(v->value, "sf_featdmf")) {
11320                confp->chan.sig = SIG_FEATDMF;
11321                confp->chan.radio = 0;
11322             } else if (!strcasecmp(v->value, "sf_featb")) {
11323                confp->chan.sig = SIG_SF_FEATB;
11324                confp->chan.radio = 0;
11325             } else if (!strcasecmp(v->value, "sf")) {
11326                confp->chan.sig = SIG_SF;
11327                confp->chan.radio = 0;
11328             } else if (!strcasecmp(v->value, "sf_rx")) {
11329                confp->chan.sig = SIG_SF;
11330                confp->chan.radio = 1;
11331             } else if (!strcasecmp(v->value, "sf_tx")) {
11332                confp->chan.sig = SIG_SF;
11333                confp->chan.radio = 1;
11334             } else if (!strcasecmp(v->value, "sf_rxtx")) {
11335                confp->chan.sig = SIG_SF;
11336                confp->chan.radio = 2;
11337             } else if (!strcasecmp(v->value, "sf_txrx")) {
11338                confp->chan.sig = SIG_SF;
11339                confp->chan.radio = 2;
11340             } else if (!strcasecmp(v->value, "featd")) {
11341                confp->chan.sig = SIG_FEATD;
11342                confp->chan.radio = 0;
11343             } else if (!strcasecmp(v->value, "featdmf")) {
11344                confp->chan.sig = SIG_FEATDMF;
11345                confp->chan.radio = 0;
11346             } else if (!strcasecmp(v->value, "featdmf_ta")) {
11347                confp->chan.sig = SIG_FEATDMF_TA;
11348                confp->chan.radio = 0;
11349             } else if (!strcasecmp(v->value, "e911")) {
11350                confp->chan.sig = SIG_E911;
11351                confp->chan.radio = 0;
11352             } else if (!strcasecmp(v->value, "fgccama")) {
11353                confp->chan.sig = SIG_FGC_CAMA;
11354                confp->chan.radio = 0;
11355             } else if (!strcasecmp(v->value, "fgccamamf")) {
11356                confp->chan.sig = SIG_FGC_CAMAMF;
11357                confp->chan.radio = 0;
11358             } else if (!strcasecmp(v->value, "featb")) {
11359                confp->chan.sig = SIG_FEATB;
11360                confp->chan.radio = 0;
11361 #ifdef HAVE_PRI
11362             } else if (!strcasecmp(v->value, "pri_net")) {
11363                confp->chan.radio = 0;
11364                confp->chan.sig = SIG_PRI;
11365                confp->pri.nodetype = PRI_NETWORK;
11366             } else if (!strcasecmp(v->value, "pri_cpe")) {
11367                confp->chan.sig = SIG_PRI;
11368                confp->chan.radio = 0;
11369                confp->pri.nodetype = PRI_CPE;
11370             } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
11371                confp->chan.sig = SIG_GR303FXOKS;
11372                confp->chan.radio = 0;
11373                confp->pri.nodetype = PRI_NETWORK;
11374             } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
11375                confp->chan.sig = SIG_GR303FXSKS;
11376                confp->chan.radio = 0;
11377                confp->pri.nodetype = PRI_CPE;
11378 #endif
11379             } else {
11380                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11381             }
11382           } else if (!strcasecmp(v->name, "outsignalling")) {
11383             if (!strcasecmp(v->value, "em")) {
11384                confp->chan.outsigmod = SIG_EM;
11385             } else if (!strcasecmp(v->value, "em_e1")) {
11386                confp->chan.outsigmod = SIG_EM_E1;
11387             } else if (!strcasecmp(v->value, "em_w")) {
11388                confp->chan.outsigmod = SIG_EMWINK;
11389             } else if (!strcasecmp(v->value, "sf")) {
11390                confp->chan.outsigmod = SIG_SF;
11391             } else if (!strcasecmp(v->value, "sf_w")) {
11392                confp->chan.outsigmod = SIG_SFWINK;
11393             } else if (!strcasecmp(v->value, "sf_featd")) {
11394                confp->chan.outsigmod = SIG_FEATD;
11395             } else if (!strcasecmp(v->value, "sf_featdmf")) {
11396                confp->chan.outsigmod = SIG_FEATDMF;
11397             } else if (!strcasecmp(v->value, "sf_featb")) {
11398                confp->chan.outsigmod = SIG_SF_FEATB;
11399             } else if (!strcasecmp(v->value, "sf")) {
11400                confp->chan.outsigmod = SIG_SF;
11401             } else if (!strcasecmp(v->value, "featd")) {
11402                confp->chan.outsigmod = SIG_FEATD;
11403             } else if (!strcasecmp(v->value, "featdmf")) {
11404                confp->chan.outsigmod = SIG_FEATDMF;
11405             } else if (!strcasecmp(v->value, "featdmf_ta")) {
11406                confp->chan.outsigmod = SIG_FEATDMF_TA;
11407             } else if (!strcasecmp(v->value, "e911")) {
11408                confp->chan.outsigmod = SIG_E911;
11409             } else if (!strcasecmp(v->value, "fgccama")) {
11410                confp->chan.outsigmod = SIG_FGC_CAMA;
11411             } else if (!strcasecmp(v->value, "fgccamamf")) {
11412                confp->chan.outsigmod = SIG_FGC_CAMAMF;
11413             } else if (!strcasecmp(v->value, "featb")) {
11414                confp->chan.outsigmod = SIG_FEATB;
11415             } else {
11416                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11417             }
11418 #ifdef HAVE_PRI
11419          } else if (!strcasecmp(v->name, "pridialplan")) {
11420             if (!strcasecmp(v->value, "national")) {
11421                confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
11422             } else if (!strcasecmp(v->value, "unknown")) {
11423                confp->pri.dialplan = PRI_UNKNOWN + 1;
11424             } else if (!strcasecmp(v->value, "private")) {
11425                confp->pri.dialplan = PRI_PRIVATE + 1;
11426             } else if (!strcasecmp(v->value, "international")) {
11427                confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
11428             } else if (!strcasecmp(v->value, "local")) {
11429                confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
11430             } else if (!strcasecmp(v->value, "dynamic")) {
11431                confp->pri.dialplan = -1;
11432             } else {
11433                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11434             }
11435          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
11436             if (!strcasecmp(v->value, "national")) {
11437                confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
11438             } else if (!strcasecmp(v->value, "unknown")) {
11439                confp->pri.localdialplan = PRI_UNKNOWN + 1;
11440             } else if (!strcasecmp(v->value, "private")) {
11441                confp->pri.localdialplan = PRI_PRIVATE + 1;
11442             } else if (!strcasecmp(v->value, "international")) {
11443                confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
11444             } else if (!strcasecmp(v->value, "local")) {
11445                confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
11446             } else if (!strcasecmp(v->value, "dynamic")) {
11447                confp->pri.localdialplan = -1;
11448             } else {
11449                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11450             }
11451          } else if (!strcasecmp(v->name, "switchtype")) {
11452             if (!strcasecmp(v->value, "national")) 
11453                confp->pri.switchtype = PRI_SWITCH_NI2;
11454             else if (!strcasecmp(v->value, "ni1"))
11455                confp->pri.switchtype = PRI_SWITCH_NI1;
11456             else if (!strcasecmp(v->value, "dms100"))
11457                confp->pri.switchtype = PRI_SWITCH_DMS100;
11458             else if (!strcasecmp(v->value, "4ess"))
11459                confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
11460             else if (!strcasecmp(v->value, "5ess"))
11461                confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
11462             else if (!strcasecmp(v->value, "euroisdn"))
11463                confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
11464             else if (!strcasecmp(v->value, "qsig"))
11465                confp->pri.switchtype = PRI_SWITCH_QSIG;
11466             else {
11467                ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
11468                return -1;
11469             }
11470          } else if (!strcasecmp(v->name, "nsf")) {
11471             if (!strcasecmp(v->value, "sdn"))
11472                confp->pri.nsf = PRI_NSF_SDN;
11473             else if (!strcasecmp(v->value, "megacom"))
11474                confp->pri.nsf = PRI_NSF_MEGACOM;
11475             else if (!strcasecmp(v->value, "tollfreemegacom"))
11476                confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;           
11477             else if (!strcasecmp(v->value, "accunet"))
11478                confp->pri.nsf = PRI_NSF_ACCUNET;
11479             else if (!strcasecmp(v->value, "none"))
11480                confp->pri.nsf = PRI_NSF_NONE;
11481             else {
11482                ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
11483                confp->pri.nsf = PRI_NSF_NONE;
11484             }
11485          } else if (!strcasecmp(v->name, "priindication")) {
11486             if (!strcasecmp(v->value, "outofband"))
11487                confp->chan.priindication_oob = 1;
11488             else if (!strcasecmp(v->value, "inband"))
11489                confp->chan.priindication_oob = 0;
11490             else
11491                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
11492                   v->value, v->lineno);
11493          } else if (!strcasecmp(v->name, "priexclusive")) {
11494             confp->chan.priexclusive = ast_true(v->value);
11495          } else if (!strcasecmp(v->name, "internationalprefix")) {
11496             ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
11497          } else if (!strcasecmp(v->name, "nationalprefix")) {
11498             ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
11499          } else if (!strcasecmp(v->name, "localprefix")) {
11500             ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
11501          } else if (!strcasecmp(v->name, "privateprefix")) {
11502             ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
11503          } else if (!strcasecmp(v->name, "unknownprefix")) {
11504             ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
11505          } else if (!strcasecmp(v->name, "resetinterval")) {
11506             if (!strcasecmp(v->value, "never"))
11507                confp->pri.resetinterval = -1;
11508             else if (atoi(v->value) >= 60)
11509                confp->pri.resetinterval = atoi(v->value);
11510             else
11511                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
11512                   v->value, v->lineno);
11513          } else if (!strcasecmp(v->name, "minunused")) {
11514             confp->pri.minunused = atoi(v->value);
11515          } else if (!strcasecmp(v->name, "minidle")) {
11516             confp->pri.minidle = atoi(v->value); 
11517          } else if (!strcasecmp(v->name, "idleext")) {
11518             ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
11519          } else if (!strcasecmp(v->name, "idledial")) {
11520             ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
11521          } else if (!strcasecmp(v->name, "overlapdial")) {
11522             confp->pri.overlapdial = ast_true(v->value);
11523 #ifdef HAVE_PRI_INBANDDISCONNECT
11524          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
11525             confp->pri.inbanddisconnect = ast_true(v->value);
11526 #endif
11527          } else if (!strcasecmp(v->name, "pritimer")) {
11528 #ifdef PRI_GETSET_TIMERS
11529             char *timerc, *c;
11530             int timer, timeridx;
11531             c = v->value;
11532             timerc = strsep(&c, ",");
11533             if (timerc) {
11534                timer = atoi(c);
11535                if (!timer)
11536                   ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer\n", timerc);
11537                else {
11538                   if ((timeridx = pri_timer2idx(timerc)) >= 0)
11539                      pritimers[timeridx] = timer;
11540                   else
11541                      ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer\n", timerc);
11542                }
11543             } else
11544                ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string\n", v->value);
11545 
11546          } else if (!strcasecmp(v->name, "facilityenable")) {
11547             confp->pri.facilityenable = ast_true(v->value);
11548 #endif /* PRI_GETSET_TIMERS */
11549 #endif /* HAVE_PRI */
11550          } else if (!strcasecmp(v->name, "cadence")) {
11551             /* setup to scan our argument */
11552             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
11553             int i;
11554             struct dahdi_ring_cadence new_cadence;
11555             int cid_location = -1;
11556             int firstcadencepos = 0;
11557             char original_args[80];
11558             int cadence_is_ok = 1;
11559 
11560             ast_copy_string(original_args, v->value, sizeof(original_args));
11561             /* 16 cadences allowed (8 pairs) */
11562             element_count = sscanf(v->value, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11], &c[12], &c[13], &c[14], &c[15]);
11563    
11564             /* Cadence must be even (on/off) */
11565             if (element_count % 2 == 1) {
11566                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
11567                cadence_is_ok = 0;
11568             }
11569    
11570             /* Ring cadences cannot be negative */
11571             for (i = 0; i < element_count; i++) {
11572                if (c[i] == 0) {
11573                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
11574                   cadence_is_ok = 0;
11575                   break;
11576                } else if (c[i] < 0) {
11577                   if (i % 2 == 1) {
11578                      /* Silence duration, negative possibly okay */
11579                      if (cid_location == -1) {
11580                         cid_location = i;
11581                         c[i] *= -1;
11582                      } else {
11583                         ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
11584                         cadence_is_ok = 0;
11585                         break;
11586                      }
11587                   } else {
11588                      if (firstcadencepos == 0) {
11589                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
11590                                  /* duration will be passed negative to the DAHDI driver */
11591                      } else {
11592                          ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
11593                         cadence_is_ok = 0;
11594                         break;
11595                      }
11596                   }
11597                }
11598             }
11599    
11600             /* Substitute our scanned cadence */
11601             for (i = 0; i < 16; i++) {
11602                new_cadence.ringcadence[i] = c[i];
11603             }
11604    
11605             if (cadence_is_ok) {
11606                /* ---we scanned it without getting annoyed; now some sanity checks--- */
11607                if (element_count < 2) {
11608                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
11609                } else {
11610                   if (cid_location == -1) {
11611                      /* user didn't say; default to first pause */
11612                      cid_location = 1;
11613                   } else {
11614                      /* convert element_index to cidrings value */
11615                      cid_location = (cid_location + 1) / 2;
11616                   }
11617                   /* ---we like their cadence; try to install it--- */
11618                   if (!user_has_defined_cadences++)
11619                      /* this is the first user-defined cadence; clear the default user cadences */
11620                      num_cadence = 0;
11621                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
11622                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
11623                   else {
11624                      cadences[num_cadence] = new_cadence;
11625                      cidrings[num_cadence++] = cid_location;
11626                      if (option_verbose > 2)
11627                         ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
11628                   }
11629                }
11630             }
11631          } else if (!strcasecmp(v->name, "ringtimeout")) {
11632             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
11633          } else if (!strcasecmp(v->name, "prewink")) {
11634             confp->timing.prewinktime = atoi(v->value);
11635          } else if (!strcasecmp(v->name, "preflash")) {
11636             confp->timing.preflashtime = atoi(v->value);
11637          } else if (!strcasecmp(v->name, "wink")) {
11638             confp->timing.winktime = atoi(v->value);
11639          } else if (!strcasecmp(v->name, "flash")) {
11640             confp->timing.flashtime = atoi(v->value);
11641          } else if (!strcasecmp(v->name, "start")) {
11642             confp->timing.starttime = atoi(v->value);
11643          } else if (!strcasecmp(v->name, "rxwink")) {
11644             confp->timing.rxwinktime = atoi(v->value);
11645          } else if (!strcasecmp(v->name, "rxflash")) {
11646             confp->timing.rxflashtime = atoi(v->value);
11647          } else if (!strcasecmp(v->name, "debounce")) {
11648             confp->timing.debouncetime = atoi(v->value);
11649          } else if (!strcasecmp(v->name, "toneduration")) {
11650             int toneduration;
11651             int ctlfd;
11652             int res;
11653             struct dahdi_dialparams dps;
11654 
11655 #ifdef HAVE_ZAPTEL
11656             ctlfd = open("/dev/zap/ctl", O_RDWR);
11657 #else
11658             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
11659 #endif
11660 
11661             if (ctlfd == -1) {
11662                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration\n");
11663                return -1;
11664             }
11665 
11666             toneduration = atoi(v->value);
11667             if (toneduration > -1) {
11668                memset(&dps, 0, sizeof(dps));
11669 
11670                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
11671                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
11672                if (res < 0) {
11673                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
11674                   return -1;
11675                }
11676             }
11677             close(ctlfd);
11678          } else if (!strcasecmp(v->name, "defaultcic")) {
11679             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
11680          } else if (!strcasecmp(v->name, "defaultozz")) {
11681             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
11682          } 
11683       } else if (!skipchannels)
11684          ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
11685    }
11686    if (dahdichan[0]) { 
11687       /* The user has set 'dahdichan' */
11688       /*< \todo pass proper line number instead of 0 */
11689       if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
11690          return -1;
11691       }
11692    }
11693    /*< \todo why check for the pseudo in the per-channel section.
11694     * Any actual use for manual setup of the pseudo channel? */
11695    if (!found_pseudo && reload == 0) {
11696       /* Make sure pseudo isn't a member of any groups if
11697          we're automatically making it. */   
11698       
11699       confp->chan.group = 0;
11700       confp->chan.callgroup = 0;
11701       confp->chan.pickupgroup = 0;
11702 
11703       tmp = mkintf(CHAN_PSEUDO, confp, NULL, reload);
11704 
11705       if (tmp) {
11706          if (option_verbose > 2)
11707             ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
11708       } else {
11709          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
11710       }
11711    }
11712    return 0;
11713 }

static int reload ( void   )  [static]

Definition at line 12022 of file chan_dahdi.c.

References ast_log(), and setup_dahdi().

12023 {
12024    int res = 0;
12025 
12026    res = setup_dahdi(1);
12027    if (res) {
12028       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
12029       return -1;
12030    }
12031    return 0;
12032 }

static int reset_conf ( struct dahdi_pvt p  )  [static]

Definition at line 1395 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, dahdi_pvt::confno, dahdi_subchannel::dfd, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_hangup().

01396 {
01397    struct dahdi_confinfo zi;
01398    memset(&zi, 0, sizeof(zi));
01399    p->confno = -1;
01400    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01401    if (p->subs[SUB_REAL].dfd > -1) {
01402       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
01403          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
01404    }
01405    return 0;
01406 }

static int restart_monitor ( void   )  [static]

Definition at line 7141 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_background, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_monitor(), and LOG_ERROR.

Referenced by dahdi_hangup(), dahdi_request(), h323_reload(), load_module(), mgcp_reload(), mgcp_request(), oh323_request(), phone_hangup(), phone_request(), setup_dahdi(), sip_reload(), sip_request_call(), and skinny_request().

07142 {
07143    pthread_attr_t attr;
07144    pthread_attr_init(&attr);
07145    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
07146    /* If we're supposed to be stopped -- stay stopped */
07147    if (monitor_thread == AST_PTHREADT_STOP)
07148       return 0;
07149    ast_mutex_lock(&monlock);
07150    if (monitor_thread == pthread_self()) {
07151       ast_mutex_unlock(&monlock);
07152       ast_log(LOG_WARNING, "Cannot kill myself\n");
07153       return -1;
07154    }
07155    if (monitor_thread != AST_PTHREADT_NULL) {
07156       /* Wake up the thread */
07157       pthread_kill(monitor_thread, SIGURG);
07158    } else {
07159       /* Start a new monitor */
07160       if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
07161          ast_mutex_unlock(&monlock);
07162          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
07163          pthread_attr_destroy(&attr);
07164          return -1;
07165       }
07166    }
07167    ast_mutex_unlock(&monlock);
07168    pthread_attr_destroy(&attr);
07169    return 0;
07170 }

static int restore_conference ( struct dahdi_pvt p  )  [static]

Definition at line 1728 of file chan_dahdi.c.

References ast_log(), errno, LOG_DEBUG, LOG_WARNING, option_debug, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_handle_event(), dahdi_read(), and send_callerid().

01729 {
01730    int res;
01731    if (p->saveconf.confmode) {
01732       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
01733       p->saveconf.confmode = 0;
01734       if (res) {
01735          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
01736          return -1;
01737       }
01738    }
01739    if (option_debug)
01740       ast_log(LOG_DEBUG, "Restored conferencing\n");
01741    return 0;
01742 }

static int restore_gains ( struct dahdi_pvt p  )  [static]

Definition at line 1654 of file chan_dahdi.c.

References ast_log(), errno, dahdi_pvt::law, LOG_WARNING, dahdi_pvt::rxgain, set_actual_gain(), SUB_REAL, dahdi_pvt::subs, and dahdi_pvt::txgain.

Referenced by dahdi_hangup(), and ss_thread().

01655 {
01656    int res;
01657 
01658    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
01659    if (res) {
01660       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
01661       return -1;
01662    }
01663 
01664    return 0;
01665 }

static int save_conference ( struct dahdi_pvt p  )  [static]

Definition at line 1700 of file chan_dahdi.c.

References ast_log(), errno, LOG_DEBUG, LOG_WARNING, option_debug, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_callwait(), and dahdi_handle_event().

01701 {
01702    struct dahdi_confinfo c;
01703    int res;
01704    if (p->saveconf.confmode) {
01705       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
01706       return -1;
01707    }
01708    p->saveconf.chan = 0;
01709    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
01710    if (res) {
01711       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
01712       p->saveconf.confmode = 0;
01713       return -1;
01714    }
01715    c.chan = 0;
01716    c.confno = 0;
01717    c.confmode = DAHDI_CONF_NORMAL;
01718    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
01719    if (res) {
01720       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
01721       return -1;
01722    }
01723    if (option_debug)
01724       ast_log(LOG_DEBUG, "Disabled conferencing\n");
01725    return 0;
01726 }

static int send_callerid ( struct dahdi_pvt p  )  [static]

Definition at line 1768 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::callwaitcas, CIDCW_EXPIRE_SAMPLES, dahdi_pvt::cidcwexpire, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_setlinear(), errno, free, dahdi_subchannel::linear, LOG_WARNING, restore_conference(), SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_call(), dahdi_callwait(), dahdi_read(), and send_cwcidspill().

01769 {
01770    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
01771    int res;
01772    /* Take out of linear mode if necessary */
01773    if (p->subs[SUB_REAL].linear) {
01774       p->subs[SUB_REAL].linear = 0;
01775       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
01776    }
01777    while (p->cidpos < p->cidlen) {
01778       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
01779       if (res < 0) {
01780          if (errno == EAGAIN)
01781             return 0;
01782          else {
01783             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
01784             return -1;
01785          }
01786       }
01787       if (!res)
01788          return 0;
01789       p->cidpos += res;
01790    }
01791    free(p->cidspill);
01792    p->cidspill = NULL;
01793    if (p->callwaitcas) {
01794       /* Wait for CID/CW to expire */
01795       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
01796    } else
01797       restore_conference(p);
01798    return 0;
01799 }

static int send_cwcidspill ( struct dahdi_pvt p  )  [static]

Definition at line 1746 of file chan_dahdi.c.

References ast_callerid_callwaiting_generate(), AST_LAW, ast_malloc, ast_verbose(), dahdi_pvt::callwait_name, dahdi_pvt::callwait_num, dahdi_pvt::callwaitcas, dahdi_pvt::cidcwexpire, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, MAX_CALLERID_SIZE, option_verbose, READ_SIZE, send_callerid(), and VERBOSE_PREFIX_3.

Referenced by dahdi_handle_dtmfup().

01747 {
01748    p->callwaitcas = 0;
01749    p->cidcwexpire = 0;
01750    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
01751       return -1;
01752    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
01753    /* Make sure we account for the end */
01754    p->cidlen += READ_SIZE * 4;
01755    p->cidpos = 0;
01756    send_callerid(p);
01757    if (option_verbose > 2)
01758       ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
01759    return 0;
01760 }

static int set_actual_gain ( int  fd,
int  chan,
float  rxgain,
float  txgain,
int  law 
) [static]

Definition at line 1635 of file chan_dahdi.c.

References set_actual_rxgain(), and set_actual_txgain().

Referenced by bump_gains(), dahdi_call(), and restore_gains().

01636 {
01637    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
01638 }

static int set_actual_rxgain ( int  fd,
int  chan,
float  gain,
int  law 
) [static]

Definition at line 1617 of file chan_dahdi.c.

References ast_log(), errno, fill_rxgain(), and LOG_DEBUG.

Referenced by dahdi_setoption(), and set_actual_gain().

01618 {
01619    struct dahdi_gains g;
01620    int res;
01621 
01622    memset(&g, 0, sizeof(g));
01623    g.chan = chan;
01624    res = ioctl(fd, DAHDI_GETGAINS, &g);
01625    if (res) {
01626       ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01627       return res;
01628    }
01629 
01630    fill_rxgain(&g, gain, law);
01631 
01632    return ioctl(fd, DAHDI_SETGAINS, &g);
01633 }

static int set_actual_txgain ( int  fd,
int  chan,
float  gain,
int  law 
) [static]

Definition at line 1598 of file chan_dahdi.c.

References ast_log(), errno, fill_txgain(), LOG_DEBUG, and option_debug.

Referenced by dahdi_setoption(), and set_actual_gain().

01599 {
01600    struct dahdi_gains g;
01601    int res;
01602 
01603    memset(&g, 0, sizeof(g));
01604    g.chan = chan;
01605    res = ioctl(fd, DAHDI_GETGAINS, &g);
01606    if (res) {
01607       if (option_debug)
01608          ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01609       return res;
01610    }
01611 
01612    fill_txgain(&g, gain, law);
01613 
01614    return ioctl(fd, DAHDI_SETGAINS, &g);
01615 }

static int setup_dahdi ( int  reload  )  [static]

Definition at line 11715 of file chan_dahdi.c.

References ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verbose(), CHAN_ZAP_MODE, dahdi_chan_conf_default(), dahdi_chan_mode, default_jbconf, global_jbconf, ast_variable::lineno, LOG_ERROR, ast_variable::name, ast_variable::next, option_verbose, process_dahdi(), restart_monitor(), ast_variable::value, and VERBOSE_PREFIX_2.

Referenced by dahdi_restart(), load_module(), and reload().

11716 {
11717    struct ast_config *cfg;
11718    struct ast_variable *v;
11719    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
11720    int res;
11721 
11722 #ifdef HAVE_PRI
11723    char *c;
11724    int spanno;
11725    int i, x;
11726    int logicalspan;
11727    int trunkgroup;
11728    int dchannels[NUM_DCHANS];
11729 #endif
11730 
11731 #ifdef HAVE_ZAPTEL
11732    int load_from_zapata_conf = 1;
11733 #else
11734    int load_from_zapata_conf = (dahdi_chan_mode == CHAN_ZAP_MODE);
11735 #endif
11736 
11737    if (load_from_zapata_conf) {
11738       if (!(cfg = ast_config_load("zapata.conf"))) {
11739          ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
11740          return 0;
11741       }
11742    } else {
11743       if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
11744          ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
11745          return 0;
11746       }
11747    }
11748 
11749    /* It's a little silly to lock it, but we mind as well just to be sure */
11750    ast_mutex_lock(&iflock);
11751 #ifdef HAVE_PRI
11752    if (reload != 1) {
11753       /* Process trunkgroups first */
11754       v = ast_variable_browse(cfg, "trunkgroups");
11755       while (v) {
11756          if (!strcasecmp(v->name, "trunkgroup")) {
11757             trunkgroup = atoi(v->value);
11758             if (trunkgroup > 0) {
11759                if ((c = strchr(v->value, ','))) {
11760                   i = 0;
11761                   memset(dchannels, 0, sizeof(dchannels));
11762                   while (c && (i < NUM_DCHANS)) {
11763                      dchannels[i] = atoi(c + 1);
11764                      if (dchannels[i] < 0) {
11765                         ast_log(LOG_WARNING, "D-channel for trunk group %d must be a postiive number at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11766                      } else
11767                         i++;
11768                      c = strchr(c + 1, ',');
11769                   }
11770                   if (i) {
11771                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
11772                         ast_log(LOG_WARNING, "Unable to create trunk group %d with Primary D-channel %d at line %d of chan_dahdi.conf\n", trunkgroup, dchannels[0], v->lineno);
11773                      } else if (option_verbose > 1)
11774                         ast_verbose(VERBOSE_PREFIX_2 "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
11775                   } else
11776                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11777                } else
11778                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11779             } else
11780                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
11781          } else if (!strcasecmp(v->name, "spanmap")) {
11782             spanno = atoi(v->value);
11783             if (spanno > 0) {
11784                if ((c = strchr(v->value, ','))) {
11785                   trunkgroup = atoi(c + 1);
11786                   if (trunkgroup > 0) {
11787                      if ((c = strchr(c + 1, ','))) 
11788                         logicalspan = atoi(c + 1);
11789                      else
11790                         logicalspan = 0;
11791                      if (logicalspan >= 0) {
11792                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
11793                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11794                         } else if (option_verbose > 1) 
11795                            ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11796                      } else
11797                         ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of chan_dahdi.conf\n", v->lineno);
11798                   } else
11799                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
11800                } else
11801                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
11802             } else
11803                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
11804          } else {
11805             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
11806          }
11807          v = v->next;
11808       }
11809    }
11810 #endif
11811    
11812    /* Copy the default jb config over global_jbconf */
11813    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
11814 
11815    v = ast_variable_browse(cfg, "channels");
11816    res = process_dahdi(&conf, "", v, reload, 0);
11817    ast_mutex_unlock(&iflock);
11818    ast_config_destroy(cfg);
11819    if (res)
11820       return res;
11821    cfg = ast_config_load("users.conf");
11822    if (cfg) {
11823       char *cat;
11824       const char *chans;
11825       process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
11826       for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
11827          if (!strcasecmp(cat, "general"))
11828             continue;
11829          chans = ast_variable_retrieve(cfg, cat, "dahdichan");
11830          if (!ast_strlen_zero(chans)) {
11831             struct dahdi_chan_conf sect_conf;
11832             memcpy(&sect_conf, &conf, sizeof(sect_conf));
11833 
11834             process_dahdi(&sect_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
11835          }
11836       }
11837       ast_config_destroy(cfg);
11838    }
11839 #ifdef HAVE_PRI
11840    if (reload != 1) {
11841       for (x = 0; x < NUM_SPANS; x++) {
11842          if (pris[x].pvts[0]) {
11843             if (start_pri(pris + x)) {
11844                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
11845                return -1;
11846             } else if (option_verbose > 1)
11847                ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
11848          }
11849       }
11850    }
11851 #endif
11852    /* And start the monitor for the first time */
11853    restart_monitor();
11854    return 0;
11855 }

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

Definition at line 5561 of file chan_dahdi.c.

References ast_channel::_state, alloc_sub(), ast_bridged_channel(), ast_canmatch_extension(), AST_CAUSE_UNALLOCATED, AST_CONTROL_RING, AST_CONTROL_UNHOLD, ast_db_put(), ast_dsp_digitmode(), ast_dsp_digitreset(), ast_dsp_free(), ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_DTMF, 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_say_digit_str(), ast_set_callerid(), ast_setstate(), ast_smdi_md_message_wait(), AST_STATE_PRERING, AST_STATE_RING, AST_STATE_RINGING, ast_streamfile(), ast_strlen_zero(), ast_verbose(), ast_waitfor(), ast_waitfordigit(), ast_waitstream(), bump_gains(), dahdi_pvt::call_forward, callerid_feed(), callerid_feed_jp(), callerid_free(), callerid_get(), callerid_get_dtmf(), callerid_new(), ast_smdi_md_message::calling_st, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::cancallforward, dahdi_pvt::canpark, chan_tech, 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_POLARITY, dahdi_pvt::context, ast_channel::context, ringContextData::contextData, dahdi_chan_name, 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::dnd, dahdi_pvt::dop, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, errno, event2str(), EVENT_FLAG_SYSTEM, ast_channel::exten, dahdi_pvt::exten, exten, f, free, func, ast_smdi_md_message::fwd_st, ast_channel::hangupcause, dahdi_pvt::hardwaredtmf, dahdi_pvt::hidecallerid, dahdi_pvt::immediate, ISTRUNK, dahdi_pvt::lastcid_num, len, dahdi_subchannel::linear, LOG_DEBUG, LOG_NOTICE, manager_event(), my_getsigstr(), name, NEED_MFDETECT, option_debug, option_verbose, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), quit, restore_gains(), distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, 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_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::smdi_iface, SMDI_MD_WAIT_TIMEOUT, strsep(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, 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, dahdi_pvt::usedistinctiveringdetection, VERBOSE_PREFIX_2, and VERBOSE_PREFIX_3.

Referenced by dahdi_handle_event(), and handle_init_event().

05562 {
05563    struct ast_channel *chan = data;
05564    struct dahdi_pvt *p = chan->tech_pvt;
05565    char exten[AST_MAX_EXTENSION] = "";
05566    char exten2[AST_MAX_EXTENSION] = "";
05567    unsigned char buf[256];
05568    char dtmfcid[300];
05569    char dtmfbuf[300];
05570    struct callerid_state *cs = NULL;
05571    char *name = NULL, *number = NULL;
05572    int distMatches;
05573    int curRingData[3];
05574    int receivedRingT;
05575    int counter1;
05576    int counter;
05577    int samples = 0;
05578    struct ast_smdi_md_message *smdi_msg = NULL;
05579    int flags;
05580    int i;
05581    int timeout;
05582    int getforward = 0;
05583    char *s1, *s2;
05584    int len = 0;
05585    int res;
05586    int index;
05587 
05588    ast_mutex_lock(&ss_thread_lock);
05589    ss_thread_count++;
05590    ast_mutex_unlock(&ss_thread_lock);
05591    /* in the bizarre case where the channel has become a zombie before we
05592       even get started here, abort safely
05593    */
05594    if (!p) {
05595       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
05596       ast_hangup(chan);
05597       goto quit;
05598    }
05599    if (option_verbose > 2) 
05600       ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
05601    index = dahdi_get_index(chan, p, 1);
05602    if (index < 0) {
05603       ast_log(LOG_WARNING, "Huh?\n");
05604       ast_hangup(chan);
05605       goto quit;
05606    }
05607    if (p->dsp)
05608       ast_dsp_digitreset(p->dsp);
05609    switch (p->sig) {
05610 #ifdef HAVE_PRI
05611    case SIG_PRI:
05612       /* Now loop looking for an extension */
05613       ast_copy_string(exten, p->exten, sizeof(exten));
05614       len = strlen(exten);
05615       res = 0;
05616       while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
05617          if (len && !ast_ignore_pattern(chan->context, exten))
05618             tone_zone_play_tone(p->subs[index].dfd, -1);
05619          else
05620             tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
05621          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
05622             timeout = matchdigittimeout;
05623          else
05624             timeout = gendigittimeout;
05625          res = ast_waitfordigit(chan, timeout);
05626          if (res < 0) {
05627             ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
05628             ast_hangup(chan);
05629             goto quit;
05630          } else if (res) {
05631             exten[len++] = res;
05632             exten[len] = '\0';
05633          } else
05634             break;
05635       }
05636       /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
05637       if (ast_strlen_zero(exten)) {
05638          if (option_verbose > 2)
05639             ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
05640          exten[0] = 's';
05641          exten[1] = '\0';
05642       }
05643       tone_zone_play_tone(p->subs[index].dfd, -1);
05644       if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
05645          /* Start the real PBX */
05646          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
05647          if (p->dsp) ast_dsp_digitreset(p->dsp);
05648          dahdi_enable_ec(p);
05649          ast_setstate(chan, AST_STATE_RING);
05650          res = ast_pbx_run(chan);
05651          if (res) {
05652             ast_log(LOG_WARNING, "PBX exited non-zero!\n");
05653          }
05654       } else {
05655          ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
05656          chan->hangupcause = AST_CAUSE_UNALLOCATED;
05657          ast_hangup(chan);
05658          p->exten[0] = '\0';
05659          /* Since we send release complete here, we won't get one */
05660          p->call = NULL;
05661       }
05662       goto quit;
05663       break;
05664 #endif
05665    case SIG_FEATD:
05666    case SIG_FEATDMF:
05667    case SIG_FEATDMF_TA:
05668    case SIG_E911:
05669    case SIG_FGC_CAMAMF:
05670    case SIG_FEATB:
05671    case SIG_EMWINK:
05672    case SIG_SF_FEATD:
05673    case SIG_SF_FEATDMF:
05674    case SIG_SF_FEATB:
05675    case SIG_SFWINK:
05676       if (dahdi_wink(p, index))  
05677          goto quit;
05678       /* Fall through */
05679    case SIG_EM:
05680    case SIG_EM_E1:
05681    case SIG_SF:
05682    case SIG_FGC_CAMA:
05683       res = tone_zone_play_tone(p->subs[index].dfd, -1);
05684       if (p->dsp)
05685          ast_dsp_digitreset(p->dsp);
05686       /* set digit mode appropriately */
05687       if (p->dsp) {
05688          if (NEED_MFDETECT(p))
05689             ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 
05690          else 
05691             ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
05692       }
05693       memset(dtmfbuf, 0, sizeof(dtmfbuf));
05694       /* Wait for the first digit only if immediate=no */
05695       if (!p->immediate)
05696          /* Wait for the first digit (up to 5 seconds). */
05697          res = ast_waitfordigit(chan, 5000);
05698       else
05699          res = 0;
05700       if (res > 0) {
05701          /* save first char */
05702          dtmfbuf[0] = res;
05703          switch (p->sig) {
05704          case SIG_FEATD:
05705          case SIG_SF_FEATD:
05706             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
05707             if (res > 0)
05708                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
05709             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05710             break;
05711          case SIG_FEATDMF_TA:
05712             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05713             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05714             if (dahdi_wink(p, index)) goto quit;
05715             dtmfbuf[0] = 0;
05716             /* Wait for the first digit (up to 5 seconds). */
05717             res = ast_waitfordigit(chan, 5000);
05718             if (res <= 0) break;
05719             dtmfbuf[0] = res;
05720             /* fall through intentionally */
05721          case SIG_FEATDMF:
05722          case SIG_E911:
05723          case SIG_FGC_CAMAMF:
05724          case SIG_SF_FEATDMF:
05725             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05726             /* if international caca, do it again to get real ANO */
05727             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
05728             {
05729                if (dahdi_wink(p, index)) goto quit;
05730                dtmfbuf[0] = 0;
05731                /* Wait for the first digit (up to 5 seconds). */
05732                res = ast_waitfordigit(chan, 5000);
05733                if (res <= 0) break;
05734                dtmfbuf[0] = res;
05735                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05736             }
05737             if (res > 0) {
05738                /* if E911, take off hook */
05739                if (p->sig == SIG_E911)
05740                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05741                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
05742             }
05743             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05744             break;
05745          case SIG_FEATB:
05746          case SIG_SF_FEATB:
05747             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05748             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05749             break;
05750          case SIG_EMWINK:
05751             /* if we received a '*', we are actually receiving Feature Group D
05752                dial syntax, so use that mode; otherwise, fall through to normal
05753                mode
05754             */
05755             if (res == '*') {
05756                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
05757                if (res > 0)
05758                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
05759                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05760                break;
05761             }
05762          default:
05763             /* If we got the first digit, get the rest */
05764             len = 1;
05765             dtmfbuf[len] = '\0';
05766             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
05767                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
05768                   timeout = matchdigittimeout;
05769                } else {
05770                   timeout = gendigittimeout;
05771                }
05772                res = ast_waitfordigit(chan, timeout);
05773                if (res < 0) {
05774                   ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
05775                   ast_hangup(chan);
05776                   goto quit;
05777                } else if (res) {
05778                   dtmfbuf[len++] = res;
05779                   dtmfbuf[len] = '\0';
05780                } else {
05781                   break;
05782                }
05783             }
05784             break;
05785          }
05786       }
05787       if (res == -1) {
05788          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
05789          ast_hangup(chan);
05790          goto quit;
05791       } else if (res < 0) {
05792          ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
05793          ast_hangup(chan);
05794          goto quit;
05795       }
05796 
05797       if (p->sig == SIG_FGC_CAMA) {
05798          char anibuf[100];
05799 
05800          if (ast_safe_sleep(chan,1000) == -1) {
05801                            ast_hangup(chan);
05802                            goto quit;
05803          }
05804                         dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05805                         ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
05806                         res = my_getsigstr(chan, anibuf, "#", 10000);
05807                         if ((res > 0) && (strlen(anibuf) > 2)) {
05808             if (anibuf[strlen(anibuf) - 1] == '#')
05809                anibuf[strlen(anibuf) - 1] = 0;
05810             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
05811          }
05812                         ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
05813       }
05814 
05815       ast_copy_string(exten, dtmfbuf, sizeof(exten));
05816       if (ast_strlen_zero(exten))
05817          ast_copy_string(exten, "s", sizeof(exten));
05818       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
05819          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
05820          if (exten[0] == '*') {
05821             char *stringp=NULL;
05822             ast_copy_string(exten2, exten, sizeof(exten2));
05823             /* Parse out extension and callerid */
05824             stringp=exten2 +1;
05825             s1 = strsep(&stringp, "*");
05826             s2 = strsep(&stringp, "*");
05827             if (s2) {
05828                if (!ast_strlen_zero(p->cid_num))
05829                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
05830                else
05831                   ast_set_callerid(chan, s1, NULL, s1);
05832                ast_copy_string(exten, s2, sizeof(exten));
05833             } else
05834                ast_copy_string(exten, s1, sizeof(exten));
05835          } else if (p->sig == SIG_FEATD)
05836             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
05837       }
05838       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
05839          if (exten[0] == '*') {
05840             char *stringp=NULL;
05841             ast_copy_string(exten2, exten, sizeof(exten2));
05842             /* Parse out extension and callerid */
05843             stringp=exten2 +1;
05844             s1 = strsep(&stringp, "#");
05845             s2 = strsep(&stringp, "#");
05846             if (s2) {
05847                if (!ast_strlen_zero(p->cid_num))
05848                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
05849                else
05850                   if (*(s1 + 2))
05851                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
05852                ast_copy_string(exten, s2 + 1, sizeof(exten));
05853             } else
05854                ast_copy_string(exten, s1 + 2, sizeof(exten));
05855          } else
05856             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
05857       }
05858       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
05859          if (exten[0] == '*') {
05860             char *stringp=NULL;
05861             ast_copy_string(exten2, exten, sizeof(exten2));
05862             /* Parse out extension and callerid */
05863             stringp=exten2 +1;
05864             s1 = strsep(&stringp, "#");
05865             s2 = strsep(&stringp, "#");
05866             if (s2 && (*(s2 + 1) == '0')) {
05867                if (*(s2 + 2))
05868                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
05869             }
05870             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
05871             else ast_copy_string(exten, "911", sizeof(exten));
05872          } else
05873             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
05874       }
05875       if (p->sig == SIG_FEATB) {
05876          if (exten[0] == '*') {
05877             char *stringp=NULL;
05878             ast_copy_string(exten2, exten, sizeof(exten2));
05879             /* Parse out extension and callerid */
05880             stringp=exten2 +1;
05881             s1 = strsep(&stringp, "#");
05882             ast_copy_string(exten, exten2 + 1, sizeof(exten));
05883          } else
05884             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
05885       }
05886       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
05887          dahdi_wink(p, index);
05888                         /* some switches require a minimum guard time between
05889                            the last FGD wink and something that answers
05890                            immediately. This ensures it */
05891                         if (ast_safe_sleep(chan,100)) goto quit;
05892       }
05893       dahdi_enable_ec(p);
05894       if (NEED_MFDETECT(p)) {
05895          if (p->dsp) {
05896             if (!p->hardwaredtmf)
05897                ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 
05898             else {
05899                ast_dsp_free(p->dsp);
05900                p->dsp = NULL;
05901             }
05902          }
05903       }
05904 
05905       if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
05906          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
05907          if (p->dsp) ast_dsp_digitreset(p->dsp);
05908          res = ast_pbx_run(chan);
05909          if (res) {
05910             ast_log(LOG_WARNING, "PBX exited non-zero\n");
05911             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05912          }
05913          goto quit;
05914       } else {
05915          if (option_verbose > 2)
05916             ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
05917          sleep(2);
05918          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
05919          if (res < 0)
05920             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
05921          else
05922             sleep(1);
05923          res = ast_streamfile(chan, "ss-noservice", chan->language);
05924          if (res >= 0)
05925             ast_waitstream(chan, "");
05926          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05927          ast_hangup(chan);
05928          goto quit;
05929       }
05930       break;
05931    case SIG_FXOLS:
05932    case SIG_FXOGS:
05933    case SIG_FXOKS:
05934       /* Read the first digit */
05935       timeout = firstdigittimeout;
05936       /* If starting a threeway call, never timeout on the first digit so someone
05937          can use flash-hook as a "hold" feature */
05938       if (p->subs[SUB_THREEWAY].owner) 
05939          timeout = 999999;
05940       while (len < AST_MAX_EXTENSION-1) {
05941          /* Read digit unless it's supposed to be immediate, in which case the
05942             only answer is 's' */
05943          if (p->immediate) 
05944             res = 's';
05945          else
05946             res = ast_waitfordigit(chan, timeout);
05947          timeout = 0;
05948          if (res < 0) {
05949             ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
05950             res = tone_zone_play_tone(p->subs[index].dfd, -1);
05951             ast_hangup(chan);
05952             goto quit;
05953          } else if (res)  {
05954             exten[len++]=res;
05955             exten[len] = '\0';
05956          }
05957          if (!ast_ignore_pattern(chan->context, exten))
05958             tone_zone_play_tone(p->subs[index].dfd, -1);
05959          else
05960             tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
05961          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
05962             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
05963                if (getforward) {
05964                   /* Record this as the forwarding extension */
05965                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 
05966                   if (option_verbose > 2)
05967                      ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
05968                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
05969                   if (res)
05970                      break;
05971                   usleep(500000);
05972                   res = tone_zone_play_tone(p->subs[index].dfd, -1);
05973                   sleep(1);
05974                   memset(exten, 0, sizeof(exten));
05975                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
05976                   len = 0;
05977                   getforward = 0;
05978                } else  {
05979                   res = tone_zone_play_tone(p->subs[index].dfd, -1);
05980                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
05981                   if (!ast_strlen_zero(p->cid_num)) {
05982                      if (!p->hidecallerid)
05983                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 
05984                      else
05985                         ast_set_callerid(chan, NULL, NULL, p->cid_num); 
05986                   }
05987                   if (!ast_strlen_zero(p->cid_name)) {
05988                      if (!p->hidecallerid)
05989                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
05990                   }
05991                   ast_setstate(chan, AST_STATE_RING);
05992                   dahdi_enable_ec(p);
05993                   res = ast_pbx_run(chan);
05994                   if (res) {
05995                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
05996                      res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05997                   }
05998                   goto quit;
05999                }
06000             } else {
06001                /* It's a match, but they just typed a digit, and there is an ambiguous match,
06002                   so just set the timeout to matchdigittimeout and wait some more */
06003                timeout = matchdigittimeout;
06004             }
06005          } else if (res == 0) {
06006             ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
06007             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06008             dahdi_wait_event(p->subs[index].dfd);
06009             ast_hangup(chan);
06010             goto quit;
06011          } else if (p->callwaiting && !strcmp(exten, "*70")) {
06012             if (option_verbose > 2) 
06013                ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
06014             /* Disable call waiting if enabled */
06015             p->callwaiting = 0;
06016             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06017             if (res) {
06018                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
06019                   chan->name, strerror(errno));
06020             }
06021             len = 0;
06022             ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
06023             memset(exten, 0, sizeof(exten));
06024             timeout = firstdigittimeout;
06025                
06026          } else if (!strcmp(exten,ast_pickup_ext())) {
06027             /* Scan all channels and see if there are any
06028              * ringing channels that have call groups
06029              * that equal this channels pickup group  
06030              */
06031             if (index == SUB_REAL) {
06032                /* Switch us from Third call to Call Wait */
06033                if (p->subs[SUB_THREEWAY].owner) {
06034                   /* If you make a threeway call and the *8# a call, it should actually 
06035                      look like a callwait */
06036                   alloc_sub(p, SUB_CALLWAIT);   
06037                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06038                   unalloc_sub(p, SUB_THREEWAY);
06039                }
06040                dahdi_enable_ec(p);
06041                if (ast_pickup_call(chan)) {
06042                   ast_log(LOG_DEBUG, "No call pickup possible...\n");
06043                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06044                   dahdi_wait_event(p->subs[index].dfd);
06045                }
06046                ast_hangup(chan);
06047                goto quit;
06048             } else {
06049                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
06050                ast_hangup(chan);
06051                goto quit;
06052             }
06053             
06054          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
06055             if (option_verbose > 2) 
06056                ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
06057             /* Disable Caller*ID if enabled */
06058             p->hidecallerid = 1;
06059             if (chan->cid.cid_num)
06060                free(chan->cid.cid_num);
06061             chan->cid.cid_num = NULL;
06062             if (chan->cid.cid_name)
06063                free(chan->cid.cid_name);
06064             chan->cid.cid_name = NULL;
06065             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06066             if (res) {
06067                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
06068                   chan->name, strerror(errno));
06069             }
06070             len = 0;
06071             memset(exten, 0, sizeof(exten));
06072             timeout = firstdigittimeout;
06073          } else if (p->callreturn && !strcmp(exten, "*69")) {
06074             res = 0;
06075             if (!ast_strlen_zero(p->lastcid_num)) {
06076                res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
06077             }
06078             if (!res)
06079                res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06080             break;
06081          } else if (!strcmp(exten, "*78")) {
06082             /* Do not disturb */
06083             if (option_verbose > 2)
06084                ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
06085             manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06086                      "Channel: %s/%d\r\n"
06087                      "Status: enabled\r\n", dahdi_chan_name, p->channel);
06088             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06089             p->dnd = 1;
06090             getforward = 0;
06091             memset(exten, 0, sizeof(exten));
06092             len = 0;
06093          } else if (!strcmp(exten, "*79")) {
06094             /* Do not disturb */
06095             if (option_verbose > 2)
06096                ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
06097             manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06098                      "Channel: %s/%d\r\n"
06099                      "Status: disabled\r\n", dahdi_chan_name, p->channel);
06100             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06101             p->dnd = 0;
06102             getforward = 0;
06103             memset(exten, 0, sizeof(exten));
06104             len = 0;
06105          } else if (p->cancallforward && !strcmp(exten, "*72")) {
06106             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06107             getforward = 1;
06108             memset(exten, 0, sizeof(exten));
06109             len = 0;
06110          } else if (p->cancallforward && !strcmp(exten, "*73")) {
06111             if (option_verbose > 2)
06112                ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
06113             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06114             memset(p->call_forward, 0, sizeof(p->call_forward));
06115             getforward = 0;
06116             memset(exten, 0, sizeof(exten));
06117             len = 0;
06118          } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 
06119                   p->subs[SUB_THREEWAY].owner &&
06120                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06121             /* This is a three way call, the main call being a real channel, 
06122                and we're parking the first call. */
06123             ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
06124             if (option_verbose > 2)
06125                ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
06126             break;
06127          } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
06128             if (option_verbose > 2)
06129                ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
06130             res = ast_db_put("blacklist", p->lastcid_num, "1");
06131             if (!res) {
06132                res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06133                memset(exten, 0, sizeof(exten));
06134                len = 0;
06135             }
06136          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
06137             if (option_verbose > 2) 
06138                ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
06139             /* Enable Caller*ID if enabled */
06140             p->hidecallerid = 0;
06141             if (chan->cid.cid_num)
06142                free(chan->cid.cid_num);
06143             chan->cid.cid_num = NULL;
06144             if (chan->cid.cid_name)
06145                free(chan->cid.cid_name);
06146             chan->cid.cid_name = NULL;
06147             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
06148             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06149             if (res) {
06150                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
06151                   chan->name, strerror(errno));
06152             }
06153             len = 0;
06154             memset(exten, 0, sizeof(exten));
06155             timeout = firstdigittimeout;
06156          } else if (!strcmp(exten, "*0")) {
06157             struct ast_channel *nbridge = 
06158                p->subs[SUB_THREEWAY].owner;
06159             struct dahdi_pvt *pbridge = NULL;
06160               /* set up the private struct of the bridged one, if any */
06161             if (nbridge && ast_bridged_channel(nbridge)) 
06162                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
06163             if (nbridge && pbridge && 
06164                 (nbridge->tech == chan_tech) && 
06165                 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
06166                 ISTRUNK(pbridge)) {
06167                int func = DAHDI_FLASH;
06168                /* Clear out the dial buffer */
06169                p->dop.dialstr[0] = '\0';
06170                /* flash hookswitch */
06171                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06172                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
06173                      nbridge->name, strerror(errno));
06174                }
06175                swap_subs(p, SUB_REAL, SUB_THREEWAY);
06176                unalloc_sub(p, SUB_THREEWAY);
06177                p->owner = p->subs[SUB_REAL].owner;
06178                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06179                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06180                ast_hangup(chan);
06181                goto quit;
06182             } else {
06183                tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06184                dahdi_wait_event(p->subs[index].dfd);
06185                tone_zone_play_tone(p->subs[index].dfd, -1);
06186                swap_subs(p, SUB_REAL, SUB_THREEWAY);
06187                unalloc_sub(p, SUB_THREEWAY);
06188                p->owner = p->subs[SUB_REAL].owner;
06189                ast_hangup(chan);
06190                goto quit;
06191             }              
06192          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
06193                      ((exten[0] != '*') || (strlen(exten) > 2))) {
06194             if (option_debug)
06195                ast_log(LOG_DEBUG, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
06196             break;
06197          }
06198          if (!timeout)
06199             timeout = gendigittimeout;
06200          if (len && !ast_ignore_pattern(chan->context, exten))
06201             tone_zone_play_tone(p->subs[index].dfd, -1);
06202       }
06203       break;
06204    case SIG_FXSLS:
06205    case SIG_FXSGS:
06206    case SIG_FXSKS:
06207 #ifdef HAVE_PRI
06208       if (p->pri) {
06209          /* This is a GR-303 trunk actually.  Wait for the first ring... */
06210          struct ast_frame *f;
06211          int res;
06212          time_t start;
06213 
06214          time(&start);
06215          ast_setstate(chan, AST_STATE_RING);
06216          while (time(NULL) < start + 3) {
06217             res = ast_waitfor(chan, 1000);
06218             if (res) {
06219                f = ast_read(chan);
06220                if (!f) {
06221                   ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
06222                   ast_hangup(chan);
06223                   goto quit;
06224                } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
06225                   res = 1;
06226                } else
06227                   res = 0;
06228                ast_frfree(f);
06229                if (res) {
06230                   ast_log(LOG_DEBUG, "Got ring!\n");
06231                   res = 0;
06232                   break;
06233                }
06234             }
06235          }
06236       }
06237 #endif
06238       /* check for SMDI messages */
06239       if (p->use_smdi && p->smdi_iface) {
06240          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
06241 
06242          if (smdi_msg != NULL) {
06243             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
06244 
06245             if (smdi_msg->type == 'B')
06246                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
06247             else if (smdi_msg->type == 'N')
06248                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
06249 
06250             ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
06251          } else {
06252             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
06253          }
06254       }
06255 
06256       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
06257             number = smdi_msg->calling_st;
06258 
06259       /* If we want caller id, we're in a prering state due to a polarity reversal
06260        * and we're set to use a polarity reversal to trigger the start of caller id,
06261        * grab the caller id and wait for ringing to start... */
06262       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) {
06263          /* If set to use DTMF CID signalling, listen for DTMF */
06264          if (p->cid_signalling == CID_SIG_DTMF) {
06265             int i = 0;
06266             cs = NULL;
06267             ast_log(LOG_DEBUG, "Receiving DTMF cid on "
06268                "channel %s\n", chan->name);
06269             dahdi_setlinear(p->subs[index].dfd, 0);
06270             res = 2000;
06271             for (;;) {
06272                struct ast_frame *f;
06273                res = ast_waitfor(chan, res);
06274                if (res <= 0) {
06275                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
06276                      "Exiting simple switch\n");
06277                   ast_hangup(chan);
06278                   goto quit;
06279                } 
06280                f = ast_read(chan);
06281                if (!f)
06282                   break;
06283                if (f->frametype == AST_FRAME_DTMF) {
06284                   dtmfbuf[i++] = f->subclass;
06285                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
06286                   res = 2000;
06287                }
06288                ast_frfree(f);
06289                if (chan->_state == AST_STATE_RING ||
06290                    chan->_state == AST_STATE_RINGING) 
06291                   break; /* Got ring */
06292             }
06293             dtmfbuf[i] = '\0';
06294             dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06295             /* Got cid and ring. */
06296             ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
06297             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
06298             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 
06299                dtmfcid, flags);
06300             /* If first byte is NULL, we have no cid */
06301             if (!ast_strlen_zero(dtmfcid)) 
06302                number = dtmfcid;
06303             else
06304                number = NULL;
06305          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
06306          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
06307             cs = callerid_new(p->cid_signalling);
06308             if (cs) {
06309                samples = 0;
06310 #if 1
06311                bump_gains(p);
06312 #endif            
06313                /* Take out of linear mode for Caller*ID processing */
06314                dahdi_setlinear(p->subs[index].dfd, 0);
06315                
06316                /* First we wait and listen for the Caller*ID */
06317                for (;;) {  
06318                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06319                   if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
06320                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06321                      callerid_free(cs);
06322                      ast_hangup(chan);
06323                      goto quit;
06324                   }
06325                   if (i & DAHDI_IOMUX_SIGEVENT) {
06326                      res = dahdi_get_event(p->subs[index].dfd);
06327                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06328 
06329                      if (p->cid_signalling == CID_SIG_V23_JP) {
06330 #ifdef DAHDI_EVENT_RINGBEGIN
06331                         if (res == DAHDI_EVENT_RINGBEGIN) {
06332                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06333                            usleep(1);
06334                         }
06335 #endif
06336                      } else {
06337                         res = 0;
06338                         break;
06339                      }
06340                   } else if (i & DAHDI_IOMUX_READ) {
06341                      res = read(p->subs[index].dfd, buf, sizeof(buf));
06342                      if (res < 0) {
06343                         if (errno != ELAST) {
06344                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06345                            callerid_free(cs);
06346                            ast_hangup(chan);
06347                            goto quit;
06348                         }
06349                         break;
06350                      }
06351                      samples += res;
06352 
06353                      if  (p->cid_signalling == CID_SIG_V23_JP) {
06354                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
06355                      } else {
06356                         res = callerid_feed(cs, buf, res, AST_LAW(p));
06357                      }
06358 
06359                      if (res < 0) {
06360                         ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
06361                         break;
06362                      } else if (res)
06363                         break;
06364                      else if (samples > (8000 * 10))
06365                         break;
06366                   }
06367                }
06368                if (res == 1) {
06369                   callerid_get(cs, &name, &number, &flags);
06370                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
06371                }
06372 
06373                if (p->cid_signalling == CID_SIG_V23_JP) {
06374                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06375                   usleep(1);
06376                   res = 4000;
06377                } else {
06378 
06379                   /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 
06380                   res = 2000;
06381                }
06382 
06383                for (;;) {
06384                   struct ast_frame *f;
06385                   res = ast_waitfor(chan, res);
06386                   if (res <= 0) {
06387                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
06388                         "Exiting simple switch\n");
06389                      ast_hangup(chan);
06390                      goto quit;
06391                   } 
06392                   if (!(f = ast_read(chan))) {
06393                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
06394                      ast_hangup(chan);
06395                      goto quit;
06396                   }
06397                   ast_frfree(f);
06398                   if (chan->_state == AST_STATE_RING ||
06399                       chan->_state == AST_STATE_RINGING) 
06400                      break; /* Got ring */
06401                }
06402    
06403                /* We must have a ring by now, so, if configured, lets try to listen for
06404                 * distinctive ringing */ 
06405                if (p->usedistinctiveringdetection == 1) {
06406                   len = 0;
06407                   distMatches = 0;
06408                   /* Clear the current ring data array so we dont have old data in it. */
06409                   for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
06410                      curRingData[receivedRingT] = 0;
06411                   receivedRingT = 0;
06412                   counter = 0;
06413                   counter1 = 0;
06414                   /* Check to see if context is what it should be, if not set to be. */
06415                   if (strcmp(p->context,p->defcontext) != 0) {
06416                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
06417                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
06418                   }
06419       
06420                   for (;;) {  
06421                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06422                      if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
06423                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06424                         callerid_free(cs);
06425                         ast_hangup(chan);
06426                         goto quit;
06427                      }
06428                      if (i & DAHDI_IOMUX_SIGEVENT) {
06429                         res = dahdi_get_event(p->subs[index].dfd);
06430                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06431                         res = 0;
06432                         /* Let us detect distinctive ring */
06433       
06434                         curRingData[receivedRingT] = p->ringt;
06435       
06436                         if (p->ringt < p->ringt_base/2)
06437                            break;
06438                         /* Increment the ringT counter so we can match it against
06439                            values in chan_dahdi.conf for distinctive ring */
06440                         if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06441                            break;
06442                      } else if (i & DAHDI_IOMUX_READ) {
06443                         res = read(p->subs[index].dfd, buf, sizeof(buf));
06444                         if (res < 0) {
06445                            if (errno != ELAST) {
06446                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06447                               callerid_free(cs);
06448                               ast_hangup(chan);
06449                               goto quit;
06450                            }
06451                            break;
06452                         }
06453                         if (p->ringt) 
06454                            p->ringt--;
06455                         if (p->ringt == 1) {
06456                            res = -1;
06457                            break;
06458                         }
06459                      }
06460                   }
06461                   if (option_verbose > 2)
06462                      /* this only shows up if you have n of the dring patterns filled in */
06463                      ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
06464    
06465                   for (counter = 0; counter < 3; counter++) {
06466                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
06467                      channel */
06468                      distMatches = 0;
06469                      for (counter1 = 0; counter1 < 3; counter1++) {
06470                         if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
06471                         (p->drings.ringnum[counter].ring[counter1]-10)) {
06472                            distMatches++;
06473                         }
06474                      }
06475                      if (distMatches == 3) {
06476                         /* The ring matches, set the context to whatever is for distinctive ring.. */
06477                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
06478                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
06479                         if (option_verbose > 2)
06480                            ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
06481                         break;
06482                      }
06483                   }
06484                }
06485                /* Restore linear mode (if appropriate) for Caller*ID processing */
06486                dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06487 #if 1
06488                restore_gains(p);
06489 #endif            
06490             } else
06491                ast_log(LOG_WARNING, "Unable to get caller ID space\n");       
06492          } else {
06493             ast_log(LOG_WARNING, "Channel %s in prering "
06494                "state, but I have nothing to do. "
06495                "Terminating simple switch, should be "
06496                "restarted by the actual ring.\n", 
06497                chan->name);
06498             ast_hangup(chan);
06499             goto quit;
06500          }
06501       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
06502          /* FSK Bell202 callerID */
06503          cs = callerid_new(p->cid_signalling);
06504          if (cs) {
06505 #if 1
06506             bump_gains(p);
06507 #endif            
06508             samples = 0;
06509             len = 0;
06510             distMatches = 0;
06511             /* Clear the current ring data array so we dont have old data in it. */
06512             for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
06513                curRingData[receivedRingT] = 0;
06514             receivedRingT = 0;
06515             counter = 0;
06516             counter1 = 0;
06517             /* Check to see if context is what it should be, if not set to be. */
06518             if (strcmp(p->context,p->defcontext) != 0) {
06519                ast_copy_string(p->context, p->defcontext, sizeof(p->context));
06520                ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
06521             }
06522 
06523             /* Take out of linear mode for Caller*ID processing */
06524             dahdi_setlinear(p->subs[index].dfd, 0);
06525             for (;;) {  
06526                i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06527                if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
06528                   ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06529                   callerid_free(cs);
06530                   ast_hangup(chan);
06531                   goto quit;
06532                }
06533                if (i & DAHDI_IOMUX_SIGEVENT) {
06534                   res = dahdi_get_event(p->subs[index].dfd);
06535                   ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06536                   /* If we get a PR event, they hung up while processing calerid */
06537                   if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
06538                      ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
06539                      p->polarity = POLARITY_IDLE;
06540                      callerid_free(cs);
06541                      ast_hangup(chan);
06542                      goto quit;
06543                   }
06544                   res = 0;
06545                   /* Let us detect callerid when the telco uses distinctive ring */
06546 
06547                   curRingData[receivedRingT] = p->ringt;
06548 
06549                   if (p->ringt < p->ringt_base/2)
06550                      break;
06551                   /* Increment the ringT counter so we can match it against
06552                      values in chan_dahdi.conf for distinctive ring */
06553                   if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06554                      break;
06555                } else if (i & DAHDI_IOMUX_READ) {
06556                   res = read(p->subs[index].dfd, buf, sizeof(buf));
06557                   if (res < 0) {
06558                      if (errno != ELAST) {
06559                         ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06560                         callerid_free(cs);
06561                         ast_hangup(chan);
06562                         goto quit;
06563                      }
06564                      break;
06565                   }
06566                   if (p->ringt) 
06567                      p->ringt--;
06568                   if (p->ringt == 1) {
06569                      res = -1;
06570                      break;
06571                   }
06572                   samples += res;
06573                   res = callerid_feed(cs, buf, res, AST_LAW(p));
06574                   if (res < 0) {
06575                      ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
06576                      break;
06577                   } else if (res)
06578                      break;
06579                   else if (samples > (8000 * 10))
06580                      break;
06581                }
06582             }
06583             if (res == 1) {
06584                callerid_get(cs, &name, &number, &flags);
06585                if (option_debug)
06586                   ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
06587             }
06588             if (distinctiveringaftercid == 1) {
06589                /* Clear the current ring data array so we dont have old data in it. */
06590                for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
06591                   curRingData[receivedRingT] = 0;
06592                }
06593                receivedRingT = 0;
06594                if (option_verbose > 2)
06595                   ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
06596                for (;;) {
06597                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06598                   if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))    {
06599                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06600                      callerid_free(cs);
06601                      ast_hangup(chan);
06602                      goto quit;
06603                   }
06604                   if (i & DAHDI_IOMUX_SIGEVENT) {
06605                      res = dahdi_get_event(p->subs[index].dfd);
06606                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06607                      res = 0;
06608                      /* Let us detect callerid when the telco uses distinctive ring */
06609 
06610                      curRingData[receivedRingT] = p->ringt;
06611 
06612                      if (p->ringt < p->ringt_base/2)
06613                         break;
06614                      /* Increment the ringT counter so we can match it against
06615                         values in chan_dahdi.conf for distinctive ring */
06616                      if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06617                         break;
06618                   } else if (i & DAHDI_IOMUX_READ) {
06619                      res = read(p->subs[index].dfd, buf, sizeof(buf));
06620                      if (res < 0) {
06621                         if (errno != ELAST) {
06622                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06623                            callerid_free(cs);
06624                            ast_hangup(chan);
06625                            goto quit;
06626                         }
06627                         break;
06628                      }
06629                   if (p->ringt)
06630                      p->ringt--;
06631                      if (p->ringt == 1) {
06632                         res = -1;
06633                         break;
06634                      }
06635                   }
06636                }
06637             }
06638             if (p->usedistinctiveringdetection == 1) {
06639                if (option_verbose > 2)
06640                   /* this only shows up if you have n of the dring patterns filled in */
06641                   ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
06642 
06643                for (counter = 0; counter < 3; counter++) {
06644                   /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
06645                   channel */
06646                   if (option_verbose > 2)
06647                      /* this only shows up if you have n of the dring patterns filled in */
06648                      ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
06649                         p->drings.ringnum[counter].ring[0],
06650                         p->drings.ringnum[counter].ring[1],
06651                         p->drings.ringnum[counter].ring[2]);
06652                   distMatches = 0;
06653                   for (counter1 = 0; counter1 < 3; counter1++) {
06654                      if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
06655                      (p->drings.ringnum[counter].ring[counter1]-10)) {
06656                         distMatches++;
06657                      }
06658                   }
06659                   if (distMatches == 3) {
06660                      /* The ring matches, set the context to whatever is for distinctive ring.. */
06661                      ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
06662                      ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
06663                      if (option_verbose > 2)
06664                         ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
06665                      break;
06666                   }
06667                }
06668             }
06669             /* Restore linear mode (if appropriate) for Caller*ID processing */
06670             dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06671 #if 1
06672             restore_gains(p);
06673 #endif            
06674             if (res < 0) {
06675                ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
06676             }
06677          } else
06678             ast_log(LOG_WARNING, "Unable to get caller ID space\n");
06679       }
06680       else
06681          cs = NULL;
06682 
06683       if (number)
06684          ast_shrink_phone_number(number);
06685       ast_set_callerid(chan, number, name, number);
06686 
06687       if (smdi_msg)
06688          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
06689 
06690       if (cs)
06691          callerid_free(cs);
06692 
06693       ast_setstate(chan, AST_STATE_RING);
06694       chan->rings = 1;
06695       p->ringt = p->ringt_base;
06696       res = ast_pbx_run(chan);
06697       if (res) {
06698          ast_hangup(chan);
06699          ast_log(LOG_WARNING, "PBX exited non-zero\n");
06700       }
06701       goto quit;
06702    default:
06703       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
06704       res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06705       if (res < 0)
06706             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
06707    }
06708    res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06709    if (res < 0)
06710          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
06711    ast_hangup(chan);
06712 quit:
06713    ast_mutex_lock(&ss_thread_lock);
06714    ss_thread_count--;
06715    ast_cond_signal(&ss_thread_complete);
06716    ast_mutex_unlock(&ss_thread_lock);
06717    return NULL;
06718 }

static void swap_subs ( struct dahdi_pvt p,
int  a,
int  b 
) [static]

Definition at line 878 of file chan_dahdi.c.

References ast_log(), dahdi_subchannel::chan, dahdi_subchannel::dfd, ast_channel::fds, dahdi_subchannel::inthreeway, LOG_DEBUG, dahdi_subchannel::owner, dahdi_pvt::subs, and wakeup_sub().

Referenced by attempt_transfer(), dahdi_answer(), dahdi_handle_event(), dahdi_hangup(), and ss_thread().

00879 {
00880    int tchan;
00881    int tinthreeway;
00882    struct ast_channel *towner;
00883 
00884    ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
00885 
00886    tchan = p->subs[a].chan;
00887    towner = p->subs[a].owner;
00888    tinthreeway = p->subs[a].inthreeway;
00889 
00890    p->subs[a].chan = p->subs[b].chan;
00891    p->subs[a].owner = p->subs[b].owner;
00892    p->subs[a].inthreeway = p->subs[b].inthreeway;
00893 
00894    p->subs[b].chan = tchan;
00895    p->subs[b].owner = towner;
00896    p->subs[b].inthreeway = tinthreeway;
00897 
00898    if (p->subs[a].owner) 
00899       p->subs[a].owner->fds[0] = p->subs[a].dfd;
00900    if (p->subs[b].owner) 
00901       p->subs[b].owner->fds[0] = p->subs[b].dfd;
00902    wakeup_sub(p, a, NULL);
00903    wakeup_sub(p, b, NULL);
00904 }

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

Definition at line 1025 of file chan_dahdi.c.

References ast_log(), dahdi_subchannel::chan, dahdi_pvt::channel, dahdi_subchannel::curconf, dahdi_close_sub(), dahdi_subchannel::inthreeway, dahdi_subchannel::linear, LOG_DEBUG, LOG_WARNING, dahdi_subchannel::owner, dahdi_pvt::polarity, POLARITY_IDLE, and dahdi_pvt::subs.

Referenced by attempt_transfer(), dahdi_handle_event(), dahdi_hangup(), and ss_thread().

01026 {
01027    if (!x) {
01028       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01029       return -1;
01030    }
01031    ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
01032    dahdi_close_sub(p, x);
01033    p->subs[x].linear = 0;
01034    p->subs[x].chan = 0;
01035    p->subs[x].owner = NULL;
01036    p->subs[x].inthreeway = 0;
01037    p->polarity = POLARITY_IDLE;
01038    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01039    return 0;
01040 }

static int unload_module ( void   )  [static]

Definition at line 10900 of file chan_dahdi.c.

References __unload_module(), ast_mutex_destroy(), and lock.

10901 {
10902 #ifdef HAVE_PRI      
10903    int y;
10904    for (y = 0; y < NUM_SPANS; y++)
10905       ast_mutex_destroy(&pris[y].lock);
10906 #endif
10907    return __unload_module();
10908 }

static int update_conf ( struct dahdi_pvt p  )  [static]

Definition at line 1408 of file chan_dahdi.c.

References conf_add(), conf_del(), dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, isslavenative(), and dahdi_pvt::subs.

Referenced by __dahdi_exception(), dahdi_bridge(), dahdi_handle_event(), and dahdi_hangup().

01409 {
01410    int needconf = 0;
01411    int x;
01412    int useslavenative;
01413    struct dahdi_pvt *slave = NULL;
01414 
01415    useslavenative = isslavenative(p, &slave);
01416    /* Start with the obvious, general stuff */
01417    for (x = 0; x < 3; x++) {
01418       /* Look for three way calls */
01419       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
01420          conf_add(p, &p->subs[x], x, 0);
01421          needconf++;
01422       } else {
01423          conf_del(p, &p->subs[x], x);
01424       }
01425    }
01426    /* If we have a slave, add him to our conference now. or DAX
01427       if this is slave native */
01428    for (x = 0; x < MAX_SLAVES; x++) {
01429       if (p->slaves[x]) {
01430          if (useslavenative)
01431             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
01432          else {
01433             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
01434             needconf++;
01435          }
01436       }
01437    }
01438    /* If we're supposed to be in there, do so now */
01439    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
01440       if (useslavenative)
01441          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
01442       else {
01443          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
01444          needconf++;
01445       }
01446    }
01447    /* If we have a master, add ourselves to his conference */
01448    if (p->master) {
01449       if (isslavenative(p->master, NULL)) {
01450          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
01451       } else {
01452          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
01453       }
01454    }
01455    if (!needconf) {
01456       /* Nobody is left (or should be left) in our conference.
01457          Kill it. */
01458       p->confno = -1;
01459    }
01460    if (option_debug)
01461       ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
01462    return 0;
01463 }

static void wakeup_sub ( struct dahdi_pvt p,
int  a,
void *  pri 
) [static]

Definition at line 822 of file chan_dahdi.c.

References ast_mutex_trylock(), ast_mutex_unlock(), ast_null_frame, ast_queue_frame(), DEADLOCK_AVOIDANCE, dahdi_pvt::lock, ast_channel::lock, dahdi_subchannel::owner, and dahdi_pvt::subs.

Referenced by swap_subs().

00824 {
00825 #ifdef HAVE_PRI
00826    if (pri)
00827       ast_mutex_unlock(&pri->lock);
00828 #endif         
00829    for (;;) {
00830       if (p->subs[a].owner) {
00831          if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
00832             DEADLOCK_AVOIDANCE(&p->lock);
00833          } else {
00834             ast_queue_frame(p->subs[a].owner, &ast_null_frame);
00835             ast_mutex_unlock(&p->subs[a].owner->lock);
00836             break;
00837          }
00838       } else
00839          break;
00840    }
00841 #ifdef HAVE_PRI
00842    if (pri)
00843       ast_mutex_lock(&pri->lock);
00844 #endif         
00845 }

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

Definition at line 10746 of file chan_dahdi.c.

References __action_dialoffhook(), and s.

10747 {
10748    return __action_dialoffhook(s, m, 1);
10749 }

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

Definition at line 10646 of file chan_dahdi.c.

References __action_dnd(), and s.

10647 {
10648    return __action_dnd(s, m, 1, 0);
10649 }

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

Definition at line 10636 of file chan_dahdi.c.

References __action_dnd(), and s.

10637 {
10638    return __action_dnd(s, m, 1, 1);
10639 }

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

Definition at line 10825 of file chan_dahdi.c.

References __action_restart(), and s.

10826 {
10827    return __action_restart(s, m, 1);
10828 }

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

Definition at line 10801 of file chan_dahdi.c.

References __action_showchannels(), and s.

10802 {
10803    return __action_showchannels(s, m, 1);
10804 }

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

Definition at line 10675 of file chan_dahdi.c.

References __action_transfer(), and s.

10676 {
10677    return __action_transfer(s, m, 1);
10678 }

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

Definition at line 10703 of file chan_dahdi.c.

References __action_transferhangup(), and s.

10704 {
10705    return __action_transferhangup(s, m, 1);
10706 }


Variable Documentation

int alarm

Definition at line 1177 of file chan_dahdi.c.

Referenced by __action_showchannels().

struct { ... } alarms[] [static]

Referenced by alarm2str(), and dahdi_show_status().

struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static]

Definition at line 778 of file chan_dahdi.c.

struct ast_channel_tech* chan_tech [static]

Definition at line 746 of file chan_dahdi.c.

Referenced by __unload_module(), ast_device_state(), dahdi_new(), load_module(), and ss_thread().

int cidrings[NUM_CADENCE_MAX] [static]

cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on.

Definition at line 789 of file chan_dahdi.c.

struct ast_cli_entry cli_zap_destroy_channel_deprecated [static]

Initial value:

 {
   { "zap", "destroy", "channel", NULL },
   dahdi_destroy_channel, NULL,
   NULL }

Definition at line 10542 of file chan_dahdi.c.

struct ast_cli_entry cli_zap_restart_deprecated [static]

Initial value:

 {
   { "zap", "restart", NULL },
   dahdi_restart_cmd, NULL,
   NULL }

Definition at line 10547 of file chan_dahdi.c.

struct ast_cli_entry cli_zap_show_cadences_deprecated [static]

Initial value:

 {
   { "zap", "show", "cadences", NULL },
   handle_dahdi_show_cadences, NULL,
   NULL }

Definition at line 10527 of file chan_dahdi.c.

struct ast_cli_entry cli_zap_show_channel_deprecated [static]

Initial value:

 {
   { "zap", "show", "channel", NULL },
   dahdi_show_channel, NULL,
   NULL }

Definition at line 10537 of file chan_dahdi.c.

struct ast_cli_entry cli_zap_show_channels_deprecated [static]

Initial value:

 {
   { "zap", "show", "channels", NULL },
   dahdi_show_channels, NULL,
   NULL }

Definition at line 10532 of file chan_dahdi.c.

struct ast_cli_entry cli_zap_show_status_deprecated [static]

Initial value:

 {
   { "zap", "show", "status", NULL },
   dahdi_show_status, NULL,
   NULL }

Definition at line 10552 of file chan_dahdi.c.

struct ast_cli_entry dahdi_cli[] [static]

Definition at line 10557 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

char dahdi_restart_usage[] [static]

Definition at line 10520 of file chan_dahdi.c.

char dahdi_show_cadences_usage[] [static]

Initial value:

"Usage: dahdi show cadences\n"
"       Shows all cadences currently defined\n"

Definition at line 10405 of file chan_dahdi.c.

char dahdi_show_status_usage[] [static]

Initial value:

   "Usage: dahdi show status\n"
   "       Shows a list of DAHDI cards with status\n"

Definition at line 10512 of file chan_dahdi.c.

struct ast_channel_tech dahdi_tech [static]

Definition at line 704 of file chan_dahdi.c.

Referenced by load_module().

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 110 of file chan_dahdi.c.

char defaultcic[64] = "" [static]

Definition at line 199 of file chan_dahdi.c.

char defaultozz[64] = "" [static]

Definition at line 200 of file chan_dahdi.c.

char destroy_channel_usage[] [static]

Initial value:

   "Usage: dahdi destroy channel <chan num>\n"
   "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n"

Definition at line 10516 of file chan_dahdi.c.

int distinctiveringaftercid = 0 [static]

Definition at line 204 of file chan_dahdi.c.

struct dahdi_distRings drings [static]

Definition at line 371 of file chan_dahdi.c.

Referenced by process_dahdi().

char* events[] [static]

Definition at line 1154 of file chan_dahdi.c.

Referenced by authenticate(), and geteventbyname().

int firstdigittimeout = 16000 [static]

Wait up to 16 seconds for first digit (FXO logic).

Definition at line 218 of file chan_dahdi.c.

Referenced by disa_exec(), mgcp_ss(), and skinny_ss().

int gendigittimeout = 8000 [static]

How long to wait for following digits (FXO logic).

Definition at line 221 of file chan_dahdi.c.

Referenced by mgcp_ss(), and skinny_ss().

struct ast_jb_conf global_jbconf [static]

Definition at line 117 of file chan_dahdi.c.

int ifcount = 0 [static]

Definition at line 230 of file chan_dahdi.c.

struct dahdi_pvt * ifend [static]

struct dahdi_pvt * iflist [static]

Referenced by __action_showchannels(), __oh323_destroy(), __sip_destroy(), __sip_show_channels(), __unload_module(), chandup(), complete_sipch(), dahdi_destroy_channel_bynum(), dahdi_hangup(), dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), destroy_channel(), do_monitor(), find_call(), find_call_locked(), find_channel(), get_sip_pvt_byid_locked(), handle_request_subscribe(), load_module(), mkintf(), oh323_alloc(), phone_request(), sip_alloc(), sip_show_channel(), sip_show_history(), and unload_module().

int matchdigittimeout = 3000 [static]

How long to wait for an extra digit, if there is an ambiguous match.

Definition at line 224 of file chan_dahdi.c.

Referenced by mgcp_ss(), and skinny_ss().

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

This is the thread for the monitor which checks for input on the channels which are not currently in use.

Definition at line 242 of file chan_dahdi.c.

Referenced by reload_config(), restart_monitor(), and unload_module().

char* name

Definition at line 1178 of file chan_dahdi.c.

int num_cadence = 4 [static]

Definition at line 775 of file chan_dahdi.c.

int num_restart_pending = 0 [static]

Definition at line 247 of file chan_dahdi.c.

int numbufs = 4 [static]

Definition at line 206 of file chan_dahdi.c.

char progzone[10] = "" [static]

Definition at line 202 of file chan_dahdi.c.

int ringt_base = DEFAULT_RINGT [static]

Definition at line 290 of file chan_dahdi.c.

struct dahdi_pvt* round_robin[32]

Definition at line 754 of file chan_dahdi.c.

Referenced by dahdi_request(), and load_module().

char show_channel_usage[] [static]

Initial value:

   "Usage: dahdi show channel <chan num>\n"
   "  Detailed information about a given channel\n"

Definition at line 10508 of file chan_dahdi.c.

char show_channels_usage[] [static]

Initial value:

   "Usage: dahdi show channels\n"
   "  Shows a list of available channels\n"

Definition at line 10504 of file chan_dahdi.c.

ast_cond_t ss_thread_complete [static]

Definition at line 243 of file chan_dahdi.c.

int ss_thread_count = 0 [static]

Definition at line 246 of file chan_dahdi.c.

char* subnames[] [static]

Initial value:

 {
   "Real",
   "Callwait",
   "Threeway"
}

Definition at line 384 of file chan_dahdi.c.

const char tdesc[] = "DAHDI Telephony Driver" [static]

Definition at line 156 of file chan_dahdi.c.

int user_has_defined_cadences = 0 [static]

Definition at line 776 of file chan_dahdi.c.

struct ast_channel_tech zap_tech [static]

Definition at line 725 of file chan_dahdi.c.

Referenced by load_module().


Generated on Mon Nov 24 15:34:28 2008 for Asterisk - the Open Source PBX by  doxygen 1.4.7