Tue Apr 6 15:45:43 2010

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 <libpri.h>
#include <openr2.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_mfcr2
struct  dahdi_pri
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 DAHDI_OVERLAPDIAL_BOTH   (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
#define DAHDI_OVERLAPDIAL_INCOMING   2
#define DAHDI_OVERLAPDIAL_NONE   0
#define DAHDI_OVERLAPDIAL_OUTGOING   1
#define DAHDI_R2_LOCAL_BLOCK   (1 << 1)
#define DAHDI_R2_REMOTE_BLOCK   (1 << 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_PRI_DEBUG   0
#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 FORMAT   "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
#define FORMAT   "%4s %40s\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)->bearer ? (p)->bearer->channel : 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 PRI_CHANNEL(p)   ((p) & 0xff)
#define PRI_EXPLICIT(p)   (((p) >> 16) & 0x01)
#define PRI_SPAN(p)   (((p) >> 8) & 0xff)
#define PVT_TO_CHANNEL(p)   (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
#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_MFCR2   DAHDI_SIG_CAS
#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 w/PRI"
#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 void __reg_module (void)
static int __unload_module (void)
static void __unreg_module (void)
static char * alarm2str (int alarm)
static int alloc_sub (struct dahdi_pvt *p, int x)
static void apply_plan_to_number (char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
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 void build_status (char *s, size_t len, int status, int active)
static int bump_gains (struct dahdi_pvt *p)
static int calc_energy (const unsigned char *buf, int len, int law)
static struct dahdi_pvtchandup (struct dahdi_pvt *src)
static int check_for_conference (struct dahdi_pvt *p)
static char * complete_span_4 (const char *line, const char *word, int pos, int state)
static char * complete_span_5 (const char *line, const char *word, int pos, int state)
static char * complete_span_helper (const char *line, const char *word, int pos, int state, int rpos)
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_accept_r2_call_exec (struct ast_channel *chan, void *data)
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 openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause (int cause)
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_pri_fd (struct dahdi_pri *pri, int fd_num)
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 *i, int state, int startpbx, int index, int law, int transfercapability)
static int dahdi_open (char *fn)
static void dahdi_pri_error (struct pri *pri, char *s)
static void dahdi_pri_message (struct pri *pri, char *s)
static void dahdi_queue_frame (struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri)
static int16_t dahdi_r2_alaw_to_linear (uint8_t sample)
static int dahdi_r2_answer (struct dahdi_pvt *p)
static void dahdi_r2_disconnect_call (struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
static openr2_calling_party_category_t dahdi_r2_get_channel_category (struct ast_channel *c)
static uint8_t dahdi_r2_linear_to_alaw (int sample)
static void dahdi_r2_on_ani_digit_received (openr2_chan_t *r2chan, char digit)
static void dahdi_r2_on_billing_pulse_received (openr2_chan_t *r2chan)
static void dahdi_r2_on_call_accepted (openr2_chan_t *r2chan, openr2_call_mode_t mode)
static void dahdi_r2_on_call_answered (openr2_chan_t *r2chan)
static void dahdi_r2_on_call_disconnect (openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
static void dahdi_r2_on_call_end (openr2_chan_t *r2chan)
static void dahdi_r2_on_call_init (openr2_chan_t *r2chan)
static void dahdi_r2_on_call_offered (openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
static void dahdi_r2_on_call_read (openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
static void dahdi_r2_on_chan_log (openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
static void dahdi_r2_on_context_log (openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
static int dahdi_r2_on_dnis_digit_received (openr2_chan_t *r2chan, char digit)
static void dahdi_r2_on_hardware_alarm (openr2_chan_t *r2chan, int alarm)
static void dahdi_r2_on_line_blocked (openr2_chan_t *r2chan)
static void dahdi_r2_on_line_idle (openr2_chan_t *r2chan)
static void dahdi_r2_on_os_error (openr2_chan_t *r2chan, int errorcode)
static void dahdi_r2_on_protocol_error (openr2_chan_t *r2chan, openr2_protocol_error_t reason)
static void dahdi_r2_write_log (openr2_log_level_t level, char *logmessage)
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_send_keypad_facility_exec (struct ast_channel *chan, void *data)
static int dahdi_sendtext (struct ast_channel *c, const char *text)
static int dahdi_set_hook (int fd, int hs)
static int dahdi_setlaw (int dfd, int law)
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 char * dialplan2str (int dialplan)
static int digit_to_dtmfindex (char digit)
static void disable_dtmf_detect (struct dahdi_pvt *p)
static void * do_idle_thread (void *vchan)
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 struct dahdi_pvthandle_init_event (struct dahdi_pvt *i, int event)
static int handle_mfcr2_call_files (int fd, int argc, char *argv[])
static int handle_mfcr2_set_blocked (int fd, int argc, char *argv[])
static int handle_mfcr2_set_debug (int fd, int argc, char *argv[])
static int handle_mfcr2_set_idle (int fd, int argc, char *argv[])
static int handle_mfcr2_show_channels (int fd, int argc, char *argv[])
static int handle_mfcr2_show_variants (int fd, int argc, char *argv[])
static int handle_mfcr2_version (int fd, int argc, char *argv[])
static int handle_pri_debug (int fd, int argc, char *argv[])
static int handle_pri_no_debug (int fd, int argc, char *argv[])
static int handle_pri_really_debug (int fd, int argc, char *argv[])
static int handle_pri_set_debug_file (int fd, int argc, char **argv)
static int handle_pri_show_debug (int fd, int argc, char *argv[])
static int handle_pri_show_span (int fd, int argc, char *argv[])
static int handle_pri_show_spans (int fd, int argc, char *argv[])
static int handle_pri_version (int fd, int agc, char *argv[])
static int has_voicemail (struct dahdi_pvt *p)
static void init_mfcr2_globals (void)
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_mfcr2mfcr2_get_context (int id)
static void * mfcr2_monitor (void *data)
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 pri_active_dchan_fd (struct dahdi_pri *pri)
static int pri_assign_bearer (struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
static int pri_check_restart (struct dahdi_pri *pri)
static int pri_create_spanmap (int span, int trunkgroup, int logicalspan)
static int pri_create_trunkgroup (int trunkgroup, int *channels)
static void * pri_dchannel (void *vpri)
static struct dahdi_pvtpri_find_crv (struct dahdi_pri *pri, int crv)
static int pri_find_dchan (struct dahdi_pri *pri)
static int pri_find_empty_chan (struct dahdi_pri *pri, int backwards)
static int pri_find_principle (struct dahdi_pri *pri, int channel)
static int pri_fixup_principle (struct dahdi_pri *pri, int principle, q931_call *c)
static int pri_grab (struct dahdi_pvt *pvt, struct dahdi_pri *pri)
static int pri_hangup_all (struct dahdi_pvt *p, struct dahdi_pri *pri)
static int pri_is_up (struct dahdi_pri *pri)
static char * pri_order (int level)
static void pri_rel (struct dahdi_pri *pri)
static int pri_resolve_span (int *span, int channel, int offset, struct dahdi_spaninfo *si)
static int process_dahdi (struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
static char * redirectingreason2str (int redirectingreason)
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 send_keypad_facility_exec (struct ast_channel *chan, void *data)
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 int start_pri (struct dahdi_pri *pri)
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, struct dahdi_pri *pri)
static int zap_accept_r2_call_exec (struct ast_channel *chan, void *data)
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)
static int zap_send_keypad_facility_exec (struct ast_channel *chan, void *data)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "DAHDI Telephony w/PRI" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload, }
struct {
   int   alarm
   char *   name
alarms []
static const struct ast_module_infoast_module_info = &__mod_info
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 char * dahdi_accept_r2_call_app = "DAHDIAcceptR2Call"
static char * dahdi_accept_r2_call_descrip
static char * dahdi_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)"
static struct ast_cli_entry dahdi_cli []
static struct ast_cli_entry dahdi_mfcr2_cli []
static struct ast_cli_entry dahdi_pri_cli []
static const char dahdi_r2_callfiles_help []
static openr2_event_interface_t dahdi_r2_event_iface
static const char dahdi_r2_setblocked_help []
static const char dahdi_r2_setdebug_help []
static const char dahdi_r2_setidle_help []
static const char dahdi_r2_showchannels_help []
static openr2_transcoder_interface_t dahdi_r2_transcode_iface
static const char dahdi_r2_variants_help []
static const char dahdi_r2_version_help []
static char dahdi_restart_usage []
static char * dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility"
static char * dahdi_send_keypad_facility_descrip
static char * dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI"
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 int dtmfcid_level = 256
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 ast_mutex_t iflock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
 Protect the interface list (of dahdi_pvt's).
static struct ast_channel inuse
static int matchdigittimeout = 3000
 How long to wait for an extra digit, if there is an ambiguous match.
static int mfcr2_cur_accept_on_offer = 1
static int mfcr2_cur_allow_collect_calls = 0
static int mfcr2_cur_call_files = 0
static openr2_calling_party_category_t mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
static int mfcr2_cur_charge_calls = 1
static int mfcr2_cur_context_index = 0
static int mfcr2_cur_double_answer = 0
static int mfcr2_cur_forced_release = 0
static int mfcr2_cur_get_ani_first = -1
static int mfcr2_cur_immediate_accept = -1
static char mfcr2_cur_logdir [OR2_MAX_PATH]
static openr2_log_level_t mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING
static int mfcr2_cur_max_ani = 10
static int mfcr2_cur_max_dnis = 4
static int mfcr2_cur_metering_pulse_timeout = -1
static int mfcr2_cur_mfback_timeout = -1
static char mfcr2_cur_r2proto_file [OR2_MAX_PATH]
static int mfcr2_cur_skip_category = -1
static openr2_variant_t mfcr2_cur_variant = OR2_VAR_UNKNOWN
static pthread_t monitor_thread = AST_PTHREADT_NULL
 This is the thread for the monitor which checks for input on the channels which are not currently in use.
static ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
 Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
static int num_cadence = 4
static int num_restart_pending = 0
static int numbufs = 4
static const char pri_debug_help []
static const char pri_no_debug_help []
static const char pri_really_debug_help []
static const char pri_show_span_help []
static const char pri_show_spans_help []
static int pridebugfd = -1
static ast_mutex_t pridebugfdlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static char pridebugfilename [1024] = ""
static struct dahdi_pri pris [NUM_SPANS]
static char progzone [10] = ""
static struct dahdi_mfcr2 r2links [NUM_SPANS]
static ast_mutex_t restart_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static int ringt_base = DEFAULT_RINGT
 Configured ring timeout base.
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 ast_mutex_t ss_thread_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static char * subnames []
static const char tdesc []
static int user_has_defined_cadences = 0
static char * zap_accept_r2_call_app = "ZapAcceptR2Call"
static char * zap_accept_r2_call_descrip
static char * zap_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)"
static char * zap_send_keypad_facility_app = "ZapSendKeypadFacility"
static char * zap_send_keypad_facility_descrip
static char * zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI"
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 156 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 299 of file chan_dahdi.c.

Referenced by dahdi_callwait().

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

300 ms

Definition at line 298 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 1187 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 1188 of file chan_dahdi.c.

Referenced by dahdi_handle_event(), and dahdi_new().

#define CHAN_PSEUDO   -2

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

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

500 ms

Definition at line 300 of file chan_dahdi.c.

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 473 of file chan_dahdi.c.

#define CONF_USER_THIRDCALL   (1 << 1)

Definition at line 474 of file chan_dahdi.c.

#define DAHDI_EVENT_DTMFDOWN   0

Definition at line 126 of file chan_dahdi.c.

Referenced by dahdi_handle_event().

#define DAHDI_EVENT_DTMFUP   0

Definition at line 127 of file chan_dahdi.c.

Referenced by dahdi_handle_event().

#define DAHDI_OVERLAPDIAL_BOTH   (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)

Definition at line 212 of file chan_dahdi.c.

Referenced by process_dahdi(), and start_pri().

#define DAHDI_OVERLAPDIAL_INCOMING   2

Definition at line 211 of file chan_dahdi.c.

Referenced by dahdi_handle_event(), dahdi_read(), handle_pri_show_span(), and process_dahdi().

#define DAHDI_OVERLAPDIAL_NONE   0

Definition at line 209 of file chan_dahdi.c.

Referenced by process_dahdi().

#define DAHDI_OVERLAPDIAL_OUTGOING   1

Definition at line 210 of file chan_dahdi.c.

Referenced by dahdi_read(), process_dahdi(), and start_pri().

#define DAHDI_R2_LOCAL_BLOCK   (1 << 1)

Definition at line 1646 of file chan_dahdi.c.

Referenced by handle_mfcr2_set_blocked(), handle_mfcr2_set_idle(), mfcr2_monitor(), and mkintf().

#define DAHDI_R2_REMOTE_BLOCK   (1 << 0)

Definition at line 1645 of file chan_dahdi.c.

Referenced by dahdi_r2_on_line_blocked(), dahdi_r2_on_line_idle(), and mkintf().

#define DCHAN_AVAILABLE   (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)

Definition at line 206 of file chan_dahdi.c.

Referenced by pri_find_dchan(), and pri_is_up().

#define DCHAN_NOTINALARM   (1 << 1)

Definition at line 203 of file chan_dahdi.c.

Referenced by build_status(), and start_pri().

#define DCHAN_PROVISIONED   (1 << 0)

Definition at line 202 of file chan_dahdi.c.

Referenced by build_status(), pri_create_trunkgroup(), and pri_resolve_span().

#define DCHAN_UP   (1 << 2)

Definition at line 204 of file chan_dahdi.c.

#define DEFAULT_CIDRINGS   1

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

Definition at line 152 of file chan_dahdi.c.

Referenced by dahdi_chan_conf_default().

#define DEFAULT_PRI_DEBUG   0

Definition at line 413 of file chan_dahdi.c.

Referenced by start_pri().

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

8,000 ms

Definition at line 302 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 FORMAT   "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"

#define FORMAT   "%4s %40s\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)->bearer ? (p)->bearer->channel : p->channel)

Definition at line 1137 of file chan_dahdi.c.

#define HANGUP   1

Definition at line 12499 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 1184 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 12529 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 12530 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 13926 of file chan_dahdi.c.

Referenced by load_module().

#define local_astman_unregister (  ) 

Definition at line 12750 of file chan_dahdi.c.

Referenced by __unload_module().

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 295 of file chan_dahdi.c.

#define MASK_INUSE   (1 << 1)

Channel currently in use

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

Referenced by process_dahdi().

#define MAX_CHANNELS   672

No more than a DS3 per trunk group

Definition at line 198 of file chan_dahdi.c.

Referenced by mkintf().

#define MAX_SLAVES   4

Definition at line 476 of file chan_dahdi.c.

Referenced by isslavenative().

#define MIN_MS_SINCE_FLASH   ( (2000) )

2000 ms

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

Referenced by dahdi_new(), and ss_thread().

#define NUM_CADENCE_MAX   25

Definition at line 1162 of file chan_dahdi.c.

#define NUM_DCHANS   4

No more than 4 d-channels

Definition at line 197 of file chan_dahdi.c.

Referenced by dahdi_pri_error(), dahdi_pri_message(), mkintf(), pri_active_dchan_fd(), pri_create_trunkgroup(), pri_find_dchan(), and pri_is_up().

#define NUM_SPANS   32

Definition at line 196 of file chan_dahdi.c.

Referenced by __unload_module(), build_channels(), complete_span_helper(), dahdi_pri_error(), dahdi_pri_message(), dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), handle_pri_debug(), handle_pri_no_debug(), handle_pri_really_debug(), handle_pri_show_debug(), handle_pri_show_span(), handle_pri_show_spans(), init_mfcr2_globals(), load_module(), mkintf(), pri_create_trunkgroup(), pri_resolve_span(), setup_dahdi(), and unload_module().

#define POLARITY_IDLE   0

Definition at line 431 of file chan_dahdi.c.

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

#define POLARITY_REV   1

Definition at line 432 of file chan_dahdi.c.

Referenced by dahdi_handle_event(), and handle_init_event().

#define PRI_CHANNEL (  )     ((p) & 0xff)

Definition at line 354 of file chan_dahdi.c.

Referenced by pri_find_principle().

#define PRI_EXPLICIT (  )     (((p) >> 16) & 0x01)

Definition at line 356 of file chan_dahdi.c.

Referenced by pri_find_principle().

#define PRI_SPAN (  )     (((p) >> 8) & 0xff)

Definition at line 355 of file chan_dahdi.c.

Referenced by pri_find_principle().

#define PVT_TO_CHANNEL (  )     (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))

Definition at line 353 of file chan_dahdi.c.

Referenced by dahdi_call(), dahdi_indicate(), dahdi_write(), and pri_check_restart().

#define READ_SIZE   160

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

Definition at line 293 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 2166 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 175 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 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_EM_E1   DAHDI_SIG_EM_E1

Definition at line 192 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 171 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 174 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 172 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 173 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 176 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 177 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 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_FXOGS   DAHDI_SIG_FXOGS

Definition at line 183 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 184 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 182 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 180 of file chan_dahdi.c.

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

#define SIG_FXSKS   DAHDI_SIG_FXSKS

Definition at line 181 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(), do_monitor(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().

#define SIG_FXSLS   DAHDI_SIG_FXSLS

Definition at line 179 of file chan_dahdi.c.

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

#define SIG_GR303FXOKS   (0x0100000 | DAHDI_SIG_FXOKS)

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

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

#define SIG_MFCR2   DAHDI_SIG_CAS

Definition at line 186 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_sig2str(), do_monitor(), handle_mfcr2_call_files(), handle_mfcr2_set_blocked(), handle_mfcr2_set_debug(), handle_mfcr2_set_idle(), handle_mfcr2_show_channels(), mkintf(), and process_dahdi().

#define SIG_PRI   DAHDI_SIG_CLEAR

Definition at line 185 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 187 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 191 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 189 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 190 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 188 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 109 of file chan_dahdi.c.

Referenced by ss_thread().

#define SUB_CALLWAIT   1

Call-Waiting call on hold

Definition at line 427 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 426 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_r2_on_call_accepted(), dahdi_r2_on_call_answered(), dahdi_r2_on_call_disconnect(), dahdi_r2_on_call_offered(), 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(), pri_assign_bearer(), pri_fixup_principle(), reset_conf(), restore_conference(), restore_gains(), save_conference(), send_callerid(), and ss_thread().

#define SUB_THREEWAY   2

Three-way call

Definition at line 428 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 w/PRI"

Definition at line 14120 of file chan_dahdi.c.

#define TRAILER_MS   5

Referenced by dahdi_sendtext().

#define TRANSFER   0

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

References AST_FRAME_DTMF, ast_strlen_zero(), astman_get_header(), astman_send_error(), dahdi_pvt::channel, 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().

12629 {
12630    struct dahdi_pvt *p = NULL;
12631    const char *channel = local_astman_header(m, "Channel", zap_mode);
12632    const char *number = astman_get_header(m, "Number");
12633    int i;
12634 
12635    if (ast_strlen_zero(channel)) {
12636       astman_send_error(s, m, "No channel specified");
12637       return 0;
12638    }
12639    if (ast_strlen_zero(number)) {
12640       astman_send_error(s, m, "No number specified");
12641       return 0;
12642    }
12643    if (!(p = find_channel(atoi(channel)))) {
12644       astman_send_error(s, m, "No such channel");
12645       return 0;
12646    }
12647    if (!p->owner) {
12648       astman_send_error(s, m, "Channel does not have an owner");
12649       return 0;
12650    }
12651    for (i = 0; i < strlen(number); i++) {
12652       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
12653 
12654       dahdi_queue_frame(p, &f, NULL); 
12655    }
12656    local_astman_ack(s, m, "DialOffHook", zap_mode);
12657 
12658    return 0;
12659 }

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

Definition at line 12532 of file chan_dahdi.c.

References ast_strlen_zero(), astman_send_error(), dahdi_pvt::channel, 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().

12533 {
12534    struct dahdi_pvt *p = NULL;
12535    const char *channel = local_astman_header(m, "Channel", zap_mode);
12536 
12537    if (ast_strlen_zero(channel)) {
12538       astman_send_error(s, m, "No channel specified");
12539       return 0;
12540    }
12541    if (!(p = find_channel(atoi(channel)))) {
12542       astman_send_error(s, m, "No such channel");
12543       return 0;
12544    }
12545    p->dnd = dnd;
12546    local_astman_ack(s, m, "DND", zap_mode);
12547 
12548    return 0;
12549 }

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

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

12727 {
12728    if (dahdi_restart() != 0) {
12729       if (zap_mode) {
12730          astman_send_error(s, m, "Failed to restart Zap");
12731       } else {
12732          astman_send_error(s, m, "Failed to restart DAHDI");
12733       }
12734       return 1;
12735    }
12736    local_astman_ack(s, m, "Restart: Success", zap_mode);
12737    return 0;
12738 }

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

Definition at line 12671 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, iflock, local_astman_ack, dahdi_pvt::next, s, dahdi_pvt::sig, and sig2str.

Referenced by dahdi_action_showchannels(), and zap_action_showchannels().

12672 {
12673    struct dahdi_pvt *tmp = NULL;
12674    const char *id = astman_get_header(m, "ActionID");
12675    char idText[256] = "";
12676 
12677    local_astman_ack(s, m, " channel status will follow", zap_mode);
12678    if (!ast_strlen_zero(id))
12679       snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
12680 
12681    ast_mutex_lock(&iflock);
12682    
12683    tmp = iflist;
12684    while (tmp) {
12685       if (tmp->channel > 0) {
12686          int alarm = get_alarms(tmp);
12687          astman_append(s,
12688                   "Event: %sShowChannels\r\n"
12689                   "Channel: %d\r\n"
12690                   "Signalling: %s\r\n"
12691                   "Context: %s\r\n"
12692                   "DND: %s\r\n"
12693                   "Alarm: %s\r\n"
12694                   "%s"
12695                   "\r\n",
12696                   dahdi_chan_name,
12697                   tmp->channel, sig2str(tmp->sig), tmp->context, 
12698                   tmp->dnd ? "Enabled" : "Disabled",
12699                   alarm2str(alarm), idText);
12700       } 
12701 
12702       tmp = tmp->next;
12703    }
12704 
12705    ast_mutex_unlock(&iflock);
12706    
12707    astman_append(s, 
12708             "Event: %sShowChannelsComplete\r\n"
12709             "%s"
12710             "\r\n",
12711             dahdi_chan_name,
12712             idText);
12713    return 0;
12714 }

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

Definition at line 12571 of file chan_dahdi.c.

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

Referenced by dahdi_action_transfer(), and zap_action_transfer().

12572 {
12573    struct dahdi_pvt *p = NULL;
12574    const char *channel = local_astman_header(m, "Channel", zap_mode);
12575 
12576    if (ast_strlen_zero(channel)) {
12577       astman_send_error(s, m, "No channel specified");
12578       return 0;
12579    }
12580    if (!(p = find_channel(atoi(channel)))) {
12581       astman_send_error(s, m, "No such channel");
12582       return 0;
12583    }
12584    dahdi_fake_event(p,TRANSFER);
12585    local_astman_ack(s, m, "Transfer", zap_mode);
12586 
12587    return 0;
12588 }

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

Definition at line 12600 of file chan_dahdi.c.

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

Referenced by dahdi_action_transferhangup(), and zap_action_transferhangup().

12601 {
12602    struct dahdi_pvt *p = NULL;
12603    const char *channel = local_astman_header(m, "Channel", zap_mode);
12604 
12605    if (ast_strlen_zero(channel)) {
12606       astman_send_error(s, m, "No channel specified");
12607       return 0;
12608    }
12609    if (!(p = find_channel(atoi(channel)))) {
12610       astman_send_error(s, m, "No such channel");
12611       return 0;
12612    }
12613    dahdi_fake_event(p, HANGUP);
12614    local_astman_ack(s, m, "Hangup", zap_mode);
12615    return 0;
12616 }

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

Definition at line 5791 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_tv(), 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, ast_channel::name, 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().

05792 {
05793    struct dahdi_pvt *p = ast->tech_pvt;
05794    int res;
05795    int usedindex=-1;
05796    int index;
05797    struct ast_frame *f;
05798 
05799 
05800    index = dahdi_get_index(ast, p, 1);
05801    
05802    p->subs[index].f.frametype = AST_FRAME_NULL;
05803    p->subs[index].f.datalen = 0;
05804    p->subs[index].f.samples = 0;
05805    p->subs[index].f.mallocd = 0;
05806    p->subs[index].f.offset = 0;
05807    p->subs[index].f.subclass = 0;
05808    p->subs[index].f.delivery = ast_tv(0,0);
05809    p->subs[index].f.src = "dahdi_exception";
05810    p->subs[index].f.data = NULL;
05811    
05812    
05813    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
05814       /* If nobody owns us, absorb the event appropriately, otherwise
05815          we loop indefinitely.  This occurs when, during call waiting, the
05816          other end hangs up our channel so that it no longer exists, but we
05817          have neither FLASH'd nor ONHOOK'd to signify our desire to
05818          change to the other channel. */
05819       if (p->fake_event) {
05820          res = p->fake_event;
05821          p->fake_event = 0;
05822       } else
05823          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
05824       /* Switch to real if there is one and this isn't something really silly... */
05825       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
05826          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
05827          ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
05828          p->owner = p->subs[SUB_REAL].owner;
05829          if (p->owner && ast_bridged_channel(p->owner))
05830             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05831          p->subs[SUB_REAL].needunhold = 1;
05832       }
05833       switch (res) {
05834       case DAHDI_EVENT_ONHOOK:
05835          dahdi_disable_ec(p);
05836          if (p->owner) {
05837             if (option_verbose > 2) 
05838                ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
05839             dahdi_ring_phone(p);
05840             p->callwaitingrepeat = 0;
05841             p->cidcwexpire = 0;
05842          } else
05843             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05844          update_conf(p);
05845          break;
05846       case DAHDI_EVENT_RINGOFFHOOK:
05847          dahdi_enable_ec(p);
05848          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05849          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
05850             p->subs[SUB_REAL].needanswer = 1;
05851             p->dialing = 0;
05852          }
05853          break;
05854       case DAHDI_EVENT_HOOKCOMPLETE:
05855       case DAHDI_EVENT_RINGERON:
05856       case DAHDI_EVENT_RINGEROFF:
05857          /* Do nothing */
05858          break;
05859       case DAHDI_EVENT_WINKFLASH:
05860          gettimeofday(&p->flashtime, NULL);
05861          if (p->owner) {
05862             if (option_verbose > 2) 
05863                ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
05864             if (p->owner->_state != AST_STATE_UP) {
05865                /* Answer if necessary */
05866                usedindex = dahdi_get_index(p->owner, p, 0);
05867                if (usedindex > -1) {
05868                   p->subs[usedindex].needanswer = 1;
05869                }
05870                ast_setstate(p->owner, AST_STATE_UP);
05871             }
05872             p->callwaitingrepeat = 0;
05873             p->cidcwexpire = 0;
05874             if (ast_bridged_channel(p->owner))
05875                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05876             p->subs[SUB_REAL].needunhold = 1;
05877          } else
05878             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05879          update_conf(p);
05880          break;
05881       default:
05882          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
05883       }
05884       f = &p->subs[index].f;
05885       return f;
05886    }
05887    if (!(p->radio || (p->oprmode < 0)) && option_debug) 
05888       ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
05889    /* If it's not us, return NULL immediately */
05890    if (ast != p->owner) {
05891       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
05892       f = &p->subs[index].f;
05893       return f;
05894    }
05895    f = dahdi_handle_event(ast);
05896    return f;
05897 }

static void __reg_module ( void   )  [static]

Definition at line 14129 of file chan_dahdi.c.

static int __unload_module ( void   )  [static]

Definition at line 12757 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, dahdi_close_pri_fd(), dahdi_mfcr2_cli, dahdi_pri_cli, destroy_all_channels(), iflist, iflock, local_astman_unregister, master, monlock, dahdi_pvt::next, NUM_SPANS, dahdi_pvt::owner, pris, and r2links.

Referenced by load_module(), and unload_module().

12758 {
12759    struct dahdi_pvt *p;
12760 #ifdef HAVE_OPENR2
12761    int r;
12762 #endif
12763 #ifdef HAVE_PRI
12764    int i, j;
12765    for (i = 0; i < NUM_SPANS; i++) {
12766       if (pris[i].master != AST_PTHREADT_NULL) 
12767          pthread_cancel(pris[i].master);
12768    }
12769    ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
12770 
12771    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12772       ast_unregister_application(dahdi_send_keypad_facility_app);
12773    }
12774    ast_unregister_application(zap_send_keypad_facility_app);
12775 #endif
12776 #ifdef HAVE_OPENR2
12777    for (r = 0; r < NUM_SPANS; r++) {
12778       if (r2links[r].master != AST_PTHREADT_NULL) {
12779          pthread_cancel(r2links[r].master);
12780          pthread_join(r2links[r].master, NULL);
12781       }
12782    }
12783    ast_cli_unregister_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli) / sizeof(dahdi_mfcr2_cli[0]));
12784    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12785       ast_unregister_application(dahdi_accept_r2_call_app);
12786    }
12787    ast_unregister_application(zap_accept_r2_call_app);
12788 #endif
12789    ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
12790    local_astman_unregister("DialOffHook");
12791    local_astman_unregister("Hangup");
12792    local_astman_unregister("Transfer");
12793    local_astman_unregister("DNDoff");
12794    local_astman_unregister("DNDon");
12795    local_astman_unregister("ShowChannels");
12796    local_astman_unregister("Restart");
12797    ast_channel_unregister(chan_tech);
12798    ast_mutex_lock(&iflock);
12799    /* Hangup all interfaces if they have an owner */
12800    p = iflist;
12801    while (p) {
12802       if (p->owner)
12803          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
12804       p = p->next;
12805    }
12806    ast_mutex_unlock(&iflock);
12807    ast_mutex_lock(&monlock);
12808    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12809       pthread_cancel(monitor_thread);
12810       pthread_kill(monitor_thread, SIGURG);
12811       pthread_join(monitor_thread, NULL);
12812    }
12813    monitor_thread = AST_PTHREADT_STOP;
12814    ast_mutex_unlock(&monlock);
12815 
12816    destroy_all_channels();
12817 #ifdef HAVE_PRI      
12818    for (i = 0; i < NUM_SPANS; i++) {
12819       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
12820          pthread_join(pris[i].master, NULL);
12821       for (j = 0; j < NUM_DCHANS; j++) {
12822          dahdi_close_pri_fd(&(pris[i]), j);
12823       }
12824    }
12825 #endif
12826 #ifdef HAVE_OPENR2
12827    for (r = 0; r < NUM_SPANS; r++) {
12828       if (r2links[r].protocol_context) {
12829          openr2_context_delete(r2links[r].protocol_context);
12830       }
12831    }
12832 #endif
12833    ast_cond_destroy(&ss_thread_complete);
12834    return 0;
12835 }

static void __unreg_module ( void   )  [static]

Definition at line 14129 of file chan_dahdi.c.

static char* alarm2str ( int  alarm  )  [static]

Definition at line 2075 of file chan_dahdi.c.

References alarms, and name.

Referenced by __action_showchannels(), and handle_alarms().

02076 {
02077    int x;
02078    for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
02079       if (alarms[x].alarm & alarm)
02080          return alarms[x].name;
02081    }
02082    return alarm ? "Unknown Alarm" : "No Alarm";
02083 }

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

Definition at line 1877 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_FILE_PSEUDO, 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().

01878 {
01879    struct dahdi_bufferinfo bi;
01880    int res;
01881    if (p->subs[x].dfd < 0) {
01882       p->subs[x].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
01883       if (p->subs[x].dfd > -1) {
01884          res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
01885          if (!res) {
01886             bi.txbufpolicy = p->buf_policy;
01887             bi.rxbufpolicy = p->buf_policy;
01888             bi.numbufs = p->buf_no;
01889             res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01890             if (res < 0) {
01891                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01892             }
01893          } else 
01894             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01895          if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01896             ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01897             dahdi_close_sub(p, x);
01898             return -1;
01899          }
01900          if (option_debug)
01901             ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01902          return 0;
01903       } else
01904          ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01905       return -1;
01906    }
01907    ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01908    return -1;
01909 }

static void apply_plan_to_number ( char *  buf,
size_t  size,
const struct dahdi_pri pri,
const char *  number,
const int  plan 
) [static]

Definition at line 10002 of file chan_dahdi.c.

References ast_strlen_zero(), dahdi_pri::internationalprefix, dahdi_pri::localprefix, dahdi_pri::nationalprefix, dahdi_pri::privateprefix, and dahdi_pri::unknownprefix.

10003 {
10004    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
10005       if (size) {
10006          *buf = '\0';
10007       }
10008       return;
10009    }
10010 
10011    switch (plan) {
10012    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
10013       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
10014       break;
10015    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
10016       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
10017       break;
10018    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
10019       snprintf(buf, size, "%s%s", pri->localprefix, number);
10020       break;
10021    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
10022       snprintf(buf, size, "%s%s", pri->privateprefix, number);
10023       break;
10024    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
10025       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
10026       break;
10027    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
10028       snprintf(buf, size, "%s", number);
10029       break;
10030    }
10031 }

static int attempt_transfer ( struct dahdi_pvt p  )  [static]

Definition at line 4718 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, ast_channel::name, 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().

04719 {
04720    /* In order to transfer, we need at least one of the channels to
04721       actually be in a call bridge.  We can't conference two applications
04722       together (but then, why would we want to?) */
04723    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04724       /* The three-way person we're about to transfer to could still be in MOH, so
04725          stop if now if appropriate */
04726       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
04727          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
04728       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
04729          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
04730       }
04731       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
04732          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04733       }
04734        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
04735          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04736                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
04737          return -1;
04738       }
04739       /* Orphan the channel after releasing the lock */
04740       ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04741       unalloc_sub(p, SUB_THREEWAY);
04742    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04743       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04744       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
04745          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
04746       }
04747       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
04748          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04749       }
04750       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
04751          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04752                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
04753          return -1;
04754       }
04755       /* Three-way is now the REAL */
04756       swap_subs(p, SUB_THREEWAY, SUB_REAL);
04757       ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
04758       unalloc_sub(p, SUB_THREEWAY);
04759       /* Tell the caller not to hangup */
04760       return 1;
04761    } else {
04762       ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
04763                p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
04764       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04765       return -1;
04766    }
04767    return 0;
04768 }

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

Definition at line 9151 of file chan_dahdi.c.

References ast_channel::_state, ast_log(), AST_STATE_RINGING, AST_STATE_UP, dahdi_pvt::call, dahdi_pvt::callwaiting, dahdi_pvt::channel, dahdi_pvt::dnd, errno, dahdi_pvt::group, dahdi_pvt::guardtime, LOG_DEBUG, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2block, dahdi_pvt::mfcr2call, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::radio, dahdi_pvt::resetting, 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 __ast_string_field_index_build_va(), and dahdi_request().

09152 {
09153    int res;
09154    struct dahdi_params par;
09155 
09156    /* First, check group matching */
09157    if (groupmatch) {
09158       if ((p->group & groupmatch) != groupmatch)
09159          return 0;
09160       *groupmatched = 1;
09161    }
09162    /* Check to see if we have a channel match */
09163    if (channelmatch != -1) {
09164       if (p->channel != channelmatch)
09165          return 0;
09166       *channelmatched = 1;
09167    }
09168    /* We're at least busy at this point */
09169    if (busy) {
09170       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
09171          *busy = 1;
09172    }
09173    /* If do not disturb, definitely not */
09174    if (p->dnd)
09175       return 0;
09176    /* If guard time, definitely not */
09177    if (p->guardtime && (time(NULL) < p->guardtime)) 
09178       return 0;
09179       
09180    /* If no owner definitely available */
09181    if (!p->owner) {
09182 #ifdef HAVE_PRI
09183       /* Trust PRI */
09184       if (p->pri) {
09185          if (p->resetting || p->call)
09186             return 0;
09187          else
09188             return 1;
09189       }
09190 #endif
09191 #ifdef HAVE_OPENR2
09192       /* Trust MFC/R2 */
09193       if (p->mfcr2) {
09194          if (p->mfcr2call || p->mfcr2block)
09195             return 0;
09196          else
09197             return 1;
09198       }
09199 #endif
09200       if (!(p->radio || (p->oprmode < 0)))
09201       {
09202          if (!p->sig || (p->sig == SIG_FXSLS))
09203             return 1;
09204          /* Check hook state */
09205          if (p->subs[SUB_REAL].dfd > -1) {
09206             memset(&par, 0, sizeof(par));
09207             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
09208          } else {
09209             /* Assume not off hook on CVRS */
09210             res = 0;
09211             par.rxisoffhook = 0;
09212          }
09213          if (res) {
09214             ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
09215          } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
09216             /* When "onhook" that means no battery on the line, and thus
09217               it is out of service..., if it's on a TDM card... If it's a channel
09218               bank, there is no telling... */
09219             if (par.rxbits > -1)
09220                return 1;
09221             if (par.rxisoffhook)
09222                return 1;
09223             else
09224 #ifdef DAHDI_CHECK_HOOKSTATE
09225                return 0;
09226 #else
09227                return 1;
09228 #endif
09229          } else if (par.rxisoffhook) {
09230             ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
09231             /* Not available when the other end is off hook */
09232             return 0;
09233          }
09234       }
09235       return 1;
09236    }
09237 
09238    /* If it's not an FXO, forget about call wait */
09239    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 
09240       return 0;
09241 
09242    if (!p->callwaiting) {
09243       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
09244       return 0;
09245    }
09246 
09247    if (p->subs[SUB_CALLWAIT].dfd > -1) {
09248       /* If there is already a call waiting call, then we can't take a second one */
09249       return 0;
09250    }
09251    
09252    if ((p->owner->_state != AST_STATE_UP) &&
09253        ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
09254       /* If the current call is not up, then don't allow the call */
09255       return 0;
09256    }
09257    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
09258       /* Can't take a call wait when the three way calling hasn't been merged yet. */
09259       return 0;
09260    }
09261    /* We're cool */
09262    return 1;
09263 }

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

References ast_log(), ast_strdupa, ast_verbose(), dahdi_chan_conf::chan, CHAN_PSEUDO, HAVE_PRI, LOG_ERROR, mkintf(), NUM_SPANS, option_verbose, dahdi_pri::pri, pris, r2links, dahdi_pvt::sig, sig2str, dahdi_pri::trunkgroup, and VERBOSE_PREFIX_3.

Referenced by process_dahdi().

12848 {
12849    char *c, *chan;
12850    int x, start, finish;
12851    struct dahdi_pvt *tmp;
12852 #ifdef HAVE_PRI
12853    struct dahdi_pri *pri;
12854    int trunkgroup, y;
12855 #endif
12856    
12857    if ((reload == 0) && (conf->chan.sig < 0)) {
12858       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
12859       return -1;
12860    }
12861 
12862    c = ast_strdupa(value);
12863 
12864 #ifdef HAVE_PRI
12865    pri = NULL;
12866    if (iscrv) {
12867       if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
12868          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
12869          return -1;
12870       }
12871       if (trunkgroup < 1) {
12872          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
12873          return -1;
12874       }
12875       c += y;
12876       for (y = 0; y < NUM_SPANS; y++) {
12877          if (pris[y].trunkgroup == trunkgroup) {
12878             pri = pris + y;
12879             break;
12880          }
12881       }
12882       if (!pri) {
12883          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
12884          return -1;
12885       }
12886    }
12887 #endif         
12888 
12889    while ((chan = strsep(&c, ","))) {
12890       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
12891          /* Range */
12892       } else if (sscanf(chan, "%30d", &start)) {
12893          /* Just one */
12894          finish = start;
12895       } else if (!strcasecmp(chan, "pseudo")) {
12896          finish = start = CHAN_PSEUDO;
12897          if (found_pseudo)
12898             *found_pseudo = 1;
12899       } else {
12900          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
12901          return -1;
12902       }
12903       if (finish < start) {
12904          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
12905          x = finish;
12906          finish = start;
12907          start = x;
12908       }
12909 
12910       for (x = start; x <= finish; x++) {
12911 #ifdef HAVE_PRI
12912          tmp = mkintf(x, conf, pri, reload);
12913 #else       
12914          tmp = mkintf(x, conf, NULL, reload);
12915 #endif         
12916 
12917          if (tmp) {
12918             if (option_verbose > 2) {
12919 #ifdef HAVE_PRI
12920                if (pri)
12921                   ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
12922                else
12923 #endif
12924                   ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
12925             }
12926          } else {
12927             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
12928                (reload == 1) ? "reconfigure" : "register", value);
12929             return -1;
12930          }
12931       }
12932 #ifdef HAVE_OPENR2
12933       if (reload != 1 && r2links[mfcr2_cur_context_index].protocol_context) {
12934          mfcr2_cur_context_index++;
12935       }  
12936 #endif
12937    }
12938 
12939    return 0;
12940 }

static void build_status ( char *  s,
size_t  len,
int  status,
int  active 
) [static]

Definition at line 11417 of file chan_dahdi.c.

References DCHAN_NOTINALARM, and DCHAN_PROVISIONED.

Referenced by handle_pri_show_span(), and handle_pri_show_spans().

11418 {
11419    if (!s || len < 1) {
11420       return;
11421    }
11422    s[0] = '\0';
11423    if (status & DCHAN_PROVISIONED)
11424       strncat(s, "Provisioned, ", len - strlen(s) - 1);
11425    if (!(status & DCHAN_NOTINALARM))
11426       strncat(s, "In Alarm, ", len - strlen(s) - 1);
11427    if (status & DCHAN_UP)
11428       strncat(s, "Up", len - strlen(s) - 1);
11429    else
11430       strncat(s, "Down", len - strlen(s) - 1);
11431    if (active)
11432       strncat(s, ", Active", len - strlen(s) - 1);
11433    else
11434       strncat(s, ", Standby", len - strlen(s) - 1);
11435    s[len - 1] = '\0';
11436 }

static int bump_gains ( struct dahdi_pvt p  )  [static]

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

02527 {
02528    int res;
02529 
02530    /* Bump receive gain by 5.0db */
02531    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
02532    if (res) {
02533       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02534       return -1;
02535    }
02536 
02537    return 0;
02538 }

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

Definition at line 7917 of file chan_dahdi.c.

References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.

07918 {
07919    int x;
07920    int sum = 0;
07921 
07922    if (!len)
07923       return 0;
07924 
07925    for (x = 0; x < len; x++)
07926       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
07927 
07928    return sum / len;
07929 }

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

Definition at line 9265 of file chan_dahdi.c.

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

Referenced by dahdi_request().

09266 {
09267    struct dahdi_pvt *p;
09268    struct dahdi_bufferinfo bi;
09269    int res;
09270    
09271    if ((p = ast_malloc(sizeof(*p)))) {
09272       memcpy(p, src, sizeof(struct dahdi_pvt));
09273       ast_mutex_init(&p->lock);
09274       p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
09275       /* Allocate a DAHDI structure */
09276       if (p->subs[SUB_REAL].dfd < 0) {
09277          ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
09278          destroy_dahdi_pvt(&p);
09279          return NULL;
09280       }
09281       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09282       if (!res) {
09283          bi.txbufpolicy = p->buf_policy;
09284          bi.rxbufpolicy = p->buf_policy;
09285          bi.numbufs = p->buf_no;
09286          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09287          if (res < 0) {
09288             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09289          }
09290       } else
09291          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09292    }
09293    p->destroy = 1;
09294    p->next = iflist;
09295    p->prev = NULL;
09296    iflist = p;
09297    if (iflist->next)
09298       iflist->next->prev = p;
09299    return p;
09300 }

static int check_for_conference ( struct dahdi_pvt p  )  [static]

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

04771 {
04772    struct dahdi_confinfo ci;
04773    /* Fine if we already have a master, etc */
04774    if (p->master || (p->confno > -1))
04775       return 0;
04776    memset(&ci, 0, sizeof(ci));
04777    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
04778       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
04779       return 0;
04780    }
04781    /* If we have no master and don't have a confno, then 
04782       if we're in a conference, it's probably a MeetMe room or
04783       some such, so don't let us 3-way out! */
04784    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
04785       if (option_verbose > 2) 
04786          ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
04787       return 1;
04788    }
04789    return 0;
04790 }

static char* complete_span_4 ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 11284 of file chan_dahdi.c.

References complete_span_helper().

11285 {
11286    return complete_span_helper(line,word,pos,state,3);
11287 }

static char* complete_span_5 ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 11289 of file chan_dahdi.c.

References complete_span_helper().

11290 {
11291    return complete_span_helper(line,word,pos,state,4);
11292 }

static char* complete_span_helper ( const char *  line,
const char *  word,
int  pos,
int  state,
int  rpos 
) [static]

Definition at line 11265 of file chan_dahdi.c.

References asprintf, ast_log(), errno, NUM_SPANS, and pris.

Referenced by complete_span_4(), and complete_span_5().

11266 {
11267    int which, span;
11268    char *ret = NULL;
11269 
11270    if (pos != rpos)
11271       return ret;
11272 
11273    for (which = span = 0; span < NUM_SPANS; span++) {
11274       if (pris[span].pri && ++which > state) {
11275          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
11276             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
11277          }
11278          break;
11279       }
11280    }
11281    return ret;
11282 }

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

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

02169 {
02170    /* If the conference already exists, and we're already in it
02171       don't bother doing anything */
02172    struct dahdi_confinfo zi;
02173    
02174    memset(&zi, 0, sizeof(zi));
02175    zi.chan = 0;
02176 
02177    if (slavechannel > 0) {
02178       /* If we have only one slave, do a digital mon */
02179       zi.confmode = DAHDI_CONF_DIGITALMON;
02180       zi.confno = slavechannel;
02181    } else {
02182       if (!index) {
02183          /* Real-side and pseudo-side both participate in conference */
02184          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
02185             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
02186       } else
02187          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
02188       zi.confno = p->confno;
02189    }
02190    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
02191       return 0;
02192    if (c->dfd < 0)
02193       return 0;
02194    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02195       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
02196       return -1;
02197    }
02198    if (slavechannel < 1) {
02199       p->confno = zi.confno;
02200    }
02201    memcpy(&c->curconf, &zi, sizeof(c->curconf));
02202    ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02203    return 0;
02204 }

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

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

02218 {
02219    struct dahdi_confinfo zi;
02220    if (/* Can't delete if there's no dfd */
02221       (c->dfd < 0) ||
02222       /* Don't delete from the conference if it's not our conference */
02223       !isourconf(p, c)
02224       /* Don't delete if we don't think it's conferenced at all (implied) */
02225       ) return 0;
02226    memset(&zi, 0, sizeof(zi));
02227    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02228       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
02229       return -1;
02230    }
02231    ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02232    memcpy(&c->curconf, &zi, sizeof(c->curconf));
02233    return 0;
02234 }

static int dahdi_accept_r2_call_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 3445 of file chan_dahdi.c.

References AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), ast_strlen_zero(), dahdi_tech, f, LOG_DEBUG, parse(), and ast_channel::tech.

Referenced by load_module(), and zap_accept_r2_call_exec().

03446 {
03447    /* data is whether to accept with charge or no charge */
03448    openr2_call_mode_t accept_mode;
03449    int res, timeout, maxloops;
03450    struct ast_frame *f;
03451    struct dahdi_pvt *p;
03452    char *parse;
03453    AST_DECLARE_APP_ARGS(args,
03454          AST_APP_ARG(charge);
03455    );
03456 
03457    if (ast_strlen_zero(data)) {
03458       ast_log(LOG_DEBUG, "No data sent to application!\n");
03459       return -1;
03460    }
03461 
03462    if (chan->tech != &dahdi_tech) {
03463       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
03464       return -1;
03465    }
03466 
03467    p = (struct dahdi_pvt *)chan->tech_pvt;
03468    if (!p) {
03469       ast_log(LOG_DEBUG, "Unable to find technology private!\n");
03470       return -1;
03471    }
03472 
03473    parse = ast_strdupa(data);
03474    AST_STANDARD_APP_ARGS(args, parse);
03475 
03476    if (ast_strlen_zero(args.charge)) {
03477       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
03478       return -1;
03479    }
03480 
03481    ast_mutex_lock(&p->lock);
03482    if (!p->mfcr2 || !p->mfcr2call) {
03483       ast_mutex_unlock(&p->lock);
03484       ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
03485       return -1;
03486    }
03487 
03488    if (p->mfcr2_call_accepted) {
03489       ast_mutex_unlock(&p->lock);
03490       ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
03491       return 0;
03492    }
03493    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
03494    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
03495       ast_mutex_unlock(&p->lock);
03496       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
03497       return -1;
03498    }
03499    ast_mutex_unlock(&p->lock);
03500 
03501    res = 0;
03502    timeout = 100;
03503    maxloops = 50; /* wait up to 5 seconds */
03504    /* we need to read() until the call is accepted */
03505    while (maxloops > 0) {
03506       maxloops--;
03507       if (ast_check_hangup(chan)) {
03508          break;
03509       }
03510       res = ast_waitfor(chan, timeout);
03511       if (res < 0) {
03512          ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
03513          res = -1;
03514          break;
03515       }
03516       if (res == 0) {
03517          continue;
03518       }
03519       f = ast_read(chan);
03520       if (!f) {
03521          ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
03522          res = -1;
03523          break;
03524       }
03525       if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
03526          ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
03527          ast_frfree(f);
03528          res = -1;
03529          break;
03530       }
03531       ast_frfree(f);
03532       ast_mutex_lock(&p->lock);
03533       if (p->mfcr2_call_accepted) {
03534          ast_mutex_unlock(&p->lock);
03535          ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
03536          break;
03537       }
03538       ast_mutex_unlock(&p->lock);
03539    }
03540    if (res == -1) {
03541       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
03542    }
03543    return res;
03544 }

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

Definition at line 12666 of file chan_dahdi.c.

References __action_dialoffhook(), and s.

12667 {
12668    return __action_dialoffhook(s, m, 0);
12669 }

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

Definition at line 12566 of file chan_dahdi.c.

References __action_dnd(), and s.

12567 {
12568    return __action_dnd(s, m, 0, 0);
12569 }

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

Definition at line 12556 of file chan_dahdi.c.

References __action_dnd(), and s.

12557 {
12558    return __action_dnd(s, m, 0, 1);
12559 }

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

Definition at line 12745 of file chan_dahdi.c.

References __action_restart(), and s.

12746 {
12747    return __action_restart(s, m, 0);
12748 }

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

Definition at line 12721 of file chan_dahdi.c.

References __action_showchannels(), and s.

12722 {
12723    return __action_showchannels(s, m, 0);
12724 }

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

Definition at line 12595 of file chan_dahdi.c.

References __action_transfer(), and s.

12596 {
12597    return __action_transfer(s, m, 0);
12598 }

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

Definition at line 12623 of file chan_dahdi.c.

References __action_transferhangup(), and s.

12624 {
12625    return __action_transferhangup(s, m, 0);
12626 }

static int dahdi_answer ( struct ast_channel ast  )  [static]

Definition at line 3946 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::call, dahdi_pvt::channel, dahdi_enable_ec(), dahdi_get_index(), dahdi_r2_answer(), 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::mfcr2_accept_on_offer, dahdi_pvt::mfcr2_charge_calls, ast_channel::name, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::polaritydelaytv, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, dahdi_pvt::r2chan, 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_MFCR2, 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.

03947 {
03948    struct dahdi_pvt *p = ast->tech_pvt;
03949    int res = 0;
03950    int index;
03951    int oldstate = ast->_state;
03952    ast_setstate(ast, AST_STATE_UP);
03953    ast_mutex_lock(&p->lock);
03954    index = dahdi_get_index(ast, p, 0);
03955    if (index < 0)
03956       index = SUB_REAL;
03957    /* nothing to do if a radio channel */
03958    if ((p->radio || (p->oprmode < 0))) {
03959       ast_mutex_unlock(&p->lock);
03960       return 0;
03961    }
03962    switch (p->sig) {
03963    case SIG_FXSLS:
03964    case SIG_FXSGS:
03965    case SIG_FXSKS:
03966       p->ringt = 0;
03967       /* Fall through */
03968    case SIG_EM:
03969    case SIG_EM_E1:
03970    case SIG_EMWINK:
03971    case SIG_FEATD:
03972    case SIG_FEATDMF:
03973    case SIG_FEATDMF_TA:
03974    case SIG_E911:
03975    case SIG_FGC_CAMA:
03976    case SIG_FGC_CAMAMF:
03977    case SIG_FEATB:
03978    case SIG_SF:
03979    case SIG_SFWINK:
03980    case SIG_SF_FEATD:
03981    case SIG_SF_FEATDMF:
03982    case SIG_SF_FEATB:
03983    case SIG_FXOLS:
03984    case SIG_FXOGS:
03985    case SIG_FXOKS:
03986       /* Pick up the line */
03987       ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
03988       if (p->hanguponpolarityswitch) {
03989          gettimeofday(&p->polaritydelaytv, NULL);
03990       }
03991       res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03992       tone_zone_play_tone(p->subs[index].dfd, -1);
03993       p->dialing = 0;
03994       if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
03995          if (oldstate == AST_STATE_RINGING) {
03996             ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
03997             tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
03998             swap_subs(p, SUB_THREEWAY, SUB_REAL);
03999             p->owner = p->subs[SUB_REAL].owner;
04000          }
04001       }
04002       if (p->sig & __DAHDI_SIG_FXS) {
04003          dahdi_enable_ec(p);
04004          dahdi_train_ec(p);
04005       }
04006       break;
04007 #ifdef HAVE_PRI
04008    case SIG_PRI:
04009       /* Send a pri acknowledge */
04010       if (!pri_grab(p, p->pri)) {
04011          p->proceeding = 1;
04012          p->dialing = 0;
04013          res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
04014          pri_rel(p->pri);
04015       } else {
04016          ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04017          res = -1;
04018       }
04019       break;
04020 #endif
04021 #ifdef HAVE_OPENR2
04022    case SIG_MFCR2:
04023       if (!p->mfcr2_accept_on_offer) {
04024          /* the call was not accepted on offer, so it must be accepted now before answering,
04025             the answer will be executed when the callback on_call_accepted is executed */
04026          if (p->mfcr2_charge_calls) {
04027             ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with charge on chan %d\n", p->channel);
04028             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
04029          } else {
04030             ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with no charge on chan %d\n", p->channel);
04031             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
04032          }
04033       } else {
04034          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
04035          res = dahdi_r2_answer(p);
04036       }
04037       break;
04038 #endif
04039    case 0:
04040       ast_mutex_unlock(&p->lock);
04041       return 0;
04042    default:
04043       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
04044       res = -1;
04045    }
04046    ast_mutex_unlock(&p->lock);
04047    return res;
04048 }

static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause ( int  cause  )  [static]

Definition at line 3551 of file chan_dahdi.c.

References AST_CAUSE_CALL_REJECTED, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_INTERWORKING, AST_CAUSE_NETWORK_OUT_OF_ORDER, AST_CAUSE_NO_ANSWER, AST_CAUSE_NO_USER_RESPONSE, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_UNALLOCATED, AST_CAUSE_USER_BUSY, ast_log(), and LOG_DEBUG.

Referenced by dahdi_hangup().

03552 {
03553    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
03554    switch (cause) {
03555    case AST_CAUSE_USER_BUSY:
03556    case AST_CAUSE_CALL_REJECTED:
03557    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
03558       r2cause = OR2_CAUSE_BUSY_NUMBER;
03559       break;
03560 
03561    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
03562    case AST_CAUSE_SWITCH_CONGESTION:
03563       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
03564       break;
03565 
03566    case AST_CAUSE_UNALLOCATED:
03567       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
03568       break;
03569 
03570    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
03571    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
03572       r2cause = OR2_CAUSE_OUT_OF_ORDER;
03573       break;
03574 
03575    case AST_CAUSE_NO_ANSWER:
03576    case AST_CAUSE_NO_USER_RESPONSE:
03577       r2cause = OR2_CAUSE_NO_ANSWER;
03578       break;
03579 
03580    default:
03581       r2cause = OR2_CAUSE_NORMAL_CLEARING;
03582       break;
03583    }
03584    ast_log(LOG_DEBUG, "dahdi_ast_cause_to_r2_cause returned %d/%s for ast cause %d\n", 
03585          r2cause, openr2_proto_get_disconnect_string(r2cause), cause);
03586    return r2cause;
03587 }

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 4373 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::call, 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, ast_channel::name, 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.

04374 {
04375    struct ast_channel *who;
04376    struct dahdi_pvt *p0, *p1, *op0, *op1;
04377    struct dahdi_pvt *master = NULL, *slave = NULL;
04378    struct ast_frame *f;
04379    int inconf = 0;
04380    int nothingok = 1;
04381    int ofd0, ofd1;
04382    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
04383    int os0 = -1, os1 = -1;
04384    int priority = 0;
04385    struct ast_channel *oc0, *oc1;
04386    enum ast_bridge_result res;
04387 
04388 #ifdef PRI_2BCT
04389    int triedtopribridge = 0;
04390    q931_call *q931c0 = NULL, *q931c1 = NULL;
04391 #endif
04392 
04393    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
04394       There is code below to handle it properly until DTMF is actually seen,
04395       but due to currently unresolved issues it's ignored...
04396    */
04397 
04398    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
04399       return AST_BRIDGE_FAILED_NOWARN;
04400 
04401    ast_mutex_lock(&c0->lock);
04402    while (ast_mutex_trylock(&c1->lock)) {
04403       DEADLOCK_AVOIDANCE(&c0->lock);
04404    }
04405 
04406    p0 = c0->tech_pvt;
04407    p1 = c1->tech_pvt;
04408    /* cant do pseudo-channels here */
04409    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
04410       ast_mutex_unlock(&c0->lock);
04411       ast_mutex_unlock(&c1->lock);
04412       return AST_BRIDGE_FAILED_NOWARN;
04413    }
04414 
04415    oi0 = dahdi_get_index(c0, p0, 0);
04416    oi1 = dahdi_get_index(c1, p1, 0);
04417    if ((oi0 < 0) || (oi1 < 0)) {
04418       ast_mutex_unlock(&c0->lock);
04419       ast_mutex_unlock(&c1->lock);
04420       return AST_BRIDGE_FAILED;
04421    }
04422 
04423    op0 = p0 = c0->tech_pvt;
04424    op1 = p1 = c1->tech_pvt;
04425    ofd0 = c0->fds[0];
04426    ofd1 = c1->fds[0];
04427    oc0 = p0->owner;
04428    oc1 = p1->owner;
04429 
04430    if (ast_mutex_trylock(&p0->lock)) {
04431       /* Don't block, due to potential for deadlock */
04432       ast_mutex_unlock(&c0->lock);
04433       ast_mutex_unlock(&c1->lock);
04434       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04435       return AST_BRIDGE_RETRY;
04436    }
04437    if (ast_mutex_trylock(&p1->lock)) {
04438       /* Don't block, due to potential for deadlock */
04439       ast_mutex_unlock(&p0->lock);
04440       ast_mutex_unlock(&c0->lock);
04441       ast_mutex_unlock(&c1->lock);
04442       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04443       return AST_BRIDGE_RETRY;
04444    }
04445 
04446    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04447       if (p0->owner && p1->owner) {
04448          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
04449          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
04450             master = p0;
04451             slave = p1;
04452             inconf = 1;
04453          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
04454             master = p1;
04455             slave = p0;
04456             inconf = 1;
04457          } else {
04458             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
04459             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
04460                p0->channel,
04461                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04462                p0->subs[SUB_REAL].inthreeway, p0->channel,
04463                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04464                p1->subs[SUB_REAL].inthreeway);
04465          }
04466          nothingok = 0;
04467       }
04468    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
04469       if (p1->subs[SUB_THREEWAY].inthreeway) {
04470          master = p1;
04471          slave = p0;
04472          nothingok = 0;
04473       }
04474    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
04475       if (p0->subs[SUB_THREEWAY].inthreeway) {
04476          master = p0;
04477          slave = p1;
04478          nothingok = 0;
04479       }
04480    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
04481       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise, 
04482          don't put us in anything */
04483       if (p1->subs[SUB_CALLWAIT].inthreeway) {
04484          master = p1;
04485          slave = p0;
04486          nothingok = 0;
04487       }
04488    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
04489       /* Same as previous */
04490       if (p0->subs[SUB_CALLWAIT].inthreeway) {
04491          master = p0;
04492          slave = p1;
04493          nothingok = 0;
04494       }
04495    }
04496    ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
04497       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
04498    if (master && slave) {
04499       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
04500          in an active threeway call with a channel that is ringing, we should
04501          indicate ringing. */
04502       if ((oi1 == SUB_THREEWAY) && 
04503           p1->subs[SUB_THREEWAY].inthreeway && 
04504           p1->subs[SUB_REAL].owner && 
04505           p1->subs[SUB_REAL].inthreeway && 
04506           (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04507          ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
04508          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
04509          os1 = p1->subs[SUB_REAL].owner->_state;
04510       } else {
04511          ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
04512          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
04513       }
04514       if ((oi0 == SUB_THREEWAY) && 
04515           p0->subs[SUB_THREEWAY].inthreeway && 
04516           p0->subs[SUB_REAL].owner && 
04517           p0->subs[SUB_REAL].inthreeway && 
04518           (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04519          ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
04520          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
04521          os0 = p0->subs[SUB_REAL].owner->_state;
04522       } else {
04523          ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
04524          tone_zone_play_tone(p1->subs[oi0].dfd, -1);
04525       }
04526       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04527          if (!p0->echocanbridged || !p1->echocanbridged) {
04528             /* Disable echo cancellation if appropriate */
04529             dahdi_disable_ec(p0);
04530             dahdi_disable_ec(p1);
04531          }
04532       }
04533       dahdi_link(slave, master);
04534       master->inconference = inconf;
04535    } else if (!nothingok)
04536       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
04537 
04538    update_conf(p0);
04539    update_conf(p1);
04540    t0 = p0->subs[SUB_REAL].inthreeway;
04541    t1 = p1->subs[SUB_REAL].inthreeway;
04542 
04543    ast_mutex_unlock(&p0->lock);
04544    ast_mutex_unlock(&p1->lock);
04545 
04546    ast_mutex_unlock(&c0->lock);
04547    ast_mutex_unlock(&c1->lock);
04548 
04549    /* Native bridge failed */
04550    if ((!master || !slave) && !nothingok) {
04551       dahdi_enable_ec(p0);
04552       dahdi_enable_ec(p1);
04553       return AST_BRIDGE_FAILED;
04554    }
04555    
04556    if (option_verbose > 2) 
04557       ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
04558 
04559    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04560       disable_dtmf_detect(op0);
04561 
04562    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04563       disable_dtmf_detect(op1);
04564 
04565    for (;;) {
04566       struct ast_channel *c0_priority[2] = {c0, c1};
04567       struct ast_channel *c1_priority[2] = {c1, c0};
04568 
04569       /* Here's our main loop...  Start by locking things, looking for private parts, 
04570          and then balking if anything is wrong */
04571       ast_mutex_lock(&c0->lock);
04572       while (ast_mutex_trylock(&c1->lock)) {
04573          DEADLOCK_AVOIDANCE(&c0->lock);
04574       }
04575 
04576       p0 = c0->tech_pvt;
04577       p1 = c1->tech_pvt;
04578 
04579       if (op0 == p0)
04580          i0 = dahdi_get_index(c0, p0, 1);
04581       if (op1 == p1)
04582          i1 = dahdi_get_index(c1, p1, 1);
04583       ast_mutex_unlock(&c0->lock);
04584       ast_mutex_unlock(&c1->lock);
04585 
04586       if (!timeoutms || 
04587           (op0 != p0) ||
04588           (op1 != p1) || 
04589           (ofd0 != c0->fds[0]) || 
04590           (ofd1 != c1->fds[0]) ||
04591           (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 
04592           (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 
04593           (oc0 != p0->owner) || 
04594           (oc1 != p1->owner) ||
04595           (t0 != p0->subs[SUB_REAL].inthreeway) ||
04596           (t1 != p1->subs[SUB_REAL].inthreeway) ||
04597           (oi0 != i0) ||
04598           (oi1 != i1)) {
04599          ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
04600             op0->channel, oi0, op1->channel, oi1);
04601          res = AST_BRIDGE_RETRY;
04602          goto return_from_bridge;
04603       }
04604 
04605 #ifdef PRI_2BCT
04606       q931c0 = p0->call;
04607       q931c1 = p1->call;
04608       if (p0->transfer && p1->transfer 
04609           && q931c0 && q931c1 
04610           && !triedtopribridge) {
04611          pri_channel_bridge(q931c0, q931c1);
04612          triedtopribridge = 1;
04613       }
04614 #endif
04615 
04616       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
04617       if (!who) {
04618          ast_log(LOG_DEBUG, "Ooh, empty read...\n");
04619          continue;
04620       }
04621       f = ast_read(who);
04622       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
04623          *fo = f;
04624          *rc = who;
04625          res = AST_BRIDGE_COMPLETE;
04626          goto return_from_bridge;
04627       }
04628       if (f->frametype == AST_FRAME_DTMF) {
04629          if ((who == c0) && p0->pulsedial) {
04630             ast_write(c1, f);
04631          } else if ((who == c1) && p1->pulsedial) {
04632             ast_write(c0, f);
04633          } else {
04634             *fo = f;
04635             *rc = who;
04636             res = AST_BRIDGE_COMPLETE;
04637             goto return_from_bridge;
04638          }
04639       }
04640       ast_frfree(f);
04641       
04642       /* Swap who gets priority */
04643       priority = !priority;
04644    }
04645 
04646 return_from_bridge:
04647    if (op0 == p0)
04648       dahdi_enable_ec(p0);
04649 
04650    if (op1 == p1)
04651       dahdi_enable_ec(p1);
04652 
04653    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04654       enable_dtmf_detect(op0);
04655 
04656    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04657       enable_dtmf_detect(op1);
04658 
04659    dahdi_unlink(slave, master, 1);
04660 
04661    return res;
04662 }

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

Definition at line 2714 of file chan_dahdi.c.

References ast_channel::_state, ast_callerid_generate(), ast_copy_string(), 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::bearer, dahdi_pvt::call, 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_r2_get_channel_category(), dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialednone, dahdi_pvt::dialing, dahdi_pri::dialplan, dialplan2str(), dahdi_pvt::digital, dahdi_pvt::distinctivering, dahdi_pvt::dop, dahdi_pvt::echobreak, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, dahdi_pri::facilityenable, dahdi_pvt::finaldial, free, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pri::internationalprefix, IS_DIGITAL, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_pvt::law, dahdi_pri::localdialplan, dahdi_pvt::lock, LOG_DEBUG, LOG_ERROR, LOG_WARNING, dahdi_pvt::logicalspan, MAX_CALLERID_SIZE, dahdi_pvt::mfcr2, ast_channel::name, dahdi_pri::nationalprefix, dahdi_subchannel::needbusy, dahdi_subchannel::needringing, dahdi_pri::nodetype, dahdi_pvt::oprmode, option_verbose, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pvt::owner, pbx_builtin_getvar_helper(), dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), PRI_TRANS_CAP_DIGITAL, dahdi_pvt::priexclusive, dahdi_pvt::pulse, PVT_TO_CHANNEL, dahdi_pvt::r2chan, 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_MFCR2, 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.

02715 {
02716    struct dahdi_pvt *p = ast->tech_pvt;
02717    int x, res, index,mysig;
02718    char *c, *n, *l;
02719 #ifdef HAVE_PRI
02720    char *s = NULL;
02721 #endif
02722    char dest[256]; /* must be same length as p->dialdest */
02723    ast_mutex_lock(&p->lock);
02724    ast_copy_string(dest, rdest, sizeof(dest));
02725    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
02726    if ((ast->_state == AST_STATE_BUSY)) {
02727       p->subs[SUB_REAL].needbusy = 1;
02728       ast_mutex_unlock(&p->lock);
02729       return 0;
02730    }
02731    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
02732       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
02733       ast_mutex_unlock(&p->lock);
02734       return -1;
02735    }
02736    p->dialednone = 0;
02737    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
02738    {
02739       /* Special pseudo -- automatically up */
02740       ast_setstate(ast, AST_STATE_UP); 
02741       ast_mutex_unlock(&p->lock);
02742       return 0;
02743    }
02744    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
02745    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
02746    if (res)
02747       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
02748    p->outgoing = 1;
02749 
02750    if (IS_DIGITAL(ast->transfercapability)) {
02751       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law);
02752    } else {
02753       set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02754    }
02755 
02756    mysig = p->sig;
02757    if (p->outsigmod > -1)
02758       mysig = p->outsigmod;
02759 
02760    switch (mysig) {
02761    case SIG_FXOLS:
02762    case SIG_FXOGS:
02763    case SIG_FXOKS:
02764       if (p->owner == ast) {
02765          /* Normal ring, on hook */
02766          
02767          /* Don't send audio while on hook, until the call is answered */
02768          p->dialing = 1;
02769          if (p->use_callerid) {
02770             /* Generate the Caller-ID spill if desired */
02771             if (p->cidspill) {
02772                ast_log(LOG_WARNING, "cidspill already exists??\n");
02773                free(p->cidspill);
02774             }
02775             p->callwaitcas = 0;
02776             if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02777                p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
02778                p->cidpos = 0;
02779                send_callerid(p);
02780             }
02781          }
02782          /* Choose proper cadence */
02783          if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02784             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02785                ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02786             p->cidrings = cidrings[p->distinctivering - 1];
02787          } else {
02788             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02789                ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02790             p->cidrings = p->sendcalleridafter;
02791          }
02792 
02793          /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
02794          c = strchr(dest, '/');
02795          if (c)
02796             c++;
02797          if (c && (strlen(c) < p->stripmsd)) {
02798             ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02799             c = NULL;
02800          }
02801          if (c) {
02802             p->dop.op = DAHDI_DIAL_OP_REPLACE;
02803             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
02804             ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
02805          } else {
02806             p->dop.dialstr[0] = '\0';
02807          }
02808          x = DAHDI_RING;
02809          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
02810             ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
02811             ast_mutex_unlock(&p->lock);
02812             return -1;
02813          }
02814          p->dialing = 1;
02815       } else {
02816          /* Call waiting call */
02817          p->callwaitrings = 0;
02818          if (ast->cid.cid_num)
02819             ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
02820          else
02821             p->callwait_num[0] = '\0';
02822          if (ast->cid.cid_name)
02823             ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
02824          else
02825             p->callwait_name[0] = '\0';
02826          /* Call waiting tone instead */
02827          if (dahdi_callwait(ast)) {
02828             ast_mutex_unlock(&p->lock);
02829             return -1;
02830          }
02831          /* Make ring-back */
02832          if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
02833             ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
02834             
02835       }
02836       n = ast->cid.cid_name;
02837       l = ast->cid.cid_num;
02838       if (l)
02839          ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
02840       else
02841          p->lastcid_num[0] = '\0';
02842       if (n)
02843          ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
02844       else
02845          p->lastcid_name[0] = '\0';
02846       ast_setstate(ast, AST_STATE_RINGING);
02847       index = dahdi_get_index(ast, p, 0);
02848       if (index > -1) {
02849          p->subs[index].needringing = 1;
02850       }
02851       break;
02852    case SIG_FXSLS:
02853    case SIG_FXSGS:
02854    case SIG_FXSKS:
02855    case SIG_EMWINK:
02856    case SIG_EM:
02857    case SIG_EM_E1:
02858    case SIG_FEATD:
02859    case SIG_FEATDMF:
02860    case SIG_E911:
02861    case SIG_FGC_CAMA:
02862    case SIG_FGC_CAMAMF:
02863    case SIG_FEATB:
02864    case SIG_SFWINK:
02865    case SIG_SF:
02866    case SIG_SF_FEATD:
02867    case SIG_SF_FEATDMF:
02868    case SIG_FEATDMF_TA:
02869    case SIG_SF_FEATB:
02870       c = strchr(dest, '/');
02871       if (c)
02872          c++;
02873       else
02874          c = "";
02875       if (strlen(c) < p->stripmsd) {
02876          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02877          ast_mutex_unlock(&p->lock);
02878          return -1;
02879       }
02880 #ifdef HAVE_PRI
02881       /* Start the trunk, if not GR-303 */
02882       if (!p->pri) {
02883 #endif
02884          x = DAHDI_START;
02885          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02886          if (res < 0) {
02887             if (errno != EINPROGRESS) {
02888                ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02889                ast_mutex_unlock(&p->lock);
02890                return -1;
02891             }
02892          }
02893 #ifdef HAVE_PRI
02894       }
02895 #endif
02896       ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
02897       p->dop.op = DAHDI_DIAL_OP_REPLACE;
02898 
02899       c += p->stripmsd;
02900 
02901       switch (mysig) {
02902       case SIG_FEATD:
02903          l = ast->cid.cid_num;
02904          if (l) 
02905             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02906          else
02907             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02908          break;
02909       case SIG_FEATDMF:
02910          l = ast->cid.cid_num;
02911          if (l) 
02912             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02913          else
02914             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02915          break;
02916       case SIG_FEATDMF_TA:
02917       {
02918          const char *cic, *ozz;
02919 
02920          /* If you have to go through a Tandem Access point you need to use this */
02921          ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02922          if (!ozz)
02923             ozz = defaultozz;
02924          cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02925          if (!cic)
02926             cic = defaultcic;
02927          if (!ozz || !cic) {
02928             ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02929             ast_mutex_unlock(&p->lock);
02930             return -1;
02931          }
02932          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02933          snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02934          p->whichwink = 0;
02935       }
02936          break;
02937       case SIG_E911:
02938          ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02939          break;
02940       case SIG_FGC_CAMA:
02941          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02942          break;
02943       case SIG_FGC_CAMAMF:
02944       case SIG_FEATB:
02945          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02946          break;
02947       default:
02948          if (p->pulse)
02949             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02950          else
02951             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02952          break;
02953       }
02954 
02955       if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02956          memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02957          strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02958          p->echorest[sizeof(p->echorest) - 1] = '\0';
02959          p->echobreak = 1;
02960          p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02961       } else
02962          p->echobreak = 0;
02963       if (!res) {
02964          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02965             int saveerr = errno;
02966 
02967             x = DAHDI_ONHOOK;
02968             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02969             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02970             ast_mutex_unlock(&p->lock);
02971             return -1;
02972          }
02973       } else
02974          ast_log(LOG_DEBUG, "Deferring dialing... (res %d)\n", res);
02975       p->dialing = 1;
02976       if (ast_strlen_zero(c))
02977          p->dialednone = 1;
02978       ast_setstate(ast, AST_STATE_DIALING);
02979       break;
02980    case 0:
02981       /* Special pseudo -- automatically up*/
02982       ast_setstate(ast, AST_STATE_UP);
02983       break;      
02984    case SIG_PRI:
02985    case SIG_MFCR2:
02986       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
02987       p->dialdest[0] = '\0';
02988       p->dialing = 1;
02989       break;
02990    default:
02991       ast_log(LOG_DEBUG, "not yet implemented\n");
02992       ast_mutex_unlock(&p->lock);
02993       return -1;
02994    }
02995 #ifdef HAVE_OPENR2
02996    if (p->mfcr2) {
02997       int strip = p->stripmsd;
02998       int callres = 0;
02999       c = strchr(dest, '/');
03000       if (c) {
03001          c++;
03002       } else {
03003          c = dest;
03004       }
03005       if (!p->hidecallerid) {
03006          l = ast->cid.cid_num;
03007       } else {
03008          l = NULL;
03009       }
03010       if (strlen(c) < strip) {
03011          ast_log(LOG_WARNING, "Destiny number '%s' is shorter than stripmsd(%d)? hum, you should fix that. Assuming stripmsd = 0\n", c, strip);
03012          strip = 0;
03013       }
03014       p->dialing = 1;
03015       callres = openr2_chan_make_call(p->r2chan, l, (c + strip), dahdi_r2_get_channel_category(ast));
03016       if (-1 == callres) {
03017          ast_mutex_unlock(&p->lock);
03018          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
03019          return -1;
03020       }
03021       ast_setstate(ast, AST_STATE_DIALING);
03022    }
03023 #endif /* HAVE_OPENR2 */
03024 #ifdef HAVE_PRI
03025    if (p->pri) {
03026       struct pri_sr *sr;
03027 #ifdef SUPPORT_USERUSER
03028       const char *useruser;
03029 #endif
03030       int pridialplan;
03031       int dp_strip;
03032       int prilocaldialplan;
03033       int ldp_strip;
03034       int exclusive;
03035       const char *rr_str;
03036       int redirect_reason;
03037 
03038       c = strchr(dest, '/');
03039       if (c) {
03040          c++;
03041       } else {
03042          c = "";
03043       }
03044 
03045       l = NULL;
03046       n = NULL;
03047       if (!p->hidecallerid) {
03048          l = ast->cid.cid_num;
03049          if (!p->hidecalleridname) {
03050             n = ast->cid.cid_name;
03051          }
03052       }
03053 
03054 
03055       if (strlen(c) < p->stripmsd) {
03056          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03057          ast_mutex_unlock(&p->lock);
03058          return -1;
03059       }
03060       if (mysig != SIG_FXSKS) {
03061          p->dop.op = DAHDI_DIAL_OP_REPLACE;
03062          s = strchr(c + p->stripmsd, 'w');
03063          if (s) {
03064             if (strlen(s) > 1)
03065                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
03066             else
03067                p->dop.dialstr[0] = '\0';
03068             *s = '\0';
03069          } else {
03070             p->dop.dialstr[0] = '\0';
03071          }
03072       }
03073       if (pri_grab(p, p->pri)) {
03074          ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03075          ast_mutex_unlock(&p->lock);
03076          return -1;
03077       }
03078       if (!(p->call = pri_new_call(p->pri->pri))) {
03079          ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
03080          pri_rel(p->pri);
03081          ast_mutex_unlock(&p->lock);
03082          return -1;
03083       }
03084       if (!(sr = pri_sr_new())) {
03085          ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
03086          pri_destroycall(p->pri->pri, p->call);
03087          p->call = NULL;
03088          pri_rel(p->pri);
03089          ast_mutex_unlock(&p->lock);
03090          return -1;
03091       }
03092       if (p->bearer || (mysig == SIG_FXSKS)) {
03093          if (p->bearer) {
03094             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);
03095             p->bearer->call = p->call;
03096          } else
03097             ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
03098          pri_set_crv(p->pri->pri, p->call, p->channel, 0);
03099       }
03100       p->digital = IS_DIGITAL(ast->transfercapability);
03101 
03102       /* Should the picked channel be used exclusively? */
03103       if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
03104          exclusive = 1;
03105       } else {
03106          exclusive = 0;
03107       }
03108       
03109       pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
03110       pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 
03111                (p->digital ? -1 : 
03112                   ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
03113       if (p->pri->facilityenable)
03114          pri_facility_enable(p->pri->pri);
03115 
03116       if (option_verbose > 2)
03117          ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
03118       dp_strip = 0;
03119       pridialplan = p->pri->dialplan - 1;
03120       if (pridialplan == -2) { /* compute dynamically */
03121          if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03122             dp_strip = strlen(p->pri->internationalprefix);
03123             pridialplan = PRI_INTERNATIONAL_ISDN;
03124          } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03125             dp_strip = strlen(p->pri->nationalprefix);
03126             pridialplan = PRI_NATIONAL_ISDN;
03127          } else {
03128             pridialplan = PRI_LOCAL_ISDN;
03129          }
03130       }
03131       pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03132 
03133       ldp_strip = 0;
03134       prilocaldialplan = p->pri->localdialplan - 1;
03135       if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */
03136          if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03137             ldp_strip = strlen(p->pri->internationalprefix);
03138             prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03139          } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03140             ldp_strip = strlen(p->pri->nationalprefix);
03141             prilocaldialplan = PRI_NATIONAL_ISDN;
03142          } else {
03143             prilocaldialplan = PRI_LOCAL_ISDN;
03144          }
03145       }
03146       pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03147          p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03148       if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03149          if (!strcasecmp(rr_str, "UNKNOWN"))
03150             redirect_reason = 0;
03151          else if (!strcasecmp(rr_str, "BUSY"))
03152             redirect_reason = 1;
03153          else if (!strcasecmp(rr_str, "NO_REPLY"))
03154             redirect_reason = 2;
03155          else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03156             redirect_reason = 15;
03157          else
03158             redirect_reason = PRI_REDIR_UNCONDITIONAL;
03159       } else
03160          redirect_reason = PRI_REDIR_UNCONDITIONAL;
03161       pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03162 
03163 #ifdef SUPPORT_USERUSER
03164       /* User-user info */
03165       useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03166 
03167       if (useruser)
03168          pri_sr_set_useruser(sr, useruser);
03169 #endif
03170 
03171       if (pri_setup(p->pri->pri, p->call, sr)) {
03172          ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 
03173             c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03174          pri_rel(p->pri);
03175          ast_mutex_unlock(&p->lock);
03176          pri_sr_free(sr);
03177          return -1;
03178       }
03179       pri_sr_free(sr);
03180       ast_setstate(ast, AST_STATE_DIALING);
03181       pri_rel(p->pri);
03182    }
03183 #endif      
03184    ast_mutex_unlock(&p->lock);
03185    return 0;
03186 }

static int dahdi_callwait ( struct ast_channel ast  )  [static]

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

02687 {
02688    struct dahdi_pvt *p = ast->tech_pvt;
02689    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02690    if (p->cidspill) {
02691       ast_log(LOG_WARNING, "Spill already exists?!?\n");
02692       free(p->cidspill);
02693    }
02694    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
02695       return -1;
02696    save_conference(p);
02697    /* Silence */
02698    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02699    if (!p->callwaitrings && p->callwaitingcallerid) {
02700       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
02701       p->callwaitcas = 1;
02702       p->cidlen = 2400 + 680 + READ_SIZE * 4;
02703    } else {
02704       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
02705       p->callwaitcas = 0;
02706       p->cidlen = 2400 + READ_SIZE * 4;
02707    }
02708    p->cidpos = 0;
02709    send_callerid(p);
02710    
02711    return 0;
02712 }

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

References CID_SIG_BELL, CID_START_RING, DEFAULT_CIDRINGS, dahdi_pri::nsf, and dahdi_chan_conf::pri.

Referenced by setup_dahdi().

00997                                                             {
00998    /* recall that if a field is not included here it is initialized
00999     * to 0 or equivalent
01000     */
01001    struct dahdi_chan_conf conf = {
01002 #ifdef HAVE_PRI
01003       .pri = {
01004          .nsf = PRI_NSF_NONE,
01005          .switchtype = PRI_SWITCH_NI2,
01006          .dialplan = PRI_NATIONAL_ISDN + 1,
01007          .localdialplan = PRI_NATIONAL_ISDN + 1,
01008          .nodetype = PRI_CPE,
01009 
01010          .minunused = 2,
01011          .idleext = "",
01012          .idledial = "",
01013          .internationalprefix = "",
01014          .nationalprefix = "",
01015          .localprefix = "",
01016          .privateprefix = "",
01017          .unknownprefix = "",
01018 
01019          .resetinterval = 3600
01020       },
01021 #endif
01022       .chan = {
01023          .context = "default",
01024          .cid_num = "",
01025          .cid_name = "",
01026          .mohinterpret = "default",
01027          .mohsuggest = "",
01028          .transfertobusy = 1,
01029 
01030          .cid_signalling = CID_SIG_BELL,
01031          .cid_start = CID_START_RING,
01032          .dahditrcallerid = 0,
01033          .use_callerid = 1,
01034          .sig = -1,
01035          .outsigmod = -1,
01036 
01037          .tonezone = -1,
01038 
01039          .echocancel = 1,
01040 
01041          .busycount = 3,
01042          .busycompare = 0,
01043          .busytonelength = 0,
01044          .busyquietlength = 0,
01045          .busyfuzziness = 0,
01046          .silencethreshold = 0,
01047 
01048          .accountcode = "",
01049 
01050          .mailbox = "",
01051 
01052 
01053          .polarityonanswerdelay = 600,
01054 
01055          .sendcalleridafter = DEFAULT_CIDRINGS,
01056 
01057          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01058          .buf_no = numbufs
01059       },
01060       .timing = {
01061          .prewinktime = -1,
01062          .preflashtime = -1,
01063          .winktime = -1,
01064          .flashtime = -1,
01065          .starttime = -1,
01066          .rxwinktime = -1,
01067          .rxflashtime = -1,
01068          .debouncetime = -1
01069       },
01070       .smdi_port = "/dev/ttyS0",
01071    };
01072 
01073    return conf;
01074 }

static void dahdi_close ( int  fd  )  [static]

Definition at line 1847 of file chan_dahdi.c.

Referenced by dahdi_close_pri_fd(), and dahdi_close_sub().

01848 {
01849    if (fd > 0)
01850       close(fd);
01851 }

static void dahdi_close_pri_fd ( struct dahdi_pri pri,
int  fd_num 
) [static]

Definition at line 1860 of file chan_dahdi.c.

References dahdi_close(), and dahdi_pri::fds.

Referenced by __unload_module(), dahdi_restart(), and start_pri().

01861 {
01862    dahdi_close(pri->fds[fd_num]);
01863    pri->fds[fd_num] = -1;
01864 }

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

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

01854 {
01855    dahdi_close(chan_pvt->subs[sub_num].dfd);
01856    chan_pvt->subs[sub_num].dfd = -1;
01857 }

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

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

02571 {
02572    int x, y, res;
02573    x = muted;
02574    if (p->sig == SIG_PRI) {
02575       y = 1;
02576       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02577       if (res)
02578          ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02579    }
02580    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02581    if (res < 0)
02582       ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02583    return res;
02584 }

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

Definition at line 11921 of file chan_dahdi.c.

References dahdi_destroy_channel_bynum(), and RESULT_SHOWUSAGE.

11922 {
11923    int channel;
11924    
11925    if (argc != 4)
11926       return RESULT_SHOWUSAGE;
11927    
11928    channel = atoi(argv[3]);
11929 
11930    return dahdi_destroy_channel_bynum(channel);
11931 }

static int dahdi_destroy_channel_bynum ( int  channel  )  [static]

Definition at line 7932 of file chan_dahdi.c.

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

Referenced by dahdi_destroy_channel().

07933 {
07934    struct dahdi_pvt *tmp = NULL;
07935    struct dahdi_pvt *prev = NULL;
07936 
07937    ast_mutex_lock(&iflock);
07938    tmp = iflist;
07939    while (tmp) {
07940       if (tmp->channel == channel) {
07941          int x = DAHDI_FLASH;
07942          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 */
07943          destroy_channel(prev, tmp, 1);
07944          ast_mutex_unlock(&iflock);
07945          ast_module_unref(ast_module_info->self);
07946          return RESULT_SUCCESS;
07947       }
07948       prev = tmp;
07949       tmp = tmp->next;
07950    }
07951    ast_mutex_unlock(&iflock);
07952    return RESULT_FAILURE;
07953 }

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

Definition at line 1944 of file chan_dahdi.c.

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

01945 {
01946    struct dahdi_pvt *pvt;
01947    int index;
01948    int dtmf = -1;
01949    
01950    pvt = chan->tech_pvt;
01951 
01952    ast_mutex_lock(&pvt->lock);
01953 
01954    index = dahdi_get_index(chan, pvt, 0);
01955 
01956    if ((index != SUB_REAL) || !pvt->owner)
01957       goto out;
01958 
01959 #ifdef HAVE_PRI
01960    if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01961       if (pvt->setup_ack) {
01962          if (!pri_grab(pvt, pvt->pri)) {
01963             pri_information(pvt->pri->pri, pvt->call, digit);
01964             pri_rel(pvt->pri);
01965          } else
01966             ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01967       } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01968          int res;
01969          ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01970          res = strlen(pvt->dialdest);
01971          pvt->dialdest[res++] = digit;
01972          pvt->dialdest[res] = '\0';
01973       }
01974       goto out;
01975    }
01976 #endif
01977    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01978       goto out;
01979 
01980    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
01981       int res;
01982       struct dahdi_dialoperation zo = {
01983          .op = DAHDI_DIAL_OP_APPEND,
01984          .dialstr[0] = 'T',
01985          .dialstr[1] = digit,
01986          .dialstr[2] = 0,
01987       };
01988       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
01989          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
01990       else
01991          pvt->dialing = 1;
01992    } else {
01993       ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
01994       pvt->dialing = 1;
01995       pvt->begindigit = digit;
01996    }
01997 
01998 out:
01999    ast_mutex_unlock(&pvt->lock);
02000 
02001    return 0;
02002 }

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

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

02005 {
02006    struct dahdi_pvt *pvt;
02007    int res = 0;
02008    int index;
02009    int x;
02010    
02011    pvt = chan->tech_pvt;
02012 
02013    ast_mutex_lock(&pvt->lock);
02014    
02015    index = dahdi_get_index(chan, pvt, 0);
02016 
02017    if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
02018       goto out;
02019 
02020 #ifdef HAVE_PRI
02021    /* This means that the digit was already sent via PRI signalling */
02022    if (pvt->sig == SIG_PRI && !pvt->begindigit)
02023       goto out;
02024 #endif
02025 
02026    if (pvt->begindigit) {
02027       x = -1;
02028       ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
02029       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
02030       pvt->dialing = 0;
02031       pvt->begindigit = 0;
02032    }
02033 
02034 out:
02035    ast_mutex_unlock(&pvt->lock);
02036 
02037    return res;
02038 }

static void dahdi_disable_ec ( struct dahdi_pvt p  )  [static]

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

02402 {
02403    int x;
02404    int res;
02405    if (p->echocancel) {
02406       x = 0;
02407       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
02408       if (res)
02409          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02410       else if (option_debug)
02411          ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
02412    }
02413    p->echocanon = 0;
02414 }

static void dahdi_enable_ec ( struct dahdi_pvt p  )  [static]

Definition at line 2351 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_r2_on_call_accepted(), dahdi_setoption(), handle_init_event(), and ss_thread().

02352 {
02353    int x;
02354    int res;
02355    if (!p)
02356       return;
02357    if (p->echocanon) {
02358       ast_log(LOG_DEBUG, "Echo cancellation already on\n");
02359       return;
02360    }
02361    if (p->digital) {
02362       ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
02363       return;
02364    }
02365    if (p->echocancel) {
02366       if (p->sig == SIG_PRI) {
02367          x = 1;
02368          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02369          if (res)
02370             ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02371       }
02372       x = p->echocancel;
02373       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
02374       if (res) 
02375          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02376       else {
02377          p->echocanon = 1;
02378          if (option_debug)
02379             ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
02380       }
02381    } else if (option_debug)
02382       ast_log(LOG_DEBUG, "No echo cancellation requested\n");
02383 }

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

Definition at line 5899 of file chan_dahdi.c.

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

05900 {
05901    struct dahdi_pvt *p = ast->tech_pvt;
05902    struct ast_frame *f;
05903    ast_mutex_lock(&p->lock);
05904    f = __dahdi_exception(ast);
05905    ast_mutex_unlock(&p->lock);
05906    return f;
05907 }

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

Definition at line 12501 of file chan_dahdi.c.

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

Referenced by __action_transfer(), and __action_transferhangup().

12502 {
12503    if (p) {
12504       switch (mode) {
12505          case TRANSFER:
12506             p->fake_event = DAHDI_EVENT_WINKFLASH;
12507             break;
12508          case HANGUP:
12509             p->fake_event = DAHDI_EVENT_ONHOOK;
12510             break;
12511          default:
12512             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
12513       }
12514    }
12515    return 0;
12516 }

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

Definition at line 4664 of file chan_dahdi.c.

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

04665 {
04666    struct dahdi_pvt *p = newchan->tech_pvt;
04667    int x;
04668    ast_mutex_lock(&p->lock);
04669    ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
04670    if (p->owner == oldchan) {
04671       p->owner = newchan;
04672    }
04673    for (x = 0; x < 3; x++)
04674       if (p->subs[x].owner == oldchan) {
04675          if (!x)
04676             dahdi_unlink(NULL, p, 0);
04677          p->subs[x].owner = newchan;
04678       }
04679    if (newchan->_state == AST_STATE_RINGING) 
04680       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
04681    update_conf(p);
04682    ast_mutex_unlock(&p->lock);
04683    return 0;
04684 }

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

Definition at line 4236 of file chan_dahdi.c.

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

04237 {
04238    struct dahdi_pvt *p = chan->tech_pvt;
04239    
04240    if (!strcasecmp(data, "rxgain")) {
04241       ast_mutex_lock(&p->lock);
04242       snprintf(buf, len, "%f", p->rxgain);
04243       ast_mutex_unlock(&p->lock);   
04244    } else if (!strcasecmp(data, "txgain")) {
04245       ast_mutex_lock(&p->lock);
04246       snprintf(buf, len, "%f", p->txgain);
04247       ast_mutex_unlock(&p->lock);   
04248    } else {
04249       ast_copy_string(buf, "", len);
04250    }
04251    return 0;
04252 }

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

Avoid the silly dahdi_getevent which ignores a bunch of events.

Definition at line 272 of file chan_dahdi.c.

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

00273 {
00274    int j;
00275    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00276       return -1;
00277    return j;
00278 }

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

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

01191 {
01192    int res;
01193    if (p->subs[SUB_REAL].owner == ast)
01194       res = 0;
01195    else if (p->subs[SUB_CALLWAIT].owner == ast)
01196       res = 1;
01197    else if (p->subs[SUB_THREEWAY].owner == ast)
01198       res = 2;
01199    else {
01200       res = -1;
01201       if (!nullok)
01202          ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
01203    }
01204    return res;
01205 }

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

Definition at line 4826 of file chan_dahdi.c.

References ast_async_goto(), ast_channel_lock, ast_channel_unlock, AST_CONTROL_ANSWER, ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_NULL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), 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, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, ast_channel::macrocontext, ast_channel::name, 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().

04827 {
04828    struct dahdi_pvt *p = ast->tech_pvt;
04829    struct ast_frame *f = *dest;
04830 
04831    if (option_debug)
04832       ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
04833 
04834    if (p->confirmanswer) {
04835       if (option_debug)
04836          ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
04837       /* Upon receiving a DTMF digit, consider this an answer confirmation instead
04838          of a DTMF digit */
04839       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04840       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04841       *dest = &p->subs[index].f;
04842       /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
04843       p->confirmanswer = 0;
04844    } else if (p->callwaitcas) {
04845       if ((f->subclass == 'A') || (f->subclass == 'D')) {
04846          if (option_debug)
04847             ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
04848          if (p->cidspill)
04849             free(p->cidspill);
04850          send_cwcidspill(p);
04851       }
04852       if ((f->subclass != 'm') && (f->subclass != 'u')) 
04853          p->callwaitcas = 0;
04854       p->subs[index].f.frametype = AST_FRAME_NULL;
04855       p->subs[index].f.subclass = 0;
04856       *dest = &p->subs[index].f;
04857    } else if (f->subclass == 'f') {
04858       /* Fax tone -- Handle and return NULL */
04859       if ((p->callprogress & 0x6) && !p->faxhandled) {
04860          p->faxhandled = 1;
04861          if (strcmp(ast->exten, "fax")) {
04862             const char *target_context = S_OR(ast->macrocontext, ast->context);
04863 
04864             /* We need to unlock 'ast' here because ast_exists_extension has the
04865              * potential to start autoservice on the channel. Such action is prone
04866              * to deadlock.
04867              */
04868             ast_mutex_unlock(&p->lock);
04869             ast_channel_unlock(ast);
04870             if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
04871                ast_channel_lock(ast);
04872                ast_mutex_lock(&p->lock);
04873                if (option_verbose > 2)
04874                   ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
04875                /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
04876                pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
04877                if (ast_async_goto(ast, target_context, "fax", 1))
04878                   ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
04879             } else {
04880                ast_channel_lock(ast);
04881                ast_mutex_lock(&p->lock);
04882                ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
04883             }
04884          } else if (option_debug)
04885             ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
04886       } else if (option_debug)
04887             ast_log(LOG_DEBUG, "Fax already handled\n");
04888       dahdi_confmute(p, 0);
04889       p->subs[index].f.frametype = AST_FRAME_NULL;
04890       p->subs[index].f.subclass = 0;
04891       *dest = &p->subs[index].f;
04892    } else if (f->subclass == 'm') {
04893       /* Confmute request */
04894       dahdi_confmute(p, 1);
04895       p->subs[index].f.frametype = AST_FRAME_NULL;
04896       p->subs[index].f.subclass = 0;
04897       *dest = &p->subs[index].f;    
04898    } else if (f->subclass == 'u') {
04899       /* Unmute */
04900       dahdi_confmute(p, 0);
04901       p->subs[index].f.frametype = AST_FRAME_NULL;
04902       p->subs[index].f.subclass = 0;
04903       *dest = &p->subs[index].f;    
04904    } else
04905       dahdi_confmute(p, 0);
04906 }

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

Definition at line 4928 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_copy_string(), 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_tvdiff_ms(), ast_tvnow(), ast_verbose(), attempt_transfer(), dahdi_pvt::bearer, dahdi_pvt::call, 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_OVERLAPDIAL_INCOMING, 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, ast_channel::name, 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_pri::overlapdial, dahdi_subchannel::owner, dahdi_pvt::owner, ast_channel::pbx, dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pvt::polaritydelaytv, dahdi_pvt::polarityonanswerdelay, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, dahdi_pvt::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, restore_conference(), ast_channel::rings, dahdi_pvt::ringt, dahdi_pvt::ringt_base, S_OR, ast_frame::samples, save_conference(), dahdi_pvt::sig, sig2str, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, SIG_PRI, 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().

04929 {
04930    int res, x;
04931    int index, mysig;
04932    char *c;
04933    struct dahdi_pvt *p = ast->tech_pvt;
04934    pthread_t threadid;
04935    pthread_attr_t attr;
04936    struct ast_channel *chan;
04937    struct ast_frame *f;
04938 
04939    index = dahdi_get_index(ast, p, 0);
04940    mysig = p->sig;
04941    if (p->outsigmod > -1)
04942       mysig = p->outsigmod;
04943    p->subs[index].f.frametype = AST_FRAME_NULL;
04944    p->subs[index].f.subclass = 0;
04945    p->subs[index].f.datalen = 0;
04946    p->subs[index].f.samples = 0;
04947    p->subs[index].f.mallocd = 0;
04948    p->subs[index].f.offset = 0;
04949    p->subs[index].f.src = "dahdi_handle_event";
04950    p->subs[index].f.data = NULL;
04951    f = &p->subs[index].f;
04952 
04953    if (index < 0)
04954       return &p->subs[index].f;
04955    if (p->fake_event) {
04956       res = p->fake_event;
04957       p->fake_event = 0;
04958    } else
04959       res = dahdi_get_event(p->subs[index].dfd);
04960 
04961    if (option_debug)
04962       ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
04963 
04964    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
04965       p->pulsedial =  (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
04966 
04967       ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
04968 #ifdef HAVE_PRI
04969       if (!p->proceeding && p->sig == SIG_PRI && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
04970          /* absorb event */
04971       } else {
04972 #endif
04973          p->subs[index].f.frametype = AST_FRAME_DTMF_END;
04974          p->subs[index].f.subclass = res & 0xff;
04975 #ifdef HAVE_PRI
04976       }
04977 #endif
04978       dahdi_handle_dtmfup(ast, index, &f);
04979       return f;
04980    }
04981 
04982    if (res & DAHDI_EVENT_DTMFDOWN) {
04983       if (option_debug)
04984          ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
04985       /* Mute conference */
04986       dahdi_confmute(p, 1);
04987       p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
04988       p->subs[index].f.subclass = res & 0xff;
04989       return &p->subs[index].f;
04990    }
04991 
04992    switch (res) {
04993 #ifdef DAHDI_EVENT_EC_DISABLED
04994       case DAHDI_EVENT_EC_DISABLED:
04995          if (option_verbose > 2) 
04996             ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
04997          p->echocanon = 0;
04998          break;
04999 #endif
05000       case DAHDI_EVENT_BITSCHANGED:
05001 #ifdef HAVE_OPENR2
05002          if (p->sig != SIG_MFCR2) {
05003             ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
05004          } else {
05005             ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
05006             openr2_chan_handle_cas(p->r2chan);
05007          }
05008 #else
05009          ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
05010 #endif
05011       case DAHDI_EVENT_PULSE_START:
05012          /* Stop tone if there's a pulse start and the PBX isn't started */
05013          if (!ast->pbx)
05014             tone_zone_play_tone(p->subs[index].dfd, -1);
05015          break;   
05016       case DAHDI_EVENT_DIALCOMPLETE:
05017 #ifdef HAVE_OPENR2
05018          if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
05019             /* we don't need to do anything for this event for R2 signaling 
05020                if the call is being setup */
05021             break;
05022          }
05023 #endif
05024          if (p->inalarm) break;
05025          if ((p->radio || (p->oprmode < 0))) break;
05026          if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
05027             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
05028             return NULL;
05029          }
05030          if (!x) { /* if not still dialing in driver */
05031             dahdi_enable_ec(p);
05032             if (p->echobreak) {
05033                dahdi_train_ec(p);
05034                ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
05035                p->dop.op = DAHDI_DIAL_OP_REPLACE;
05036                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05037                p->echobreak = 0;
05038             } else {
05039                p->dialing = 0;
05040                if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
05041                   /* if thru with dialing after offhook */
05042                   if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
05043                      ast_setstate(ast, AST_STATE_UP);
05044                      p->subs[index].f.frametype = AST_FRAME_CONTROL;
05045                      p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05046                      break;
05047                   } else { /* if to state wait for offhook to dial rest */
05048                      /* we now wait for off hook */
05049                      ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
05050                   }
05051                }
05052                if (ast->_state == AST_STATE_DIALING) {
05053                   if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
05054                      ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
05055                   } 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)))) {
05056                      ast_setstate(ast, AST_STATE_RINGING);
05057                   } else if (!p->answeronpolarityswitch) {
05058                      ast_setstate(ast, AST_STATE_UP);
05059                      p->subs[index].f.frametype = AST_FRAME_CONTROL;
05060                      p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05061                      /* If aops=0 and hops=1, this is necessary */
05062                      p->polarity = POLARITY_REV;
05063                   } else {
05064                      /* Start clean, so we can catch the change to REV polarity when party answers */
05065                      p->polarity = POLARITY_IDLE;
05066                   }
05067                }
05068             }
05069          }
05070          break;
05071       case DAHDI_EVENT_ALARM:
05072 #ifdef HAVE_PRI
05073          if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
05074             /* T309 is not enabled : hangup calls when alarm occurs */
05075             if (p->call) {
05076                if (p->pri && p->pri->pri) {
05077                   if (!pri_grab(p, p->pri)) {
05078                      pri_hangup(p->pri->pri, p->call, -1);
05079                      pri_destroycall(p->pri->pri, p->call);
05080                      p->call = NULL;
05081                      pri_rel(p->pri);
05082                   } else
05083                      ast_log(LOG_WARNING, "Failed to grab PRI!\n");
05084                } else
05085                   ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
05086             }
05087             if (p->owner)
05088                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
05089          }
05090          if (p->bearer)
05091             p->bearer->inalarm = 1;
05092          else
05093 #endif
05094          p->inalarm = 1;
05095          res = get_alarms(p);
05096          handle_alarms(p, res);
05097 #ifdef HAVE_PRI
05098          if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
05099             /* fall through intentionally */
05100          } else {
05101             break;
05102          }
05103 #endif
05104 #ifdef HAVE_OPENR2
05105          if (p->sig == SIG_MFCR2)
05106             break;
05107 #endif
05108       case DAHDI_EVENT_ONHOOK:
05109          if (p->radio) {
05110             p->subs[index].f.frametype = AST_FRAME_CONTROL;
05111             p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
05112             break;
05113          }
05114          if (p->oprmode < 0)
05115          {
05116             if (p->oprmode != -1) break;
05117             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05118             {
05119                /* Make sure it starts ringing */
05120                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05121                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
05122                save_conference(p->oprpeer);
05123                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05124             }
05125             break;
05126          }
05127          switch (p->sig) {
05128          case SIG_FXOLS:
05129          case SIG_FXOGS:
05130          case SIG_FXOKS:
05131             p->onhooktime = time(NULL);
05132             p->msgstate = -1;
05133             /* Check for some special conditions regarding call waiting */
05134             if (index == SUB_REAL) {
05135                /* The normal line was hung up */
05136                if (p->subs[SUB_CALLWAIT].owner) {
05137                   /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
05138                   swap_subs(p, SUB_CALLWAIT, SUB_REAL);
05139                   if (option_verbose > 2) 
05140                      ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
05141                   unalloc_sub(p, SUB_CALLWAIT); 
05142 #if 0
05143                   p->subs[index].needanswer = 0;
05144                   p->subs[index].needringing = 0;
05145 #endif                  
05146                   p->callwaitingrepeat = 0;
05147                   p->cidcwexpire = 0;
05148                   p->owner = NULL;
05149                   /* Don't start streaming audio yet if the incoming call isn't up yet */
05150                   if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
05151                      p->dialing = 1;
05152                   dahdi_ring_phone(p);
05153                } else if (p->subs[SUB_THREEWAY].owner) {
05154                   unsigned int mssinceflash;
05155                   /* Here we have to retain the lock on both the main channel, the 3-way channel, and
05156                      the private structure -- not especially easy or clean */
05157                   while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
05158                      /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
05159                      ast_mutex_unlock(&p->lock);
05160                      DEADLOCK_AVOIDANCE(&ast->lock);
05161                      /* We can grab ast and p in that order, without worry.  We should make sure
05162                         nothing seriously bad has happened though like some sort of bizarre double
05163                         masquerade! */
05164                      ast_mutex_lock(&p->lock);
05165                      if (p->owner != ast) {
05166                         ast_log(LOG_WARNING, "This isn't good...\n");
05167                         return NULL;
05168                      }
05169                   }
05170                   if (!p->subs[SUB_THREEWAY].owner) {
05171                      ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
05172                      return NULL;
05173                   }
05174                   mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
05175                   ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
05176                   if (mssinceflash < MIN_MS_SINCE_FLASH) {
05177                      /* It hasn't been long enough since the last flashook.  This is probably a bounce on 
05178                         hanging up.  Hangup both channels now */
05179                      if (p->subs[SUB_THREEWAY].owner)
05180                         ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
05181                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05182                      ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
05183                      ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05184                   } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
05185                      if (p->transfer) {
05186                         /* In any case this isn't a threeway call anymore */
05187                         p->subs[SUB_REAL].inthreeway = 0;
05188                         p->subs[SUB_THREEWAY].inthreeway = 0;
05189                         /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
05190                         if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
05191                            ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05192                            /* Swap subs and dis-own channel */
05193                            swap_subs(p, SUB_THREEWAY, SUB_REAL);
05194                            p->owner = NULL;
05195                            /* Ring the phone */
05196                            dahdi_ring_phone(p);
05197                         } else {
05198                            if ((res = attempt_transfer(p)) < 0) {
05199                               p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05200                               if (p->subs[SUB_THREEWAY].owner)
05201                                  ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05202                            } else if (res) {
05203                               /* Don't actually hang up at this point */
05204                               if (p->subs[SUB_THREEWAY].owner)
05205                                  ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05206                               break;
05207                            }
05208                         }
05209                      } else {
05210                         p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05211                         if (p->subs[SUB_THREEWAY].owner)
05212                            ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05213                      }
05214                   } else {
05215                      ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05216                      /* Swap subs and dis-own channel */
05217                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
05218                      p->owner = NULL;
05219                      /* Ring the phone */
05220                      dahdi_ring_phone(p);
05221                   }
05222                }
05223             } else {
05224                ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
05225             }
05226             /* Fall through */
05227          default:
05228             dahdi_disable_ec(p);
05229             return NULL;
05230          }
05231          break;
05232       case DAHDI_EVENT_RINGOFFHOOK:
05233          if (p->inalarm) break;
05234          if (p->oprmode < 0)
05235          {
05236             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05237             {
05238                /* Make sure it stops ringing */
05239                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05240                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
05241                restore_conference(p->oprpeer);
05242             }
05243             break;
05244          }
05245          if (p->radio)
05246          {
05247             p->subs[index].f.frametype = AST_FRAME_CONTROL;
05248             p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
05249             break;
05250          }
05251          /* for E911, its supposed to wait for offhook then dial
05252             the second half of the dial string */
05253          if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
05254             c = strchr(p->dialdest, '/');
05255             if (c)
05256                c++;
05257             else
05258                c = p->dialdest;
05259             if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
05260             else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
05261             if (strlen(p->dop.dialstr) > 4) {
05262                memset(p->echorest, 'w', sizeof(p->echorest) - 1);
05263                strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
05264                p->echorest[sizeof(p->echorest) - 1] = '\0';
05265                p->echobreak = 1;
05266                p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
05267             } else
05268                p->echobreak = 0;
05269             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
05270                int saveerr = errno;
05271 
05272                x = DAHDI_ONHOOK;
05273                ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05274                ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
05275                return NULL;
05276                }
05277             p->dialing = 1;
05278             return &p->subs[index].f;
05279          }
05280          switch (p->sig) {
05281          case SIG_FXOLS:
05282          case SIG_FXOGS:
05283          case SIG_FXOKS:
05284             switch (ast->_state) {
05285             case AST_STATE_RINGING:
05286                dahdi_enable_ec(p);
05287                dahdi_train_ec(p);
05288                p->subs[index].f.frametype = AST_FRAME_CONTROL;
05289                p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05290                /* Make sure it stops ringing */
05291                dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05292                ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
05293                if (p->cidspill) {
05294                   /* Cancel any running CallerID spill */
05295                   free(p->cidspill);
05296                   p->cidspill = NULL;
05297                }
05298                p->dialing = 0;
05299                p->callwaitcas = 0;
05300                if (p->confirmanswer) {
05301                   /* Ignore answer if "confirm answer" is enabled */
05302                   p->subs[index].f.frametype = AST_FRAME_NULL;
05303                   p->subs[index].f.subclass = 0;
05304                } else if (!ast_strlen_zero(p->dop.dialstr)) {
05305                   /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
05306                   res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05307                   if (res < 0) {
05308                      ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05309                      p->dop.dialstr[0] = '\0';
05310                      return NULL;
05311                   } else {
05312                      ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
05313                      p->subs[index].f.frametype = AST_FRAME_NULL;
05314                      p->subs[index].f.subclass = 0;
05315                      p->dialing = 1;
05316                   }
05317                   p->dop.dialstr[0] = '\0';
05318                   ast_setstate(ast, AST_STATE_DIALING);
05319                } else
05320                   ast_setstate(ast, AST_STATE_UP);
05321                return &p->subs[index].f;
05322             case AST_STATE_DOWN:
05323                ast_setstate(ast, AST_STATE_RING);
05324                ast->rings = 1;
05325                p->subs[index].f.frametype = AST_FRAME_CONTROL;
05326                p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
05327                ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
05328                return &p->subs[index].f;
05329             case AST_STATE_UP:
05330                /* Make sure it stops ringing */
05331                dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05332                /* Okay -- probably call waiting*/
05333                if (ast_bridged_channel(p->owner))
05334                   ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05335                p->subs[index].needunhold = 1;
05336                break;
05337             case AST_STATE_RESERVED:
05338                /* Start up dialtone */
05339                if (has_voicemail(p))
05340                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
05341                else
05342                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
05343                break;
05344             default:
05345                ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
05346             }
05347             break;
05348          case SIG_FXSLS:
05349          case SIG_FXSGS:
05350          case SIG_FXSKS:
05351             if (ast->_state == AST_STATE_RING) {
05352                p->ringt = p->ringt_base;
05353             }
05354 
05355             /* Fall through */
05356          case SIG_EM:
05357          case SIG_EM_E1:
05358          case SIG_EMWINK:
05359          case SIG_FEATD:
05360          case SIG_FEATDMF:
05361          case SIG_FEATDMF_TA:
05362          case SIG_E911:
05363          case SIG_FGC_CAMA:
05364          case SIG_FGC_CAMAMF:
05365          case SIG_FEATB:
05366          case SIG_SF:
05367          case SIG_SFWINK:
05368          case SIG_SF_FEATD:
05369          case SIG_SF_FEATDMF:
05370          case SIG_SF_FEATB:
05371             if (ast->_state == AST_STATE_PRERING)
05372                ast_setstate(ast, AST_STATE_RING);
05373             if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
05374                if (option_debug)
05375                   ast_log(LOG_DEBUG, "Ring detected\n");
05376                p->subs[index].f.frametype = AST_FRAME_CONTROL;
05377                p->subs[index].f.subclass = AST_CONTROL_RING;
05378             } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
05379                if (option_debug)
05380                   ast_log(LOG_DEBUG, "Line answered\n");
05381                if (p->confirmanswer) {
05382                   p->subs[index].f.frametype = AST_FRAME_NULL;
05383                   p->subs[index].f.subclass = 0;
05384                } else {
05385                   p->subs[index].f.frametype = AST_FRAME_CONTROL;
05386                   p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05387                   ast_setstate(ast, AST_STATE_UP);
05388                }
05389             } else if (ast->_state != AST_STATE_RING)
05390                ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
05391             break;
05392          default:
05393             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05394          }
05395          break;
05396 #ifdef DAHDI_EVENT_RINGBEGIN
05397       case DAHDI_EVENT_RINGBEGIN:
05398          switch (p->sig) {
05399          case SIG_FXSLS:
05400          case SIG_FXSGS:
05401          case SIG_FXSKS:
05402             if (ast->_state == AST_STATE_RING) {
05403                p->ringt = p->ringt_base;
05404             }
05405             break;
05406          }
05407          break;
05408 #endif         
05409       case DAHDI_EVENT_RINGEROFF:
05410          if (p->inalarm) break;
05411          if ((p->radio || (p->oprmode < 0))) break;
05412          ast->rings++;
05413          if ((ast->rings > p->cidrings) && (p->cidspill)) {
05414             ast_log(LOG_WARNING, "Didn't finish Caller-ID spill.  Cancelling.\n");
05415             free(p->cidspill);
05416             p->cidspill = NULL;
05417             p->callwaitcas = 0;
05418          }
05419          p->subs[index].f.frametype = AST_FRAME_CONTROL;
05420          p->subs[index].f.subclass = AST_CONTROL_RINGING;
05421          break;
05422       case DAHDI_EVENT_RINGERON:
05423          break;
05424       case DAHDI_EVENT_NOALARM:
05425          p->inalarm = 0;
05426 #ifdef HAVE_PRI
05427          /* Extremely unlikely but just in case */
05428          if (p->bearer)
05429             p->bearer->inalarm = 0;
05430 #endif            
05431          if (!p->unknown_alarm) {
05432             ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
05433             manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
05434                "Channel: %d\r\n", p->channel);
05435          } else {
05436             p->unknown_alarm = 0;
05437          }
05438          break;
05439       case DAHDI_EVENT_WINKFLASH:
05440          if (p->inalarm) break;
05441          if (p->radio) break;
05442          if (p->oprmode < 0) break;
05443          if (p->oprmode > 1)
05444          {
05445             struct dahdi_params par;
05446 
05447             memset(&par, 0, sizeof(par));
05448             if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
05449             {
05450                if (!par.rxisoffhook)
05451                {
05452                   /* Make sure it stops ringing */
05453                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05454                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
05455                   save_conference(p);
05456                   tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05457                }
05458             }
05459             break;
05460          }
05461          /* Remember last time we got a flash-hook */
05462          gettimeofday(&p->flashtime, NULL);
05463          switch (mysig) {
05464          case SIG_FXOLS:
05465          case SIG_FXOGS:
05466          case SIG_FXOKS:
05467             ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
05468                index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
05469             p->callwaitcas = 0;
05470 
05471             if (index != SUB_REAL) {
05472                ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
05473                goto winkflashdone;
05474             }
05475             
05476             if (p->subs[SUB_CALLWAIT].owner) {
05477                /* Swap to call-wait */
05478                swap_subs(p, SUB_REAL, SUB_CALLWAIT);
05479                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
05480                p->owner = p->subs[SUB_REAL].owner;
05481                ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
05482                if (p->owner->_state == AST_STATE_RINGING) {
05483                   ast_setstate(p->owner, AST_STATE_UP);
05484                   p->subs[SUB_REAL].needanswer = 1;
05485                }
05486                p->callwaitingrepeat = 0;
05487                p->cidcwexpire = 0;
05488                /* Start music on hold if appropriate */
05489                if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
05490                   ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
05491                      S_OR(p->mohsuggest, NULL),
05492                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05493                }
05494                p->subs[SUB_CALLWAIT].needhold = 1;
05495                if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05496                   ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
05497                      S_OR(p->mohsuggest, NULL),
05498                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05499                }
05500                p->subs[SUB_REAL].needunhold = 1;
05501             } else if (!p->subs[SUB_THREEWAY].owner) {
05502                if (!p->threewaycalling) {
05503                   /* Just send a flash if no 3-way calling */
05504                   p->subs[SUB_REAL].needflash = 1;
05505                   goto winkflashdone;
05506                } else if (!check_for_conference(p)) {
05507                   char cid_num[256];
05508                   char cid_name[256];
05509 
05510                   cid_num[0] = 0;
05511                   cid_name[0] = 0;
05512                   if (p->dahditrcallerid && p->owner) {
05513                      if (p->owner->cid.cid_num)
05514                         ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
05515                      if (p->owner->cid.cid_name)
05516                         ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
05517                   }
05518                   /* XXX This section needs much more error checking!!! XXX */
05519                   /* Start a 3-way call if feasible */
05520                   if (!((ast->pbx) ||
05521                         (ast->_state == AST_STATE_UP) ||
05522                         (ast->_state == AST_STATE_RING))) {
05523                      ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
05524                         goto winkflashdone;
05525                   }
05526                   if (alloc_sub(p, SUB_THREEWAY)) {
05527                      ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
05528                      goto winkflashdone;
05529                   }
05530                   /* Make new channel */
05531                   chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
05532                   if (p->dahditrcallerid) {
05533                      if (!p->origcid_num)
05534                         p->origcid_num = ast_strdup(p->cid_num);
05535                      if (!p->origcid_name)
05536                         p->origcid_name = ast_strdup(p->cid_name);
05537                      ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
05538                      ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
05539                   }
05540                   /* Swap things around between the three-way and real call */
05541                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
05542                   /* Disable echo canceller for better dialing */
05543                   dahdi_disable_ec(p);
05544                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
05545                   if (res)
05546                      ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
05547                   p->owner = chan;
05548                   pthread_attr_init(&attr);
05549                   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05550                   if (!chan) {
05551                      ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
05552                   } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
05553                      ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
05554                      res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
05555                      dahdi_enable_ec(p);
05556                      ast_hangup(chan);
05557                   } else {
05558                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05559                      int way3bridge = 0, cdr3way = 0;
05560                      
05561                      if (!other) {
05562                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05563                      } else
05564                         way3bridge = 1;
05565                      
05566                      if (p->subs[SUB_THREEWAY].owner->cdr)
05567                         cdr3way = 1;
05568                      
05569                      if (option_verbose > 2) 
05570                         ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
05571                      /* Start music on hold if appropriate */
05572                      if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05573                         ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
05574                            S_OR(p->mohsuggest, NULL),
05575                            !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05576                      }
05577                      p->subs[SUB_THREEWAY].needhold = 1;
05578                   }
05579                   pthread_attr_destroy(&attr);
05580                }
05581             } else {
05582                /* Already have a 3 way call */
05583                if (p->subs[SUB_THREEWAY].inthreeway) {
05584                   /* Call is already up, drop the last person */
05585                   if (option_debug)
05586                      ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
05587                   /* If the primary call isn't answered yet, use it */
05588                   if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
05589                      /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
05590                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
05591                      p->owner = p->subs[SUB_REAL].owner;
05592                   }
05593                   /* Drop the last call and stop the conference */
05594                   if (option_verbose > 2)
05595                      ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
05596                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05597                   p->subs[SUB_REAL].inthreeway = 0;
05598                   p->subs[SUB_THREEWAY].inthreeway = 0;
05599                } else {
05600                   /* Lets see what we're up to */
05601                   if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 
05602                       (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
05603                      int otherindex = SUB_THREEWAY;
05604                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05605                      int way3bridge = 0, cdr3way = 0;
05606                      
05607                      if (!other) {
05608                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05609                      } else
05610                         way3bridge = 1;
05611                      
05612                      if (p->subs[SUB_THREEWAY].owner->cdr)
05613                         cdr3way = 1;
05614 
05615                      if (option_verbose > 2)
05616                         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);
05617                      /* Put them in the threeway, and flip */
05618                      p->subs[SUB_THREEWAY].inthreeway = 1;
05619                      p->subs[SUB_REAL].inthreeway = 1;
05620                      if (ast->_state == AST_STATE_UP) {
05621                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
05622                         otherindex = SUB_REAL;
05623                      }
05624                      if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
05625                         ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
05626                      p->subs[otherindex].needunhold = 1;
05627                      p->owner = p->subs[SUB_REAL].owner;
05628                      if (ast->_state == AST_STATE_RINGING) {
05629                         ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
05630                         res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05631                         res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05632                      }
05633                   } else {
05634                      if (option_verbose > 2)
05635                         ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
05636                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
05637                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05638                      p->owner = p->subs[SUB_REAL].owner;
05639                      if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
05640                         ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05641                      p->subs[SUB_REAL].needunhold = 1;
05642                      dahdi_enable_ec(p);
05643                   }
05644                      
05645                }
05646             }
05647          winkflashdone:              
05648             update_conf(p);
05649             break;
05650          case SIG_EM:
05651          case SIG_EM_E1:
05652          case SIG_FEATD:
05653          case SIG_SF:
05654          case SIG_SFWINK:
05655          case SIG_SF_FEATD:
05656          case SIG_FXSLS:
05657          case SIG_FXSGS:
05658             if (p->dialing)
05659                ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
05660             else
05661                ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
05662             break;
05663          case SIG_FEATDMF_TA:
05664             switch (p->whichwink) {
05665             case 0:
05666                ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05667                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05668                break;
05669             case 1:
05670                ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
05671                break;
05672             case 2:
05673                ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
05674                return NULL;
05675             }
05676             p->whichwink++;
05677             /* Fall through */
05678          case SIG_FEATDMF:
05679          case SIG_E911:
05680          case SIG_FGC_CAMAMF:
05681          case SIG_FGC_CAMA:
05682          case SIG_FEATB:
05683          case SIG_SF_FEATDMF:
05684          case SIG_SF_FEATB:
05685          case SIG_EMWINK:
05686             /* FGD MF and EMWINK *Must* wait for wink */
05687             if (!ast_strlen_zero(p->dop.dialstr)) {
05688                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05689                if (res < 0) {
05690                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05691                   p->dop.dialstr[0] = '\0';
05692                   return NULL;
05693                } else 
05694                   ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
05695             }
05696             p->dop.dialstr[0] = '\0';
05697             break;
05698          default:
05699             ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
05700          }
05701          break;
05702       case DAHDI_EVENT_HOOKCOMPLETE:
05703          if (p->inalarm) break;
05704          if ((p->radio || (p->oprmode < 0))) break;
05705          switch (mysig) {
05706          case SIG_FXSLS:  /* only interesting for FXS */
05707          case SIG_FXSGS:
05708          case SIG_FXSKS:
05709          case SIG_EM:
05710          case SIG_EM_E1:
05711          case SIG_EMWINK:
05712          case SIG_FEATD:
05713          case SIG_SF:
05714          case SIG_SFWINK:
05715          case SIG_SF_FEATD:
05716             if (!ast_strlen_zero(p->dop.dialstr)) {
05717                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05718                if (res < 0) {
05719                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05720                   p->dop.dialstr[0] = '\0';
05721                   return NULL;
05722                } else 
05723                   ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
05724             }
05725             p->dop.dialstr[0] = '\0';
05726             p->dop.op = DAHDI_DIAL_OP_REPLACE;
05727             break;
05728          case SIG_FEATDMF:
05729          case SIG_FEATDMF_TA:
05730          case SIG_E911:
05731          case SIG_FGC_CAMA:
05732          case SIG_FGC_CAMAMF:
05733          case SIG_FEATB:
05734          case SIG_SF_FEATDMF:
05735          case SIG_SF_FEATB:
05736             ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
05737             break;
05738          default:
05739             break;
05740          }
05741          break;
05742       case DAHDI_EVENT_POLARITY:
05743          /*
05744           * If we get a Polarity Switch event, check to see
05745           * if we should change the polarity state and
05746           * mark the channel as UP or if this is an indication
05747           * of remote end disconnect.
05748           */
05749          if (p->polarity == POLARITY_IDLE) {
05750             p->polarity = POLARITY_REV;
05751             if (p->answeronpolarityswitch &&
05752                 ((ast->_state == AST_STATE_DIALING) ||
05753                 (ast->_state == AST_STATE_RINGING))) {
05754                ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
05755                ast_setstate(p->owner, AST_STATE_UP);
05756                if (p->hanguponpolarityswitch) {
05757                   gettimeofday(&p->polaritydelaytv, NULL);
05758                }
05759             } else
05760                ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
05761          } 
05762          /* Removed else statement from here as it was preventing hangups from ever happening*/
05763          /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
05764          if (p->hanguponpolarityswitch &&
05765             (p->polarityonanswerdelay > 0) &&
05766                 (p->polarity == POLARITY_REV) &&
05767             ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
05768                                 /* Added log_debug information below to provide a better indication of what is going on */
05769             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) );
05770          
05771             if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
05772                ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
05773                ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
05774                p->polarity = POLARITY_IDLE;
05775             } else {
05776                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);
05777             }
05778          } else {
05779             p->polarity = POLARITY_IDLE;
05780             ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
05781          }
05782                         /* Added more log_debug information below to provide a better indication of what is going on */
05783          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) );
05784          break;
05785       default:
05786          ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
05787    }
05788    return &p->subs[index].f;
05789 }

static int dahdi_hangup ( struct ast_channel ast  )  [static]

Definition at line 3590 of file chan_dahdi.c.

References ast_channel::_state, dahdi_pvt::alerting, dahdi_pvt::alreadyhungup, ast_bridged_channel(), ast_channel_setoption(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_copy_string(), 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::bearer, dahdi_pvt::call, 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_ast_cause_to_r2_cause(), dahdi_confmute(), dahdi_disable_ec(), dahdi_get_index(), dahdi_r2_disconnect_call(), 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, iflock, dahdi_pvt::ignoredtmf, dahdi_subchannel::inthreeway, dahdi_pvt::law, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_forced_release, dahdi_pvt::mfcr2call, dahdi_pvt::mohsuggest, ast_channel::name, 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_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, dahdi_pvt::progress, dahdi_pvt::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::rdnis, dahdi_pvt::realcall, reset_conf(), restart_monitor(), dahdi_pvt::restartpending, restore_gains(), dahdi_pvt::ringt, S_OR, dahdi_pvt::setup_ack, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, 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.

Referenced by pri_dchannel().

03591 {
03592    int res;
03593    int index,x, law;
03594    /*static int restore_gains(struct dahdi_pvt *p);*/
03595    struct dahdi_pvt *p = ast->tech_pvt;
03596    struct dahdi_pvt *tmp = NULL;
03597    struct dahdi_pvt *prev = NULL;
03598    struct dahdi_params par;
03599 
03600    if (option_debug)
03601       ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
03602    if (!ast->tech_pvt) {
03603       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
03604       return 0;
03605    }
03606    
03607    ast_mutex_lock(&p->lock);
03608    
03609    index = dahdi_get_index(ast, p, 1);
03610 
03611    if (p->sig == SIG_PRI) {
03612       x = 1;
03613       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03614       p->cid_num[0] = '\0';
03615       p->cid_name[0] = '\0';
03616    }
03617 
03618    x = 0;
03619    dahdi_confmute(p, 0);
03620    restore_gains(p);
03621    if (p->origcid_num) {
03622       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
03623       free(p->origcid_num);
03624       p->origcid_num = NULL;
03625    }  
03626    if (p->origcid_name) {
03627       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
03628       free(p->origcid_name);
03629       p->origcid_name = NULL;
03630    }  
03631    if (p->dsp)
03632       ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
03633    p->exten[0] = '\0';
03634 
03635    if (option_debug)
03636       ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
03637       p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
03638    p->ignoredtmf = 0;
03639    
03640    if (index > -1) {
03641       /* Real channel, do some fixup */
03642       p->subs[index].owner = NULL;
03643       p->subs[index].needanswer = 0;
03644       p->subs[index].needflash = 0;
03645       p->subs[index].needringing = 0;
03646       p->subs[index].needbusy = 0;
03647       p->subs[index].needcongestion = 0;
03648       p->subs[index].linear = 0;
03649       p->subs[index].needcallerid = 0;
03650       p->polarity = POLARITY_IDLE;
03651       dahdi_setlinear(p->subs[index].dfd, 0);
03652       if (index == SUB_REAL) {
03653          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
03654             ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
03655             if (p->subs[SUB_CALLWAIT].inthreeway) {
03656                /* We had flipped over to answer a callwait and now it's gone */
03657                ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
03658                /* Move to the call-wait, but un-own us until they flip back. */
03659                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03660                unalloc_sub(p, SUB_CALLWAIT);
03661                p->owner = NULL;
03662             } else {
03663                /* The three way hung up, but we still have a call wait */
03664                ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
03665                swap_subs(p, SUB_THREEWAY, SUB_REAL);
03666                unalloc_sub(p, SUB_THREEWAY);
03667                if (p->subs[SUB_REAL].inthreeway) {
03668                   /* This was part of a three way call.  Immediately make way for
03669                      another call */
03670                   ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
03671                   p->owner = p->subs[SUB_REAL].owner;
03672                } else {
03673                   /* This call hasn't been completed yet...  Set owner to NULL */
03674                   ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
03675                   p->owner = NULL;
03676                }
03677                p->subs[SUB_REAL].inthreeway = 0;
03678             }
03679          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
03680             /* Move to the call-wait and switch back to them. */
03681             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03682             unalloc_sub(p, SUB_CALLWAIT);
03683             p->owner = p->subs[SUB_REAL].owner;
03684             if (p->owner->_state != AST_STATE_UP)
03685                p->subs[SUB_REAL].needanswer = 1;
03686             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
03687                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03688          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
03689             swap_subs(p, SUB_THREEWAY, SUB_REAL);
03690             unalloc_sub(p, SUB_THREEWAY);
03691             if (p->subs[SUB_REAL].inthreeway) {
03692                /* This was part of a three way call.  Immediately make way for
03693                   another call */
03694                ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
03695                p->owner = p->subs[SUB_REAL].owner;
03696             } else {
03697                /* This call hasn't been completed yet...  Set owner to NULL */
03698                ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
03699                p->owner = NULL;
03700             }
03701             p->subs[SUB_REAL].inthreeway = 0;
03702          }
03703       } else if (index == SUB_CALLWAIT) {
03704          /* Ditch the holding callwait call, and immediately make it availabe */
03705          if (p->subs[SUB_CALLWAIT].inthreeway) {
03706             /* This is actually part of a three way, placed on hold.  Place the third part
03707                on music on hold now */
03708             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03709                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 
03710                   S_OR(p->mohsuggest, NULL),
03711                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03712             }
03713             p->subs[SUB_THREEWAY].inthreeway = 0;
03714             /* Make it the call wait now */
03715             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
03716             unalloc_sub(p, SUB_THREEWAY);
03717          } else
03718             unalloc_sub(p, SUB_CALLWAIT);
03719       } else if (index == SUB_THREEWAY) {
03720          if (p->subs[SUB_CALLWAIT].inthreeway) {
03721             /* The other party of the three way call is currently in a call-wait state.
03722                Start music on hold for them, and take the main guy out of the third call */
03723             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
03724                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 
03725                   S_OR(p->mohsuggest, NULL),
03726                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03727             }
03728             p->subs[SUB_CALLWAIT].inthreeway = 0;
03729          }
03730          p->subs[SUB_REAL].inthreeway = 0;
03731          /* If this was part of a three way call index, let us make
03732             another three way call */
03733          unalloc_sub(p, SUB_THREEWAY);
03734       } else {
03735          /* This wasn't any sort of call, but how are we an index? */
03736          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
03737       }
03738    }
03739 
03740    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
03741       p->owner = NULL;
03742       p->ringt = 0;
03743       p->distinctivering = 0;
03744       p->confirmanswer = 0;
03745       p->cidrings = 1;
03746       p->outgoing = 0;
03747       p->digital = 0;
03748       p->faxhandled = 0;
03749       p->pulsedial = 0;
03750       p->onhooktime = time(NULL);
03751 #ifdef HAVE_PRI
03752       p->proceeding = 0;
03753       p->dialing = 0;
03754       p->progress = 0;
03755       p->alerting = 0;
03756       p->setup_ack = 0;
03757 #endif      
03758       if (p->dsp) {
03759          ast_dsp_free(p->dsp);
03760          p->dsp = NULL;
03761       }
03762 
03763       law = DAHDI_LAW_DEFAULT;
03764       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
03765       if (res < 0) 
03766          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
03767       /* Perform low level hangup if no owner left */
03768 #ifdef HAVE_OPENR2
03769       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
03770          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
03771          ast_log(LOG_DEBUG, "ast->hangupcause is %d\n", ast->hangupcause);
03772          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
03773             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
03774          } else {
03775             const char *r2causestr = pbx_builtin_getvar_helper(ast,"MFCR2_CAUSE");
03776             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
03777             openr2_call_disconnect_cause_t r2cause = r2cause_user
03778                                ? dahdi_ast_cause_to_r2_cause(r2cause_user)
03779                                : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
03780             dahdi_r2_disconnect_call(p, r2cause);
03781          }
03782       } else if (p->mfcr2call) {
03783          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
03784          p->mfcr2call = 0;
03785       }
03786 #endif
03787 #ifdef HAVE_PRI
03788       if (p->pri) {
03789 #ifdef SUPPORT_USERUSER
03790          const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
03791 #endif
03792 
03793          /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
03794          if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
03795             if (!pri_grab(p, p->pri)) {
03796                if (p->alreadyhungup) {
03797                   ast_log(LOG_DEBUG, "Already hungup...  Calling hangup once, and clearing call\n");
03798 
03799 #ifdef SUPPORT_USERUSER
03800                   pri_call_set_useruser(p->call, useruser);
03801 #endif
03802 
03803                   pri_hangup(p->pri->pri, p->call, -1);
03804                   p->call = NULL;
03805                   if (p->bearer) 
03806                      p->bearer->call = NULL;
03807                } else {
03808                   const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
03809                   int icause = ast->hangupcause ? ast->hangupcause : -1;
03810                   ast_log(LOG_DEBUG, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
03811 
03812 #ifdef SUPPORT_USERUSER
03813                   pri_call_set_useruser(p->call, useruser);
03814 #endif
03815 
03816                   p->alreadyhungup = 1;
03817                   if (p->bearer)
03818                      p->bearer->alreadyhungup = 1;
03819                   if (cause) {
03820                      if (atoi(cause))
03821                         icause = atoi(cause);
03822                   }
03823                   pri_hangup(p->pri->pri, p->call, icause);
03824                }
03825                if (res < 0) 
03826                   ast_log(LOG_WARNING, "pri_disconnect failed\n");
03827                pri_rel(p->pri);        
03828             } else {
03829                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03830                res = -1;
03831             }
03832          } else {
03833             if (p->bearer)
03834                ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
03835             p->call = NULL;
03836             res = 0;
03837          }
03838       }
03839 #endif
03840       if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_MFCR2))
03841          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
03842       if (res < 0) {
03843          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
03844       }
03845       switch (p->sig) {
03846       case SIG_FXOGS:
03847       case SIG_FXOLS:
03848       case SIG_FXOKS:
03849          memset(&par, 0, sizeof(par));
03850          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
03851          if (!res) {
03852 #if 0
03853             ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
03854 #endif
03855             /* If they're off hook, try playing congestion */
03856             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
03857                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
03858             else
03859                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03860          }
03861          break;
03862       case SIG_FXSGS:
03863       case SIG_FXSLS:
03864       case SIG_FXSKS:
03865          /* Make sure we're not made available for at least two seconds assuming
03866             we were actually used for an inbound or outbound call. */
03867          if (ast->_state != AST_STATE_RESERVED) {
03868             time(&p->guardtime);
03869             p->guardtime += 2;
03870          }
03871          break;
03872       default:
03873          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03874       }
03875       if (p->cidspill)
03876          free(p->cidspill);
03877       if (p->sig)
03878          dahdi_disable_ec(p);
03879       x = 0;
03880       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
03881       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
03882       p->didtdd = 0;
03883       p->cidspill = NULL;
03884       p->callwaitcas = 0;
03885       p->callwaiting = p->permcallwaiting;
03886       p->hidecallerid = p->permhidecallerid;
03887       p->dialing = 0;
03888       p->rdnis[0] = '\0';
03889       update_conf(p);
03890       reset_conf(p);
03891       /* Restore data mode */
03892       if (p->sig == SIG_PRI) {
03893          x = 0;
03894          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03895       }
03896 #ifdef HAVE_PRI
03897       if (p->bearer) {
03898          ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
03899          /* Free up the bearer channel as well, and
03900             don't use its file descriptor anymore */
03901          update_conf(p->bearer);
03902          reset_conf(p->bearer);
03903          p->bearer->owner = NULL;
03904          p->bearer->realcall = NULL;
03905          p->bearer = NULL;
03906          p->subs[SUB_REAL].dfd = -1;
03907          p->pri = NULL;
03908       }
03909 #endif
03910       if (num_restart_pending == 0)
03911          restart_monitor();
03912    }
03913 
03914    p->callwaitingrepeat = 0;
03915    p->cidcwexpire = 0;
03916    p->oprmode = 0;
03917    ast->tech_pvt = NULL;
03918    ast_mutex_unlock(&p->lock);
03919    ast_module_unref(ast_module_info->self);
03920    if (option_verbose > 2) 
03921       ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
03922 
03923    ast_mutex_lock(&iflock);
03924 
03925    if (p->restartpending) {
03926       num_restart_pending--;
03927    }
03928 
03929    tmp = iflist;
03930    prev = NULL;
03931    if (p->destroy) {
03932       while (tmp) {
03933          if (tmp == p) {
03934             destroy_channel(prev, tmp, 0);
03935             break;
03936          } else {
03937             prev = tmp;
03938             tmp = tmp->next;
03939          }
03940       }
03941    }
03942    ast_mutex_unlock(&iflock);
03943    return 0;
03944 }

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

Definition at line 6335 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, dahdi_pvt::alerting, 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_pvt::call, dahdi_get_index(), dahdi_set_hook(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::digital, dahdi_pvt::dop, errno, ast_channel::hangupcause, ISTRUNK, dahdi_pvt::lock, LOG_DEBUG, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_call_accepted, dahdi_pvt::mohinterpret, ast_channel::name, dahdi_pvt::outgoing, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::priindication_oob, dahdi_pvt::prioffset, dahdi_pvt::proceeding, dahdi_pvt::progress, PVT_TO_CHANNEL, 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.

06336 {
06337    struct dahdi_pvt *p = chan->tech_pvt;
06338    int res=-1;
06339    int index;
06340    int func = DAHDI_FLASH;
06341    ast_mutex_lock(&p->lock);
06342    index = dahdi_get_index(chan, p, 0);
06343    ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
06344 #ifdef HAVE_OPENR2
06345    if (p->mfcr2 && !p->mfcr2_call_accepted) {
06346       ast_mutex_unlock(&p->lock);
06347       /* if this an R2 call and the call is not yet accepted we don't want the 
06348          tone indications to mess up with the MF tones */
06349       return 0;
06350    }
06351 #endif
06352    if (index == SUB_REAL) {
06353       switch (condition) {
06354       case AST_CONTROL_BUSY:
06355 #ifdef HAVE_PRI
06356          if (p->priindication_oob && p->sig == SIG_PRI) {
06357             chan->hangupcause = AST_CAUSE_USER_BUSY;
06358             chan->_softhangup |= AST_SOFTHANGUP_DEV;
06359             res = 0;
06360          } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06361             if (p->pri->pri) {      
06362                if (!pri_grab(p, p->pri)) {
06363                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06364                   pri_rel(p->pri);
06365                }
06366                else
06367                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06368             }
06369             p->progress = 1;
06370             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06371          } else
06372 #endif
06373             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06374          break;
06375       case AST_CONTROL_RINGING:
06376 #ifdef HAVE_PRI
06377          if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06378             if (p->pri->pri) {      
06379                if (!pri_grab(p, p->pri)) {
06380                   pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06381                   pri_rel(p->pri);
06382                }
06383                else
06384                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06385             }
06386             p->alerting = 1;
06387          }
06388 #endif
06389          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
06390          if (chan->_state != AST_STATE_UP) {
06391             if ((chan->_state != AST_STATE_RING) ||
06392                ((p->sig != SIG_FXSKS) &&
06393                 (p->sig != SIG_FXSLS) &&
06394                 (p->sig != SIG_FXSGS)))
06395                ast_setstate(chan, AST_STATE_RINGING);
06396          }
06397          break;
06398       case AST_CONTROL_PROCEEDING:
06399          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
06400 #ifdef HAVE_PRI
06401          if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06402             if (p->pri->pri) {      
06403                if (!pri_grab(p, p->pri)) {
06404                   pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06405                   pri_rel(p->pri);
06406                }
06407                else
06408                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06409             }
06410             p->proceeding = 1;
06411             p->dialing = 0;
06412          }
06413 #endif
06414          /* don't continue in ast_indicate */
06415          res = 0;
06416          break;
06417       case AST_CONTROL_PROGRESS:
06418          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
06419 #ifdef HAVE_PRI
06420          p->digital = 0;   /* Digital-only calls isn't allows any inband progress messages */
06421          if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06422             if (p->pri->pri) {      
06423                if (!pri_grab(p, p->pri)) {
06424                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06425                   pri_rel(p->pri);
06426                }
06427                else
06428                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06429             }
06430             p->progress = 1;
06431          }
06432 #endif
06433          /* don't continue in ast_indicate */
06434          res = 0;
06435          break;
06436       case AST_CONTROL_CONGESTION:
06437          chan->hangupcause = AST_CAUSE_CONGESTION;
06438 #ifdef HAVE_PRI
06439          if (p->priindication_oob && p->sig == SIG_PRI) {
06440             chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
06441             chan->_softhangup |= AST_SOFTHANGUP_DEV;
06442             res = 0;
06443          } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06444             if (p->pri) {     
06445                if (!pri_grab(p, p->pri)) {
06446                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06447                   pri_rel(p->pri);
06448                } else
06449                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06450             }
06451             p->progress = 1;
06452             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06453          } else
06454 #endif
06455             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06456          break;
06457       case AST_CONTROL_HOLD:
06458 #ifdef HAVE_PRI
06459          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06460             if (!pri_grab(p, p->pri)) {
06461                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
06462                pri_rel(p->pri);
06463             } else
06464                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
06465          } else
06466 #endif
06467             ast_moh_start(chan, data, p->mohinterpret);
06468          break;
06469       case AST_CONTROL_UNHOLD:
06470 #ifdef HAVE_PRI
06471          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06472             if (!pri_grab(p, p->pri)) {
06473                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
06474                pri_rel(p->pri);
06475             } else
06476                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
06477          } else
06478 #endif
06479             ast_moh_stop(chan);
06480          break;
06481       case AST_CONTROL_RADIO_KEY:
06482          if (p->radio) 
06483              res =  dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
06484          res = 0;
06485          break;
06486       case AST_CONTROL_RADIO_UNKEY:
06487          if (p->radio)
06488              res =  dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
06489          res = 0;
06490          break;
06491       case AST_CONTROL_FLASH:
06492          /* flash hookswitch */
06493          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
06494             /* Clear out the dial buffer */
06495             p->dop.dialstr[0] = '\0';
06496             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06497                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
06498                   chan->name, strerror(errno));
06499             } else
06500                res = 0;
06501          } else
06502             res = 0;
06503          break;
06504       case AST_CONTROL_SRCUPDATE:
06505          res = 0;
06506          break;
06507       case -1:
06508          res = tone_zone_play_tone(p->subs[index].dfd, -1);
06509          break;
06510       }
06511    } else
06512       res = 0;
06513    ast_mutex_unlock(&p->lock);
06514    return res;
06515 }

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

Definition at line 4311 of file chan_dahdi.c.

References ast_log(), LOG_WARNING, and master.

Referenced by dahdi_bridge().

04311                                                                           {
04312    int x;
04313    if (!slave || !master) {
04314       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
04315       return;
04316    }
04317    for (x = 0; x < MAX_SLAVES; x++) {
04318       if (!master->slaves[x]) {
04319          master->slaves[x] = slave;
04320          break;
04321       }
04322    }
04323    if (x >= MAX_SLAVES) {
04324       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
04325       master->slaves[MAX_SLAVES - 1] = slave;
04326    }
04327    if (slave->master) 
04328       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
04329    slave->master = master;
04330    
04331    ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
04332 }

static struct ast_channel * dahdi_new ( struct dahdi_pvt i,
int  state,
int  startpbx,
int  index,
int  law,
int  transfercapability 
) [static]

Definition at line 6517 of file chan_dahdi.c.

References accountcode, dahdi_pvt::accountcode, dahdi_pvt::adsi, ast_channel::adsicpe, dahdi_pvt::alreadyhungup, ast_channel::amaflags, dahdi_pvt::amaflags, AST_ADSI_UNAVAILABLE, ast_channel_alloc(), ast_copy_string(), 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_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::bearer, 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, dahdi_pvt::isidlecall, language, dahdi_pvt::language, dahdi_subchannel::linear, LOG_DEBUG, dahdi_pvt::mfcr2_recvd_category, dahdi_pvt::mfcr2call, ast_channel::name, ast_channel::nativeformats, NEED_MFDETECT, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::pickupgroup, ast_channel::pickupgroup, dahdi_pvt::pri, 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, dahdi_pri::trunkgroup, and ast_channel::writeformat.

Referenced by dahdi_handle_event(), dahdi_r2_on_call_accepted(), dahdi_r2_on_call_offered(), dahdi_request(), handle_init_event(), and register_translator().

06518 {
06519    struct ast_channel *tmp;
06520    int deflaw;
06521    int res;
06522    int x,y;
06523    int features;
06524    char *b2 = NULL;
06525    struct dahdi_params ps;
06526    char chanprefix[*dahdi_chan_name_len + 4];
06527 
06528    if (i->subs[index].owner) {
06529       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
06530       return NULL;
06531    }
06532    y = 1;
06533    do {
06534       if (b2)
06535          free(b2);
06536 #ifdef HAVE_PRI
06537       if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
06538          b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
06539       else
06540 #endif
06541       if (i->channel == CHAN_PSEUDO)
06542          b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
06543       else  
06544          b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
06545       for (x = 0; x < 3; x++) {
06546          if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6)))
06547             break;
06548       }
06549       y++;
06550    } while (x < 3);
06551    strcpy(chanprefix, dahdi_chan_name);
06552    strcat(chanprefix, "/%s");
06553    tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
06554    if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */
06555       free(b2);
06556    if (!tmp)
06557       return NULL;
06558    tmp->tech = chan_tech;
06559    memset(&ps, 0, sizeof(ps));
06560    ps.channo = i->channel;
06561    res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
06562    if (res) {
06563       ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
06564       ps.curlaw = DAHDI_LAW_MULAW;
06565    }
06566    if (ps.curlaw == DAHDI_LAW_ALAW)
06567       deflaw = AST_FORMAT_ALAW;
06568    else
06569       deflaw = AST_FORMAT_ULAW;
06570    if (law) {
06571       if (law == DAHDI_LAW_ALAW)
06572          deflaw = AST_FORMAT_ALAW;
06573       else
06574          deflaw = AST_FORMAT_ULAW;
06575    }
06576    tmp->fds[0] = i->subs[index].dfd;
06577    tmp->nativeformats = deflaw;
06578    /* Start out assuming ulaw since it's smaller :) */
06579    tmp->rawreadformat = deflaw;
06580    tmp->readformat = deflaw;
06581    tmp->rawwriteformat = deflaw;
06582    tmp->writeformat = deflaw;
06583    i->subs[index].linear = 0;
06584    dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
06585    features = 0;
06586    if (index == SUB_REAL) {
06587       if (i->busydetect && CANBUSYDETECT(i))
06588          features |= DSP_FEATURE_BUSY_DETECT;
06589       if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
06590          features |= DSP_FEATURE_CALL_PROGRESS;
06591       if ((!i->outgoing && (i->callprogress & 4)) || 
06592           (i->outgoing && (i->callprogress & 2))) {
06593          features |= DSP_FEATURE_FAX_DETECT;
06594       }
06595 #ifdef DAHDI_TONEDETECT
06596       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06597       if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
06598 #endif      
06599          i->hardwaredtmf = 0;
06600          features |= DSP_FEATURE_DTMF_DETECT;
06601 #ifdef DAHDI_TONEDETECT
06602       } else if (NEED_MFDETECT(i)) {
06603          i->hardwaredtmf = 1;
06604          features |= DSP_FEATURE_DTMF_DETECT;
06605       }
06606 #endif
06607    }
06608    if (features) {
06609       if (i->dsp) {
06610          ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
06611       } else {
06612          if (i->channel != CHAN_PSEUDO)
06613             i->dsp = ast_dsp_new();
06614          else
06615             i->dsp = NULL;
06616          if (i->dsp) {
06617             i->dsp_features = features;
06618 #ifdef HAVE_PRI
06619             /* We cannot do progress detection until receives PROGRESS message */
06620             if (i->outgoing && (i->sig == SIG_PRI)) {
06621                /* Remember requested DSP features, don't treat
06622                   talking as ANSWER */
06623                i->dsp_features = features & ~DSP_PROGRESS_TALK;
06624                features = 0;
06625             }
06626 #endif
06627             ast_dsp_set_features(i->dsp, features);
06628             ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
06629             if (!ast_strlen_zero(progzone))
06630                ast_dsp_set_call_progress_zone(i->dsp, progzone);
06631             if (i->busydetect && CANBUSYDETECT(i)) {
06632                if(i->silencethreshold > 0)
06633                   ast_dsp_set_threshold(i->dsp, i->silencethreshold);
06634                ast_dsp_set_busy_count(i->dsp, i->busycount);
06635                if(i->busytonelength > 0)
06636                   ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
06637                if((i->busytonelength == i->busyquietlength) && i->busycompare)
06638                   ast_dsp_set_busy_compare(i->dsp, i->busycompare);
06639             }
06640          }
06641       }
06642    }
06643       
06644    if (state == AST_STATE_RING)
06645       tmp->rings = 1;
06646    tmp->tech_pvt = i;
06647    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
06648       /* Only FXO signalled stuff can be picked up */
06649       tmp->callgroup = i->callgroup;
06650       tmp->pickupgroup = i->pickupgroup;
06651    }
06652    if (!ast_strlen_zero(i->language))
06653       ast_string_field_set(tmp, language, i->language);
06654    if (!i->owner)
06655       i->owner = tmp;
06656    if (!ast_strlen_zero(i->accountcode))
06657       ast_string_field_set(tmp, accountcode, i->accountcode);
06658    if (i->amaflags)
06659       tmp->amaflags = i->amaflags;
06660    i->subs[index].owner = tmp;
06661    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
06662    ast_string_field_set(tmp, call_forward, i->call_forward);
06663    /* If we've been told "no ADSI" then enforce it */
06664    if (!i->adsi)
06665       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
06666    if (!ast_strlen_zero(i->exten))
06667       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
06668    if (!ast_strlen_zero(i->rdnis))
06669       tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
06670    if (!ast_strlen_zero(i->dnid))
06671       tmp->cid.cid_dnid = ast_strdup(i->dnid);
06672 
06673    /* Don't use ast_set_callerid() here because it will
06674     * generate a needless NewCallerID event */
06675 #ifdef PRI_ANI
06676    if (!ast_strlen_zero(i->cid_ani))
06677       tmp->cid.cid_ani = ast_strdup(i->cid_ani);
06678    else  
06679       tmp->cid.cid_ani = ast_strdup(i->cid_num);
06680 #else
06681    tmp->cid.cid_ani = ast_strdup(i->cid_num);
06682 #endif
06683    tmp->cid.cid_pres = i->callingpres;
06684    tmp->cid.cid_ton = i->cid_ton;
06685 #ifdef HAVE_PRI
06686    tmp->transfercapability = transfercapability;
06687    pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
06688    if (transfercapability & PRI_TRANS_CAP_DIGITAL)
06689       i->digital = 1;
06690    /* Assume calls are not idle calls unless we're told differently */
06691    i->isidlecall = 0;
06692    i->alreadyhungup = 0;
06693 #endif
06694    /* clear the fake event in case we posted one before we had ast_channel */
06695    i->fake_event = 0;
06696    /* Assure there is no confmute on this channel */
06697    dahdi_confmute(i, 0);
06698    /* Configure the new channel jb */
06699    ast_jb_configure(tmp, &global_jbconf);
06700    if (startpbx) {
06701 #ifdef HAVE_OPENR2
06702       if (i->mfcr2call) {
06703          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
06704       }
06705 #endif
06706       if (ast_pbx_start(tmp)) {
06707          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
06708          ast_hangup(tmp);
06709          i->owner = NULL;
06710          return NULL;
06711       }
06712    }
06713 
06714    ast_module_ref(ast_module_info->self);
06715    
06716    return tmp;
06717 }

static int dahdi_open ( char *  fn  )  [static]

Definition at line 1800 of file chan_dahdi.c.

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

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

01801 {
01802    int fd;
01803    int isnum;
01804    int chan = 0;
01805    int bs;
01806    int x;
01807    isnum = 1;
01808    for (x = 0; x < strlen(fn); x++) {
01809       if (!isdigit(fn[x])) {
01810          isnum = 0;
01811          break;
01812       }
01813    }
01814    if (isnum) {
01815       chan = atoi(fn);
01816       if (chan < 1) {
01817          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
01818          return -1;
01819       }
01820       fn = DAHDI_FILE_CHANNEL;
01821    }
01822    fd = open(fn, O_RDWR | O_NONBLOCK);
01823    if (fd < 0) {
01824       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
01825       return -1;
01826    }
01827    if (chan) {
01828       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
01829          x = errno;
01830          close(fd);
01831          errno = x;
01832          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
01833          return -1;
01834       }
01835    }
01836    bs = READ_SIZE;
01837    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
01838       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
01839       x = errno;
01840       close(fd);
01841       errno = x;
01842       return -1;
01843    }
01844    return fd;
01845 }

static void dahdi_pri_error ( struct pri *  pri,
char *  s 
) [static]

Definition at line 9901 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), errno, LOG_ERROR, NUM_DCHANS, NUM_SPANS, pridebugfdlock, and pris.

Referenced by dahdi_restart(), and load_module().

09902 {
09903    int x, y;
09904    int dchan = -1, span = -1;
09905    int dchancount = 0;
09906 
09907    if (pri) {
09908       for (x = 0; x < NUM_SPANS; x++) {
09909          for (y = 0; y < NUM_DCHANS; y++) {
09910             if (pris[x].dchans[y])
09911                dchancount++;
09912 
09913             if (pris[x].dchans[y] == pri)
09914                dchan = y;
09915          }
09916          if (dchan >= 0) {
09917             span = x;
09918             break;
09919          }
09920          dchancount = 0;
09921       }
09922       if ((dchan >= 0) && (span >= 0)) {
09923          if (dchancount > 1)
09924             ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
09925          else
09926             ast_log(LOG_ERROR, "%s", s);
09927       } else
09928          ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
09929    } else
09930       ast_log(LOG_ERROR, "%s", s);
09931 
09932    ast_mutex_lock(&pridebugfdlock);
09933 
09934    if (pridebugfd >= 0) {
09935       if (write(pridebugfd, s, strlen(s)) < 0) {
09936          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
09937       }
09938    }
09939 
09940    ast_mutex_unlock(&pridebugfdlock);
09941 }

static void dahdi_pri_message ( struct pri *  pri,
char *  s 
) [static]

Definition at line 9859 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), errno, LOG_ERROR, NUM_DCHANS, NUM_SPANS, pridebugfdlock, and pris.

Referenced by dahdi_restart(), and load_module().

09860 {
09861    int x, y;
09862    int dchan = -1, span = -1;
09863    int dchancount = 0;
09864 
09865    if (pri) {
09866       for (x = 0; x < NUM_SPANS; x++) {
09867          for (y = 0; y < NUM_DCHANS; y++) {
09868             if (pris[x].dchans[y])
09869                dchancount++;
09870 
09871             if (pris[x].dchans[y] == pri)
09872                dchan = y;
09873          }
09874          if (dchan >= 0) {
09875             span = x;
09876             break;
09877          }
09878          dchancount = 0;
09879       }
09880       if ((dchan >= 0) && (span >= 0)) {
09881          if (dchancount > 1)
09882             ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
09883          else
09884             ast_verbose("%s", s);
09885       } else
09886          ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
09887    } else
09888       ast_verbose("%s", s);
09889 
09890    ast_mutex_lock(&pridebugfdlock);
09891 
09892    if (pridebugfd >= 0) {
09893       if (write(pridebugfd, s, strlen(s)) < 0) {
09894          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
09895       }
09896    }
09897 
09898    ast_mutex_unlock(&pridebugfdlock);
09899 }

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

Definition at line 1236 of file chan_dahdi.c.

References ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_frame(), DEADLOCK_AVOIDANCE, and f.

Referenced by __action_dialoffhook().

01240 {
01241    /* We must unlock the PRI to avoid the possibility of a deadlock */
01242 #ifdef HAVE_PRI
01243    if (pri)
01244       ast_mutex_unlock(&pri->lock);
01245 #endif      
01246    for (;;) {
01247       if (p->owner) {
01248          if (ast_mutex_trylock(&p->owner->lock)) {
01249             DEADLOCK_AVOIDANCE(&p->lock);
01250          } else {
01251             ast_queue_frame(p->owner, f);
01252             ast_mutex_unlock(&p->owner->lock);
01253             break;
01254          }
01255       } else
01256          break;
01257    }
01258 #ifdef HAVE_PRI
01259    if (pri)
01260       ast_mutex_lock(&pri->lock);
01261 #endif      
01262 }

static int16_t dahdi_r2_alaw_to_linear ( uint8_t  sample  )  [inline, static]

Definition at line 1753 of file chan_dahdi.c.

References AST_ALAW.

01754 {
01755    return AST_ALAW(sample);
01756 }

static int dahdi_r2_answer ( struct dahdi_pvt p  )  [static]

Definition at line 1298 of file chan_dahdi.c.

References ast_true(), dahdi_pvt::owner, pbx_builtin_getvar_helper(), and dahdi_pvt::r2chan.

Referenced by dahdi_answer(), and dahdi_r2_on_call_accepted().

01299 {
01300    int res = 0;
01301    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
01302     * and does not has support for openr2_chan_answer_call_with_mode
01303     *  */
01304 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01305    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
01306    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
01307    if (!double_answer) {
01308       /* this still can result in double answer if the channel context 
01309        * was configured that way */
01310       res = openr2_chan_answer_call(p->r2chan);
01311    } else if (wants_double_answer) {
01312       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
01313    } else {
01314       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
01315    } 
01316 #else
01317    res = openr2_chan_answer_call(p->r2chan);
01318 #endif
01319    return res;
01320 }

static void dahdi_r2_disconnect_call ( struct dahdi_pvt p,
openr2_call_disconnect_cause_t  cause 
) [static]

Definition at line 1411 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, dahdi_pvt::lock, LOG_NOTICE, dahdi_pvt::mfcr2call, and dahdi_pvt::r2chan.

Referenced by dahdi_hangup(), dahdi_r2_on_call_accepted(), dahdi_r2_on_call_disconnect(), and dahdi_r2_on_call_offered().

01412 {
01413    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
01414       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n", 
01415             p->channel, openr2_proto_get_disconnect_string(cause));
01416       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
01417       openr2_chan_set_idle(p->r2chan);
01418       ast_mutex_lock(&p->lock);
01419       p->mfcr2call = 0;
01420       ast_mutex_unlock(&p->lock);
01421    }
01422 }

static openr2_calling_party_category_t dahdi_r2_get_channel_category ( struct ast_channel c  )  [static]

Definition at line 1322 of file chan_dahdi.c.

References ast_log(), ast_strlen_zero(), LOG_DEBUG, LOG_WARNING, dahdi_pvt::mfcr2_category, ast_channel::name, pbx_builtin_getvar_helper(), and ast_channel::tech_pvt.

Referenced by dahdi_call().

01323 {
01324    openr2_calling_party_category_t cat;
01325    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
01326    struct dahdi_pvt *p = c->tech_pvt;
01327    if (ast_strlen_zero(catstr)) {
01328       ast_log(LOG_DEBUG, "no MFC/R2 category specified for chan %s, using default %s\n", 
01329             c->name, openr2_proto_get_category_string(p->mfcr2_category));
01330       return p->mfcr2_category;
01331    }
01332    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
01333       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
01334             catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
01335       return p->mfcr2_category;
01336    }
01337    ast_log(LOG_DEBUG, "Using category %s\n", catstr);
01338    return cat;
01339 }

static uint8_t dahdi_r2_linear_to_alaw ( int  sample  )  [inline, static]

Definition at line 1758 of file chan_dahdi.c.

References AST_LIN2A.

01759 {
01760    return AST_LIN2A(sample);
01761 }

static void dahdi_r2_on_ani_digit_received ( openr2_chan_t *  r2chan,
char  digit 
) [static]

Definition at line 1717 of file chan_dahdi.c.

References dahdi_pvt::cid_name, dahdi_pvt::cid_num, and dahdi_pvt::mfcr2_ani_index.

01718 {
01719    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01720    p->cid_num[p->mfcr2_ani_index] = digit;
01721    p->cid_name[p->mfcr2_ani_index] = digit;
01722    p->mfcr2_ani_index++;
01723    p->cid_num[p->mfcr2_ani_index] = 0;
01724    p->cid_name[p->mfcr2_ani_index] = 0;
01725 }

static void dahdi_r2_on_billing_pulse_received ( openr2_chan_t *  r2chan  )  [static]

Definition at line 1727 of file chan_dahdi.c.

References ast_log(), and LOG_NOTICE.

01728 {
01729    ast_log(LOG_NOTICE, "MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
01730 }

static void dahdi_r2_on_call_accepted ( openr2_chan_t *  r2chan,
openr2_call_mode_t  mode 
) [static]

Definition at line 1485 of file chan_dahdi.c.

References ast_log(), AST_STATE_RING, ast_verbose(), dahdi_pvt::channel, dahdi_enable_ec(), dahdi_new(), dahdi_r2_answer(), dahdi_r2_disconnect_call(), dahdi_pvt::dialing, LOG_ERROR, dahdi_pvt::mfcr2_accept_on_offer, dahdi_pvt::mfcr2_call_accepted, dahdi_subchannel::needringing, SUB_REAL, and dahdi_pvt::subs.

01486 {
01487    struct dahdi_pvt *p = NULL;
01488    struct ast_channel *c = NULL;
01489    p = openr2_chan_get_client_data(r2chan);
01490    dahdi_enable_ec(p);
01491    p->mfcr2_call_accepted = 1;
01492    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
01493       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
01494       /* if accept on offer is not set, it means at this point the PBX thread is already
01495          launched and therefore this callback is being executed in the PBX thread rather than
01496          the monitor thread, don't launch any other thread, just disable the R2 reading and
01497          answer the call */
01498       if (!p->mfcr2_accept_on_offer) {
01499          openr2_chan_disable_read(r2chan);
01500          ast_verbose("Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
01501          dahdi_r2_answer(p);
01502          return;
01503       }
01504       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01505       if (c) {
01506          /* chan_dahdi will take care of reading from now on, tell the library to forget about it */
01507          openr2_chan_disable_read(r2chan);
01508       } else {
01509          ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel);
01510          dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01511          return;
01512       }
01513    } else {
01514       ast_verbose("Call accepted on forward channel %d\n", p->channel);
01515       p->subs[SUB_REAL].needringing = 1;
01516       p->dialing = 0;
01517       /* chan_dahdi will take care of reading from now on, tell the library to forget about it */
01518       openr2_chan_disable_read(r2chan);
01519    }  
01520 }

static void dahdi_r2_on_call_answered ( openr2_chan_t *  r2chan  )  [static]

Definition at line 1522 of file chan_dahdi.c.

References ast_verbose(), dahdi_subchannel::needanswer, SUB_REAL, and dahdi_pvt::subs.

01523 {
01524    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01525    ast_verbose("MFC/R2 call has been answered on chan %d\n", openr2_chan_get_number(r2chan));
01526    p->subs[SUB_REAL].needanswer = 1;
01527 }

static void dahdi_r2_on_call_disconnect ( openr2_chan_t *  r2chan,
openr2_call_disconnect_cause_t  cause 
) [static]

Definition at line 1555 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, AST_CAUSE_BUSY, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_NETWORK_OUT_OF_ORDER, AST_CAUSE_NO_ANSWER, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_NOTDEFINED, AST_CAUSE_NUMBER_CHANGED, AST_CAUSE_UNALLOCATED, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_queue_hangup(), AST_SOFTHANGUP_DEV, AST_STATE_UP, ast_verbose(), dahdi_r2_disconnect_call(), ast_channel::hangupcause, dahdi_pvt::lock, LOG_WARNING, dahdi_subchannel::needbusy, dahdi_subchannel::needcongestion, dahdi_pvt::owner, SUB_REAL, and dahdi_pvt::subs.

01556 {
01557    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01558    ast_verbose("MFC/R2 call disconnected on chan %d\n", openr2_chan_get_number(r2chan));
01559    ast_mutex_lock(&p->lock);
01560    if (p->owner) {
01561       /* when we have an owner we don't call openr2_chan_disconnect_call here, that will
01562          be done in zt_hangup */
01563       if (p->owner->_state == AST_STATE_UP) {
01564          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01565          ast_mutex_unlock(&p->lock);
01566       } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
01567          /* being the forward side we must report what happened to the call to whoever requested it */
01568          switch (cause) {
01569          case OR2_CAUSE_BUSY_NUMBER:
01570             p->owner->hangupcause = AST_CAUSE_BUSY;
01571             p->subs[SUB_REAL].needbusy = 1;
01572             break;
01573          case OR2_CAUSE_NUMBER_CHANGED:
01574             p->owner->hangupcause = AST_CAUSE_NUMBER_CHANGED;
01575             p->subs[SUB_REAL].needcongestion = 1;
01576             break;
01577          case OR2_CAUSE_NETWORK_CONGESTION:
01578             p->owner->hangupcause = AST_CAUSE_NETWORK_OUT_OF_ORDER;
01579             p->subs[SUB_REAL].needcongestion = 1;
01580             break;
01581          case OR2_CAUSE_OUT_OF_ORDER:
01582             p->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01583             p->subs[SUB_REAL].needcongestion = 1;
01584             break;
01585          case OR2_CAUSE_UNALLOCATED_NUMBER:
01586             p->owner->hangupcause = AST_CAUSE_UNALLOCATED;
01587             p->subs[SUB_REAL].needcongestion = 1;
01588             break;
01589          case OR2_CAUSE_NO_ANSWER:
01590             p->owner->hangupcause = AST_CAUSE_NO_ANSWER;
01591             p->subs[SUB_REAL].needcongestion = 1;
01592             break;
01593          case OR2_CAUSE_UNSPECIFIED:
01594             p->owner->hangupcause = AST_CAUSE_NOTDEFINED;
01595             p->subs[SUB_REAL].needcongestion = 1;
01596             break;
01597          case OR2_CAUSE_NORMAL_CLEARING:
01598             p->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING;
01599             p->subs[SUB_REAL].needcongestion = 1;
01600             break;
01601          default:
01602             ast_log(LOG_WARNING, "Unhandled cause %d\n", cause);
01603          }
01604          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01605          ast_mutex_unlock(&p->lock);
01606       } else {
01607          ast_mutex_unlock(&p->lock);
01608          /* being the backward side and not UP yet, we only need to request hangup */
01609          /* TODO: what about doing this same thing when were AST_STATE_UP? */
01610          ast_queue_hangup(p->owner);
01611       }  
01612    } else {
01613       ast_mutex_unlock(&p->lock);
01614       /* no owner, therefore we can't use zt_hangup to disconnect, do it right now */
01615       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
01616    }
01617 }

static void dahdi_r2_on_call_end ( openr2_chan_t *  r2chan  )  [static]

Definition at line 1475 of file chan_dahdi.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), dahdi_pvt::channel, dahdi_pvt::lock, and dahdi_pvt::mfcr2call.

01476 {
01477    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01478    ast_verbose("MFC/R2 call end on chan %d\n", p->channel);
01479    ast_mutex_lock(&p->lock);
01480    p->mfcr2call = 0;
01481    ast_mutex_unlock(&p->lock);
01482 }

static void dahdi_r2_on_call_init ( openr2_chan_t *  r2chan  )  [static]

Definition at line 1341 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::exten, dahdi_pvt::lock, LOG_ERROR, dahdi_pvt::mfcr2_ani_index, dahdi_pvt::mfcr2_call_accepted, dahdi_pvt::mfcr2_dnis_index, dahdi_pvt::mfcr2_dnis_matched, dahdi_pvt::mfcr2call, and dahdi_pvt::rdnis.

01342 {
01343    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01344    ast_mutex_lock(&p->lock);
01345    if (p->mfcr2call) {
01346       ast_mutex_unlock(&p->lock);
01347       /* TODO: This can happen when some other thread just finished zt_request requesting this very same
01348       interface but has not yet seized the line (zt_call), and the far end wins and seize the line,
01349       can we avoid this somehow?, at this point when zt_call send the seize, it is likely that since
01350       the other end will see our seize as a forced release and drop the call, we will see an invalid
01351       pattern that will be seen and treated as protocol error. */
01352       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
01353       return;
01354    }
01355    p->mfcr2call = 1;
01356    /* better safe than sorry ... */
01357    p->cid_name[0] = 0;
01358    p->cid_num[0] = 0;
01359    p->rdnis[0] = 0;
01360    p->exten[0] = 0;
01361    p->mfcr2_ani_index = 0;
01362    p->mfcr2_dnis_index = 0;
01363    p->mfcr2_dnis_matched = 0;
01364    p->mfcr2_call_accepted = 0;
01365    ast_mutex_unlock(&p->lock);
01366    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
01367 }

static void dahdi_r2_on_call_offered ( openr2_chan_t *  r2chan,
const char *  ani,
const char *  dnis,
openr2_calling_party_category_t  category 
) [static]

Definition at line 1424 of file chan_dahdi.c.

References ast_exists_extension(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RING, ast_verbose(), dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::context, dahdi_new(), dahdi_r2_disconnect_call(), dahdi_pvt::exten, dahdi_pvt::immediate, dahdi_pvt::lock, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, dahdi_pvt::mfcr2_accept_on_offer, dahdi_pvt::mfcr2_allow_collect_calls, dahdi_pvt::mfcr2_charge_calls, dahdi_pvt::mfcr2_recvd_category, SUB_REAL, and dahdi_pvt::use_callerid.

01425 {
01426    struct dahdi_pvt *p;
01427    struct ast_channel *c;
01428    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n", 
01429          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis, openr2_proto_get_category_string(category));
01430    p = openr2_chan_get_client_data(r2chan);
01431    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
01432       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call on chan %d\n", p->channel);
01433       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
01434       return;
01435    }
01436    ast_mutex_lock(&p->lock);
01437    p->mfcr2_recvd_category = category;
01438    /* if we're not supposed to use CID, clear whatever we have */
01439    if (!p->use_callerid) {
01440       ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
01441       p->cid_num[0] = 0;
01442       p->cid_name[0] = 0;
01443    }
01444    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
01445    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
01446       ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
01447       p->exten[0] = 's';
01448       p->exten[1] = 0;
01449    }
01450    ast_mutex_unlock(&p->lock);
01451    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01452       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
01453             p->channel, p->exten, p->context);
01454       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
01455    } else {
01456       /* if the user does not want to accept on offer, then we should launch the PBX thread now */
01457       if (!p->mfcr2_accept_on_offer) {
01458          c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01459          if (!c) {
01460             ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel);
01461             dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01462          }
01463          /* Don't disable reading since we still need to generate MF tone to accept
01464             the call or reject it and detect the tone off condition of the other end */
01465       } else if (p->mfcr2_charge_calls) {
01466          ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with charge on chan %d\n", p->channel);
01467          openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
01468       } else {
01469          ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with no charge on chan %d\n", p->channel);
01470          openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
01471       }  
01472    }  
01473 }

static void dahdi_r2_on_call_read ( openr2_chan_t *  r2chan,
const unsigned char *  buf,
int  buflen 
) [static]

Definition at line 1529 of file chan_dahdi.c.

01530 {
01531    /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
01532 }

static void dahdi_r2_on_chan_log ( openr2_chan_t *  r2chan,
openr2_log_level_t  level,
const char *  fmt,
va_list  ap 
) [static]

Definition at line 1678 of file chan_dahdi.c.

References dahdi_r2_write_log().

Referenced by mkintf().

01679 {
01680    char logmsg[256];
01681    char completemsg[sizeof(logmsg)+50];
01682    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01683    snprintf(completemsg, sizeof(completemsg), "Chan %d - %s", openr2_chan_get_number(r2chan), logmsg);
01684    dahdi_r2_write_log(level, completemsg);
01685 }

static void dahdi_r2_on_context_log ( openr2_context_t *  r2context,
openr2_log_level_t  level,
const char *  fmt,
va_list  ap 
) [static]

Definition at line 1667 of file chan_dahdi.c.

References dahdi_r2_write_log().

01668 {
01669    char logmsg[256];
01670    char completemsg[sizeof(logmsg)+50];
01671    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01672    snprintf(completemsg, sizeof(completemsg), "Context - %s", logmsg);
01673    dahdi_r2_write_log(level, completemsg);
01674 }

static int dahdi_r2_on_dnis_digit_received ( openr2_chan_t *  r2chan,
char  digit 
) [static]

Definition at line 1687 of file chan_dahdi.c.

References ast_exists_extension(), ast_matchmore_extension(), dahdi_pvt::cid_num, dahdi_pvt::context, dahdi_pvt::exten, dahdi_pvt::immediate, dahdi_pvt::mfcr2_dnis_index, dahdi_pvt::mfcr2_dnis_matched, and dahdi_pvt::rdnis.

01688 {
01689    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01690    /* if 'immediate' is set, let's stop requesting DNIS */
01691    if (p->immediate) {
01692       return 0;
01693    }
01694    p->exten[p->mfcr2_dnis_index] = digit;
01695    p->rdnis[p->mfcr2_dnis_index] = digit;
01696    p->mfcr2_dnis_index++;
01697    p->exten[p->mfcr2_dnis_index] = 0;
01698    p->rdnis[p->mfcr2_dnis_index] = 0;
01699    /*
01700    ast_log(LOG_DEBUG, "Got digit %c in dahdi, dnis so far: %s\n", digit, p->exten);
01701    int ret;
01702    ret = ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num);
01703    ast_log(LOG_DEBUG, "ast_exists_extension(%s, %s, 1, %s) = %d\n", p->context, p->exten, p->cid_num, ret);
01704    ret = ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num);
01705    ast_log(LOG_DEBUG, "ast_matchmore_extension(%s, %s, 1, %s) = %d\n", p->context, p->exten, p->cid_num, ret);
01706    */
01707    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
01708    if ((p->mfcr2_dnis_matched || 
01709        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
01710        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01711       return 0;
01712    }
01713    /* otherwise keep going */
01714    return 1;
01715 }

static void dahdi_r2_on_hardware_alarm ( openr2_chan_t *  r2chan,
int  alarm 
) [static]

Definition at line 1371 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, EVENT_FLAG_SYSTEM, get_alarms(), handle_alarms(), dahdi_pvt::inalarm, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, manager_event(), and dahdi_pvt::unknown_alarm.

01372 {
01373    int res;
01374    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01375    ast_mutex_lock(&p->lock);
01376    p->inalarm = alarm ? 1 : 0;
01377    if (p->inalarm) {
01378       res = get_alarms(p);
01379       /* unknown_alarm may be set here */
01380       handle_alarms(p, res);
01381    } else {
01382       if (!p->unknown_alarm) {
01383          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
01384          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
01385       } else {
01386          p->unknown_alarm = 0;
01387       }
01388    }
01389    ast_mutex_unlock(&p->lock);
01390    ast_log(LOG_WARNING, "Zap alarm on chan %d.\n", openr2_chan_get_number(r2chan));
01391 }

static void dahdi_r2_on_line_blocked ( openr2_chan_t *  r2chan  )  [static]

Definition at line 1647 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, DAHDI_R2_REMOTE_BLOCK, dahdi_pvt::lock, LOG_NOTICE, and dahdi_pvt::mfcr2block.

01648 {
01649    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01650    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", p->channel);
01651    ast_mutex_lock(&p->lock);
01652    p->mfcr2block |= DAHDI_R2_REMOTE_BLOCK;
01653    ast_mutex_unlock(&p->lock);
01654 }

static void dahdi_r2_on_line_idle ( openr2_chan_t *  r2chan  )  [static]

Definition at line 1656 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), DAHDI_R2_REMOTE_BLOCK, dahdi_pvt::lock, LOG_NOTICE, and dahdi_pvt::mfcr2block.

01657 {
01658    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01659    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
01660    ast_mutex_lock(&p->lock);
01661    p->mfcr2block &= ~DAHDI_R2_REMOTE_BLOCK;
01662    ast_mutex_unlock(&p->lock);
01663 }

static void dahdi_r2_on_os_error ( openr2_chan_t *  r2chan,
int  errorcode 
) [static]

Definition at line 1393 of file chan_dahdi.c.

References ast_log(), and LOG_ERROR.

01394 {
01395    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
01396 }

static void dahdi_r2_on_protocol_error ( openr2_chan_t *  r2chan,
openr2_protocol_error_t  reason 
) [static]

Definition at line 1398 of file chan_dahdi.c.

References ast_channel::_softhangup, AST_CAUSE_PROTOCOL_ERROR, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SOFTHANGUP_DEV, ast_channel::hangupcause, dahdi_pvt::lock, LOG_ERROR, dahdi_pvt::mfcr2call, and dahdi_pvt::owner.

01399 {
01400    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01401    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
01402    if (p->owner) {
01403       p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
01404       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01405    } 
01406    ast_mutex_lock(&p->lock);
01407    p->mfcr2call = 0;
01408    ast_mutex_unlock(&p->lock);
01409 }

static void dahdi_r2_write_log ( openr2_log_level_t  level,
char *  logmessage 
) [static]

Definition at line 1619 of file chan_dahdi.c.

References ast_log(), ast_verbose(), LOG_DEBUG, LOG_ERROR, LOG_NOTICE, and LOG_WARNING.

Referenced by dahdi_r2_on_chan_log(), and dahdi_r2_on_context_log().

01620 {
01621    switch (level) {
01622    case OR2_LOG_NOTICE:
01623       ast_verbose("%s", logmessage);
01624       break;
01625    case OR2_LOG_WARNING:
01626       ast_log(LOG_WARNING, "%s", logmessage);
01627       break;
01628    case OR2_LOG_ERROR:
01629       ast_log(LOG_ERROR, "%s", logmessage);
01630       break;
01631    case OR2_LOG_STACK_TRACE:
01632    case OR2_LOG_MF_TRACE:
01633    case OR2_LOG_CAS_TRACE:
01634    case OR2_LOG_DEBUG:
01635    case OR2_LOG_EX_DEBUG:
01636       ast_log(LOG_DEBUG, "%s", logmessage);
01637       break;
01638    default:
01639       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
01640       ast_log(LOG_NOTICE, "%s", logmessage);
01641       break;
01642    }
01643 }

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

Definition at line 5909 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_tv(), 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_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_OUTGOING, 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_pvt::mfcr2, ast_channel::name, 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_pri::overlapdial, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::proceeding, dahdi_pvt::pulsedial, dahdi_pvt::r2chan, 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.

05910 {
05911    struct dahdi_pvt *p = ast->tech_pvt;
05912    int res;
05913    int index;
05914    void *readbuf;
05915    struct ast_frame *f;
05916 
05917    while (ast_mutex_trylock(&p->lock)) {
05918       DEADLOCK_AVOIDANCE(&ast->lock);
05919    }
05920 
05921    index = dahdi_get_index(ast, p, 0);
05922    
05923    /* Hang up if we don't really exist */
05924    if (index < 0) {
05925       ast_log(LOG_WARNING, "We dont exist?\n");
05926       ast_mutex_unlock(&p->lock);
05927       return NULL;
05928    }
05929    
05930    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
05931       ast_mutex_unlock(&p->lock);
05932       return NULL;
05933    }
05934 
05935    p->subs[index].f.frametype = AST_FRAME_NULL;
05936    p->subs[index].f.datalen = 0;
05937    p->subs[index].f.samples = 0;
05938    p->subs[index].f.mallocd = 0;
05939    p->subs[index].f.offset = 0;
05940    p->subs[index].f.subclass = 0;
05941    p->subs[index].f.delivery = ast_tv(0,0);
05942    p->subs[index].f.src = "dahdi_read";
05943    p->subs[index].f.data = NULL;
05944    
05945    /* make sure it sends initial key state as first frame */
05946    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
05947    {
05948       struct dahdi_params ps;
05949 
05950       memset(&ps, 0, sizeof(ps));
05951       ps.channo = p->channel;
05952       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
05953          ast_mutex_unlock(&p->lock);
05954          return NULL;
05955       }
05956       p->firstradio = 1;
05957       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05958       if (ps.rxisoffhook)
05959       {
05960          p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
05961       }
05962       else
05963       {
05964          p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
05965       }
05966       ast_mutex_unlock(&p->lock);
05967       return &p->subs[index].f;
05968    }
05969    if (p->ringt == 1) {
05970       ast_mutex_unlock(&p->lock);
05971       return NULL;
05972    }
05973    else if (p->ringt > 0) 
05974       p->ringt--;
05975 
05976 #ifdef HAVE_OPENR2
05977    if (p->mfcr2) {
05978       openr2_chan_process_event(p->r2chan);
05979    }  
05980 #endif
05981 
05982    if (p->subs[index].needringing) {
05983       /* Send ringing frame if requested */
05984       p->subs[index].needringing = 0;
05985       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05986       p->subs[index].f.subclass = AST_CONTROL_RINGING;
05987       ast_setstate(ast, AST_STATE_RINGING);
05988       ast_mutex_unlock(&p->lock);
05989       return &p->subs[index].f;
05990    }
05991 
05992    if (p->subs[index].needbusy) {
05993       /* Send busy frame if requested */
05994       p->subs[index].needbusy = 0;
05995       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05996       p->subs[index].f.subclass = AST_CONTROL_BUSY;
05997       ast_mutex_unlock(&p->lock);
05998       return &p->subs[index].f;
05999    }
06000 
06001    if (p->subs[index].needcongestion) {
06002       /* Send congestion frame if requested */
06003       p->subs[index].needcongestion = 0;
06004       p->subs[index].f.frametype = AST_FRAME_CONTROL;
06005       p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
06006       ast_mutex_unlock(&p->lock);
06007       return &p->subs[index].f;
06008    }
06009 
06010    if (p->subs[index].needcallerid) {
06011       ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
06012                      S_OR(p->lastcid_name, NULL),
06013                      S_OR(p->lastcid_num, NULL)
06014                      );
06015       p->subs[index].needcallerid = 0;
06016    }
06017    
06018    if (p->subs[index].needanswer) {
06019       /* Send answer frame if requested */
06020       p->subs[index].needanswer = 0;
06021       p->subs[index].f.frametype = AST_FRAME_CONTROL;
06022       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
06023       ast_mutex_unlock(&p->lock);
06024       return &p->subs[index].f;
06025    }  
06026 
06027 #ifdef HAVE_OPENR2
06028    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
06029       /* openr2 took care of reading and handling any event 
06030         (needanswer, needbusy etc), if we continue we will read()
06031         twice, lets just return a null frame. This should only
06032         happen when openr2 is dialing out */
06033       p->subs[index].f.frametype = AST_FRAME_NULL;
06034       p->subs[index].f.subclass = 0;
06035       p->subs[index].f.samples = 0;
06036       p->subs[index].f.mallocd = 0;
06037       p->subs[index].f.offset = 0;
06038       p->subs[index].f.data = NULL;
06039       p->subs[index].f.datalen= 0;
06040       ast_mutex_unlock(&p->lock);
06041       return &p->subs[index].f;
06042    }
06043 #endif
06044    
06045    if (p->subs[index].needflash) {
06046       /* Send answer frame if requested */
06047       p->subs[index].needflash = 0;
06048       p->subs[index].f.frametype = AST_FRAME_CONTROL;
06049       p->subs[index].f.subclass = AST_CONTROL_FLASH;
06050       ast_mutex_unlock(&p->lock);
06051       return &p->subs[index].f;
06052    }  
06053    
06054    if (p->subs[index].needhold) {
06055       /* Send answer frame if requested */
06056       p->subs[index].needhold = 0;
06057       p->subs[index].f.frametype = AST_FRAME_CONTROL;
06058       p->subs[index].f.subclass = AST_CONTROL_HOLD;
06059       ast_mutex_unlock(&p->lock);
06060       ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
06061       return &p->subs[index].f;
06062    }  
06063    
06064    if (p->subs[index].needunhold) {
06065       /* Send answer frame if requested */
06066       p->subs[index].needunhold = 0;
06067       p->subs[index].f.frametype = AST_FRAME_CONTROL;
06068       p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
06069       ast_mutex_unlock(&p->lock);
06070       ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
06071       return &p->subs[index].f;
06072    }  
06073    
06074    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
06075       if (!p->subs[index].linear) {
06076          p->subs[index].linear = 1;
06077          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06078          if (res) 
06079             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
06080       }
06081    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
06082          (ast->rawreadformat == AST_FORMAT_ALAW)) {
06083       if (p->subs[index].linear) {
06084          p->subs[index].linear = 0;
06085          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06086          if (res) 
06087             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
06088       }
06089    } else {
06090       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
06091       ast_mutex_unlock(&p->lock);
06092       return NULL;
06093    }
06094    readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
06095    CHECK_BLOCKING(ast);
06096    res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
06097    ast_clear_flag(ast, AST_FLAG_BLOCKING);
06098    /* Check for hangup */
06099    if (res < 0) {
06100       f = NULL;
06101       if (res == -1)  {
06102          if (errno == EAGAIN) {
06103             /* Return "NULL" frame if there is nobody there */
06104             ast_mutex_unlock(&p->lock);
06105             return &p->subs[index].f;
06106          } else if (errno == ELAST) {
06107             f = __dahdi_exception(ast);
06108          } else
06109             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
06110       }
06111       ast_mutex_unlock(&p->lock);
06112       return f;
06113    }
06114    if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
06115       ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
06116       f = __dahdi_exception(ast);
06117       ast_mutex_unlock(&p->lock);
06118       return f;
06119    }
06120    if (p->tdd) { /* if in TDD mode, see if we receive that */
06121       int c;
06122 
06123       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
06124       if (c < 0) {
06125          ast_log(LOG_DEBUG,"tdd_feed failed\n");
06126          ast_mutex_unlock(&p->lock);
06127          return NULL;
06128       }
06129       if (c) { /* if a char to return */
06130          p->subs[index].f.subclass = 0;
06131          p->subs[index].f.frametype = AST_FRAME_TEXT;
06132          p->subs[index].f.mallocd = 0;
06133          p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
06134          p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
06135          p->subs[index].f.datalen = 1;
06136          *((char *) p->subs[index].f.data) = c;
06137          ast_mutex_unlock(&p->lock);
06138          return &p->subs[index].f;
06139       }
06140    }
06141    /* Ensure the CW timer decrements only on a single subchannel */
06142    if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
06143       p->callwaitingrepeat--;
06144    }
06145    if (p->cidcwexpire)
06146       p->cidcwexpire--;
06147    /* Repeat callwaiting */
06148    if (p->callwaitingrepeat == 1) {
06149       p->callwaitrings++;
06150       dahdi_callwait(ast);
06151    }
06152    /* Expire CID/CW */
06153    if (p->cidcwexpire == 1) {
06154       if (option_verbose > 2)
06155          ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
06156       restore_conference(p);
06157    }
06158    if (p->subs[index].linear) {
06159       p->subs[index].f.datalen = READ_SIZE * 2;
06160    } else 
06161       p->subs[index].f.datalen = READ_SIZE;
06162 
06163    /* Handle CallerID Transmission */
06164    if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
06165       send_callerid(p);
06166    }
06167 
06168    p->subs[index].f.frametype = AST_FRAME_VOICE;
06169    p->subs[index].f.subclass = ast->rawreadformat;
06170    p->subs[index].f.samples = READ_SIZE;
06171    p->subs[index].f.mallocd = 0;
06172    p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
06173    p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
06174 #if 0
06175    ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
06176 #endif   
06177    if (p->dialing || /* Transmitting something */
06178       (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
06179       ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
06180       ) {
06181       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
06182          don't send anything */
06183       p->subs[index].f.frametype = AST_FRAME_NULL;
06184       p->subs[index].f.subclass = 0;
06185       p->subs[index].f.samples = 0;
06186       p->subs[index].f.mallocd = 0;
06187       p->subs[index].f.offset = 0;
06188       p->subs[index].f.data = NULL;
06189       p->subs[index].f.datalen= 0;
06190    }
06191    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect  || p->callprogress) && !index) {
06192       /* Perform busy detection. etc on the dahdi line */
06193       f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
06194       if (f) {
06195          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
06196             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
06197                /* Treat this as a "hangup" instead of a "busy" on the assumption that
06198                   a busy  */
06199                f = NULL;
06200             }
06201          } else if (f->frametype == AST_FRAME_DTMF) {
06202 #ifdef HAVE_PRI
06203             if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial &&
06204                ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
06205                (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
06206                /* Don't accept in-band DTMF when in overlap dial mode */
06207                f->frametype = AST_FRAME_NULL;
06208                f->subclass = 0;
06209             }
06210 #endif            
06211             /* DSP clears us of being pulse */
06212             p->pulsedial = 0;
06213          }
06214       }
06215    } else 
06216       f = &p->subs[index].f; 
06217 
06218    if (f && (f->frametype == AST_FRAME_DTMF))
06219       dahdi_handle_dtmfup(ast, index, &f);
06220 
06221    /* If we have a fake_event, trigger exception to handle it */
06222    if (p->fake_event)
06223       ast_set_flag(ast, AST_FLAG_EXCEPTION);
06224 
06225    ast_mutex_unlock(&p->lock);
06226    return f;
06227 }

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

Definition at line 9330 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(), dahdi_pvt::bearer, busy, ast_channel::cdrflags, CHAN_PSEUDO, chandup(), dahdi_pvt::channel, dahdi_pvt::confirmanswer, dahdi_pri::crvend, dahdi_pri::crvs, dahdi_new(), dahdi_pvt::digital, dahdi_pvt::distinctivering, iflist, iflock, dahdi_pvt::inalarm, dahdi_pvt::lock, dahdi_pri::lock, lock, LOG_DEBUG, LOG_NOTICE, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2block, dahdi_pvt::mfcr2call, ast_channel::name, dahdi_pvt::next, NUM_SPANS, option_debug, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::prev, dahdi_pvt::pri, dahdi_pri::pri, pri_assign_bearer(), pri_find_empty_chan(), pris, dahdi_pri::pvts, restart_monitor(), round_robin, s, dahdi_pvt::sig, SIG_FXSKS, dahdi_pri::span, SUB_CALLWAIT, SUB_REAL, dahdi_pvt::subs, and ast_channel::transfercapability.

Referenced by pri_dchannel().

09331 {
09332    ast_group_t groupmatch = 0;
09333    int channelmatch = -1;
09334    int roundrobin = 0;
09335    int callwait = 0;
09336    int busy = 0;
09337    struct dahdi_pvt *p;
09338    struct ast_channel *tmp = NULL;
09339    char *dest=NULL;
09340    int x;
09341    char *s;
09342    char opt=0;
09343    int res=0, y=0;
09344    int backwards = 0;
09345 #ifdef HAVE_PRI
09346    int crv;
09347    int bearer = -1;
09348    int trunkgroup;
09349    struct dahdi_pri *pri=NULL;
09350 #endif   
09351    struct dahdi_pvt *exit, *start, *end;
09352    ast_mutex_t *lock;
09353    int channelmatched = 0;
09354    int groupmatched = 0;
09355    
09356    /*
09357     * data is ---v
09358     * Dial(DAHDI/pseudo[/extension])
09359     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension])
09360     * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension])
09361     * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension])
09362     *
09363     * g - channel group allocation search forward
09364     * G - channel group allocation search backward
09365     * r - channel group allocation round robin search forward
09366     * R - channel group allocation round robin search backward
09367     *
09368     * c - Wait for DTMF digit to confirm answer
09369     * r<cadance#> - Set distintive ring cadance number
09370     * d - Force bearer capability for ISDN call to digital.
09371     */
09372 
09373    /* Assume we're locking the iflock */
09374    lock = &iflock;
09375    start = iflist;
09376    end = ifend;
09377    if (data) {
09378       dest = ast_strdupa((char *)data);
09379    } else {
09380       ast_log(LOG_WARNING, "Channel requested with no data\n");
09381       return NULL;
09382    }
09383    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
09384       /* Retrieve the group number */
09385       char *stringp;
09386 
09387       stringp = dest + 1;
09388       s = strsep(&stringp, "/");
09389       if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09390          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
09391          return NULL;
09392       }
09393       groupmatch = ((ast_group_t) 1 << x);
09394       if (toupper(dest[0]) == 'G') {
09395          if (dest[0] == 'G') {
09396             backwards = 1;
09397             p = ifend;
09398          } else
09399             p = iflist;
09400       } else {
09401          if (dest[0] == 'R') {
09402             backwards = 1;
09403             p = round_robin[x]?round_robin[x]->prev:ifend;
09404             if (!p)
09405                p = ifend;
09406          } else {
09407             p = round_robin[x]?round_robin[x]->next:iflist;
09408             if (!p)
09409                p = iflist;
09410          }
09411          roundrobin = 1;
09412       }
09413    } else {
09414       char *stringp;
09415 
09416       stringp = dest;
09417       s = strsep(&stringp, "/");
09418       p = iflist;
09419       if (!strcasecmp(s, "pseudo")) {
09420          /* Special case for pseudo */
09421          x = CHAN_PSEUDO;
09422          channelmatch = x;
09423       } 
09424 #ifdef HAVE_PRI
09425       else if ((res = sscanf(s, "%30d:%30d%c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
09426          if ((trunkgroup < 1) || (crv < 1)) {
09427             ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
09428             return NULL;
09429          }
09430          res--;
09431          for (x = 0; x < NUM_SPANS; x++) {
09432             if (pris[x].trunkgroup == trunkgroup) {
09433                pri = pris + x;
09434                lock = &pri->lock;
09435                start = pri->crvs;
09436                end = pri->crvend;
09437                break;
09438             }
09439          }
09440          if (!pri) {
09441             ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
09442             return NULL;
09443          }
09444          channelmatch = crv;
09445          p = pris[x].crvs;
09446       }
09447 #endif   
09448       else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09449          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
09450          return NULL;
09451       } else {
09452          channelmatch = x;
09453       }
09454    }
09455    /* Search for an unowned channel */
09456    ast_mutex_lock(lock);
09457    exit = p;
09458    while (p && !tmp) {
09459       if (roundrobin)
09460          round_robin[x] = p;
09461 #if 0
09462       ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
09463 #endif
09464 
09465       if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
09466          if (option_debug)
09467             ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
09468             if (p->inalarm) 
09469                goto next;
09470 
09471          callwait = (p->owner != NULL);
09472 #ifdef HAVE_PRI
09473          if (pri && (p->subs[SUB_REAL].dfd < 0)) {
09474             if (p->sig != SIG_FXSKS) {
09475                /* Gotta find an actual channel to use for this
09476                   CRV if this isn't a callwait */
09477                bearer = pri_find_empty_chan(pri, 0);
09478                if (bearer < 0) {
09479                   ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
09480                   p = NULL;
09481                   break;
09482                }
09483                pri_assign_bearer(p, pri, pri->pvts[bearer]);
09484             } else {
09485                if (alloc_sub(p, 0)) {
09486                   ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
09487                   p = NULL;
09488                   break;
09489                } else
09490                   ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
09491                p->pri = pri;
09492             }
09493          }
09494 #endif         
09495 #ifdef HAVE_OPENR2
09496          if (p->mfcr2) {
09497             ast_mutex_lock(&p->lock);
09498             if (p->mfcr2call) {
09499                ast_mutex_unlock(&p->lock);
09500                ast_log(LOG_NOTICE, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
09501                goto next;
09502             }
09503             if (p->mfcr2block) {
09504                ast_mutex_unlock(&p->lock);
09505                ast_log(LOG_NOTICE, "Yay!, channel %d just got blocked (%d).\n", p->channel, p->mfcr2block);
09506                goto next;
09507             }
09508             p->mfcr2call = 1;
09509             ast_mutex_unlock(&p->lock);
09510          }
09511 #endif
09512          if (p->channel == CHAN_PSEUDO) {
09513             p = chandup(p);
09514             if (!p) {
09515                break;
09516             }
09517          }
09518          if (p->owner) {
09519             if (alloc_sub(p, SUB_CALLWAIT)) {
09520                p = NULL;
09521                break;
09522             }
09523          }
09524          p->outgoing = 1;
09525          tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
09526          if (!tmp) {
09527             p->outgoing = 0;
09528          }
09529 #ifdef HAVE_PRI
09530          if (p->bearer) {
09531             /* Log owner to bearer channel, too */
09532             p->bearer->owner = tmp;
09533          }
09534 #endif         
09535          /* Make special notes */
09536          if (res > 1) {
09537             if (opt == 'c') {
09538                /* Confirm answer */
09539                p->confirmanswer = 1;
09540             } else if (opt == 'r') {
09541                /* Distinctive ring */
09542                if (res < 3)
09543                   ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
09544                else
09545                   p->distinctivering = y;
09546             } else if (opt == 'd') {
09547                /* If this is an ISDN call, make it digital */
09548                p->digital = 1;
09549                if (tmp)
09550                   tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
09551             } else {
09552                ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
09553             }
09554          }
09555          /* Note if the call is a call waiting call */
09556          if (tmp && callwait)
09557             tmp->cdrflags |= AST_CDR_CALLWAIT;
09558          break;
09559       }
09560 next:
09561       if (backwards) {
09562          p = p->prev;
09563          if (!p)
09564             p = end;
09565       } else {
09566          p = p->next;
09567          if (!p)
09568             p = start;
09569       }
09570       /* stop when you roll to the one that we started from */
09571       if (p == exit)
09572          break;
09573    }
09574    ast_mutex_unlock(lock);
09575    restart_monitor();
09576    if (callwait)
09577       *cause = AST_CAUSE_BUSY;
09578    else if (!tmp) {
09579       if (channelmatched) {
09580          if (busy)
09581             *cause = AST_CAUSE_BUSY;
09582       } else if (groupmatched) {
09583          *cause = AST_CAUSE_CONGESTION;
09584       }
09585    }
09586       
09587    return tmp;
09588 }

static int dahdi_restart ( void   )  [static]

Definition at line 11962 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_close_pri_fd(), dahdi_pri_error(), dahdi_pri_message(), dahdi_softhangup_all(), destroy_all_channels(), dahdi_subchannel::dfd, iflist, init_mfcr2_globals(), lock, master, monlock, dahdi_pvt::next, NUM_SPANS, option_debug, option_verbose, dahdi_pvt::owner, pris, r2links, restart_lock, setup_dahdi(), ss_thread_lock, and dahdi_pvt::subs.

Referenced by __action_restart(), and dahdi_restart_cmd().

11963 {
11964 #ifdef HAVE_OPENR2
11965    int r;
11966 #endif
11967 #if defined(HAVE_PRI)
11968    int i, j;
11969 #endif
11970    int cancel_code;
11971    struct dahdi_pvt *p;
11972 
11973    ast_mutex_lock(&restart_lock);
11974  
11975    if (option_verbose)
11976       ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
11977    dahdi_softhangup_all();
11978    if (option_verbose > 3)
11979       ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
11980 
11981 #ifdef HAVE_OPENR2
11982    for (r = 0; r < NUM_SPANS; r++) {
11983       if (r2links[r].master != AST_PTHREADT_NULL) {
11984          ast_log(LOG_DEBUG, "Killing MFC/R2 monitor thread %p\n", &r2links[r].master);
11985          pthread_cancel(r2links[r].master);
11986          pthread_join(r2links[r].master, NULL);
11987          openr2_context_delete(r2links[r].protocol_context);
11988       }
11989    }
11990    init_mfcr2_globals();
11991 #endif
11992 
11993    #if defined(HAVE_PRI)
11994    for (i = 0; i < NUM_SPANS; i++) {
11995       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
11996          cancel_code = pthread_cancel(pris[i].master);
11997          pthread_kill(pris[i].master, SIGURG);
11998          if (option_debug > 3)
11999             ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
12000             pthread_join(pris[i].master, NULL);
12001          if (option_debug > 3)
12002             ast_verbose("Joined thread of span %d\n", i);
12003       }
12004     }
12005    #endif
12006 
12007     ast_mutex_lock(&monlock);
12008     if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12009       cancel_code = pthread_cancel(monitor_thread);
12010       pthread_kill(monitor_thread, SIGURG);
12011       if (option_debug > 3)
12012          ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
12013         pthread_join(monitor_thread, NULL);
12014       if (option_debug > 3)
12015          ast_verbose("Joined monitor thread\n");
12016     }
12017    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
12018 
12019    ast_mutex_lock(&ss_thread_lock);
12020    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
12021       int x = DAHDI_FLASH;
12022       if (option_debug > 2)
12023          ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
12024 
12025       for (p = iflist; p; p = p->next) {
12026          if (p->owner)
12027             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 */    
12028       }
12029       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
12030    }
12031 
12032    /* ensure any created channels before monitor threads were stopped are hungup */
12033    dahdi_softhangup_all();
12034    if (option_verbose > 3)
12035       ast_verbose("Final softhangup of all DAHDI channels complete.\n");
12036    destroy_all_channels();
12037    if (option_debug)
12038       ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
12039 
12040     ast_mutex_unlock(&monlock);
12041 
12042    #ifdef HAVE_PRI
12043    for (i = 0; i < NUM_SPANS; i++) {
12044       for (j = 0; j < NUM_DCHANS; j++)
12045             dahdi_close_pri_fd(&(pris[i]), j);
12046    }
12047 
12048    memset(pris, 0, sizeof(pris));
12049    for (i = 0; i < NUM_SPANS; i++) {
12050       ast_mutex_init(&pris[i].lock);
12051       pris[i].offset = -1;
12052       pris[i].master = AST_PTHREADT_NULL;
12053       for (j = 0; j < NUM_DCHANS; j++)
12054          pris[i].fds[j] = -1;
12055    }
12056    pri_set_error(dahdi_pri_error);
12057    pri_set_message(dahdi_pri_message);
12058    #endif
12059 
12060    if (setup_dahdi(2) != 0) {
12061       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
12062       ast_mutex_unlock(&ss_thread_lock);
12063       return 1;
12064    }
12065    ast_mutex_unlock(&ss_thread_lock);
12066    ast_mutex_unlock(&restart_lock);
12067    return 0;
12068 }

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

Definition at line 12070 of file chan_dahdi.c.

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

12071 {
12072    if (argc != 2) {
12073       return RESULT_SHOWUSAGE;
12074    }
12075 
12076    if (dahdi_restart() != 0)
12077       return RESULT_FAILURE;
12078    return RESULT_SUCCESS;
12079 }

static int dahdi_ring_phone ( struct dahdi_pvt p  )  [static]

Definition at line 4686 of file chan_dahdi.c.

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

Referenced by __dahdi_exception(), and dahdi_handle_event().

04687 {
04688    int x;
04689    int res;
04690    /* Make sure our transmit state is on hook */
04691    x = 0;
04692    x = DAHDI_ONHOOK;
04693    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04694    do {
04695       x = DAHDI_RING;
04696       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04697       if (res) {
04698          switch (errno) {
04699          case EBUSY:
04700          case EINTR:
04701             /* Wait just in case */
04702             usleep(10000);
04703             continue;
04704          case EINPROGRESS:
04705             res = 0;
04706             break;
04707          default:
04708             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
04709             res = 0;
04710          }
04711       }
04712    } while (res);
04713    return res;
04714 }

static int dahdi_send_keypad_facility_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 3340 of file chan_dahdi.c.

References send_keypad_facility_exec().

Referenced by load_module().

03341 {
03342    return send_keypad_facility_exec(chan, data);
03343 }

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

Definition at line 14002 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, free, HEADER_LEN, HEADER_MS, len(), LOG_ERROR, dahdi_pvt::mate, option_debug, PUT_CLID, PUT_CLID_MARKMS, READ_SIZE, dahdi_pvt::subs, dahdi_pvt::tdd, TDD_BYTES_PER_CHAR, tdd_generate(), ast_channel::tech_pvt, and TRAILER_MS.

14003 {
14004 #define  END_SILENCE_LEN 400
14005 #define  HEADER_MS 50
14006 #define  TRAILER_MS 5
14007 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
14008 #define  ASCII_BYTES_PER_CHAR 80
14009 
14010    unsigned char *buf,*mybuf;
14011    struct dahdi_pvt *p = c->tech_pvt;
14012    struct pollfd fds[1];
14013    int size,res,fd,len,x;
14014    int bytes=0;
14015    /* Initial carrier (imaginary) */
14016    float cr = 1.0;
14017    float ci = 0.0;
14018    float scont = 0.0;
14019    int index;
14020 
14021    index = dahdi_get_index(c, p, 0);
14022    if (index < 0) {
14023       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
14024       return -1;
14025    }
14026    if (!text[0]) return(0); /* if nothing to send, dont */
14027    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
14028    if (p->mate) 
14029       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
14030    else
14031       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
14032    if (!buf)
14033       return -1;
14034    mybuf = buf;
14035    if (p->mate) {
14036       int codec = AST_LAW(p);
14037       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
14038          PUT_CLID_MARKMS;
14039       }
14040       /* Put actual message */
14041       for (x = 0; text[x]; x++) {
14042          PUT_CLID(text[x]);
14043       }
14044       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
14045          PUT_CLID_MARKMS;
14046       }
14047       len = bytes;
14048       buf = mybuf;
14049    } else {
14050       len = tdd_generate(p->tdd, buf, text);
14051       if (len < 1) {
14052          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
14053          free(mybuf);
14054          return -1;
14055       }
14056    }
14057    memset(buf + len, 0x7f, END_SILENCE_LEN);
14058    len += END_SILENCE_LEN;
14059    fd = p->subs[index].dfd;
14060    while (len) {
14061       if (ast_check_hangup(c)) {
14062          free(mybuf);
14063          return -1;
14064       }
14065       size = len;
14066       if (size > READ_SIZE)
14067          size = READ_SIZE;
14068       fds[0].fd = fd;
14069       fds[0].events = POLLOUT | POLLPRI;
14070       fds[0].revents = 0;
14071       res = poll(fds, 1, -1);
14072       if (!res) {
14073          ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
14074          continue;
14075       }
14076         /* if got exception */
14077       if (fds[0].revents & POLLPRI) {
14078          ast_free(mybuf);
14079          return -1;
14080       }
14081       if (!(fds[0].revents & POLLOUT)) {
14082          ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
14083          continue;
14084       }
14085       res = write(fd, buf, size);
14086       if (res != size) {
14087          if (res == -1) {
14088             free(mybuf);
14089             return -1;
14090          }
14091          if (option_debug)
14092             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
14093          break;
14094       }
14095       len -= size;
14096       buf += size;
14097    }
14098    free(mybuf);
14099    return(0);
14100 }

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

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

02554 {
02555    int x, res;
02556 
02557    x = hs;
02558    res = ioctl(fd, DAHDI_HOOK, &x);
02559 
02560    if (res < 0) {
02561       if (errno == EINPROGRESS)
02562          return 0;
02563       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02564       /* will expectedly fail if phone is off hook during operation, such as during a restart */
02565    }
02566 
02567    return res;
02568 }

static int dahdi_setlaw ( int  dfd,
int  law 
) [static]

Definition at line 10033 of file chan_dahdi.c.

10034 {
10035    int res;
10036    res = ioctl(dfd, DAHDI_SETLAW, &law);
10037    if (res)
10038       return res;
10039    return 0;
10040 }

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

Definition at line 1867 of file chan_dahdi.c.

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

01868 {
01869    int res;
01870    res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
01871    if (res)
01872       return res;
01873    return 0;
01874 }

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

Definition at line 4050 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, dahdi_pvt::law, len(), LOG_DEBUG, LOG_WARNING, dahdi_pvt::mate, oprmode::mode, ast_channel::name, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, option_debug, oprmode::peer, READ_SIZE, 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.

04051 {
04052    char *cp;
04053    signed char *scp;
04054    int x;
04055    int index;
04056    struct dahdi_pvt *p = chan->tech_pvt, *pp;
04057    struct oprmode *oprmode;
04058    
04059 
04060    /* all supported options require data */
04061    if (!data || (datalen < 1)) {
04062       errno = EINVAL;
04063       return -1;
04064    }
04065 
04066    switch (option) {
04067    case AST_OPTION_TXGAIN:
04068       scp = (signed char *) data;
04069       index = dahdi_get_index(chan, p, 0);
04070       if (index < 0) {
04071          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
04072          return -1;
04073       }
04074       if (option_debug)
04075          ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
04076       return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
04077    case AST_OPTION_RXGAIN:
04078       scp = (signed char *) data;
04079       index = dahdi_get_index(chan, p, 0);
04080       if (index < 0) {
04081          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
04082          return -1;
04083       }
04084       if (option_debug)
04085          ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
04086       return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
04087    case AST_OPTION_TONE_VERIFY:
04088       if (!p->dsp)
04089          break;
04090       cp = (char *) data;
04091       switch (*cp) {
04092       case 1:
04093          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
04094          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
04095          break;
04096       case 2:
04097          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
04098          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
04099          break;
04100       default:
04101          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
04102          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
04103          break;
04104       }
04105       break;
04106    case AST_OPTION_TDD:
04107       /* turn on or off TDD */
04108       cp = (char *) data;
04109       p->mate = 0;
04110       if (!*cp) { /* turn it off */
04111          if (option_debug)
04112             ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
04113          if (p->tdd)
04114             tdd_free(p->tdd);
04115          p->tdd = 0;
04116          break;
04117       }
04118       ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
04119          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
04120       dahdi_disable_ec(p);
04121       /* otherwise, turn it on */
04122       if (!p->didtdd) { /* if havent done it yet */
04123          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
04124          unsigned char *buf;
04125          int size, res, fd, len;
04126          struct pollfd fds[1];
04127 
04128          buf = mybuf;
04129          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
04130          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
04131          len = 40000;
04132          index = dahdi_get_index(chan, p, 0);
04133          if (index < 0) {
04134             ast_log(LOG_WARNING, "No index in TDD?\n");
04135             return -1;
04136          }
04137          fd = p->subs[index].dfd;
04138          while (len) {
04139             if (ast_check_hangup(chan))
04140                return -1;
04141             size = len;
04142             if (size > READ_SIZE)
04143                size = READ_SIZE;
04144             fds[0].fd = fd;
04145             fds[0].events = POLLPRI | POLLOUT;
04146             fds[0].revents = 0;
04147             res = poll(fds, 1, -1);
04148             if (!res) {
04149                ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
04150                continue;
04151             }
04152             /* if got exception */
04153             if (fds[0].revents & POLLPRI)
04154                return -1;
04155             if (!(fds[0].revents & POLLOUT)) {
04156                ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
04157                continue;
04158             }
04159             res = write(fd, buf, size);
04160             if (res != size) {
04161                if (res == -1) return -1;
04162                ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
04163                break;
04164             }
04165             len -= size;
04166             buf += size;
04167          }
04168          p->didtdd = 1; /* set to have done it now */    
04169       }
04170       if (*cp == 2) { /* Mate mode */
04171          if (p->tdd)
04172             tdd_free(p->tdd);
04173          p->tdd = 0;
04174          p->mate = 1;
04175          break;
04176       }     
04177       if (!p->tdd) { /* if we dont have one yet */
04178          p->tdd = tdd_new(); /* allocate one */
04179       }     
04180       break;
04181    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
04182       if (!p->dsp)
04183          break;
04184       cp = (char *) data;
04185       ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
04186          *cp ? "ON" : "OFF", (int) *cp, chan->name);
04187                 p->dtmfrelax = 0;
04188                 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
04189                 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
04190       break;
04191    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
04192       cp = (char *) data;
04193       if (!*cp) {    
04194          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
04195          x = 0;
04196          dahdi_disable_ec(p);
04197       } else {    
04198          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
04199          x = 1;
04200       }
04201       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
04202          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
04203       break;
04204    case AST_OPTION_OPRMODE:  /* Operator services mode */
04205       oprmode = (struct oprmode *) data;
04206       pp = oprmode->peer->tech_pvt;
04207       p->oprmode = pp->oprmode = 0;
04208       /* setup peers */
04209       p->oprpeer = pp;
04210       pp->oprpeer = p;
04211       /* setup modes, if any */
04212       if (oprmode->mode) 
04213       {
04214          pp->oprmode = oprmode->mode;
04215          p->oprmode = -oprmode->mode;
04216       }
04217       ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
04218          oprmode->mode, chan->name,oprmode->peer->name);;
04219       break;
04220    case AST_OPTION_ECHOCAN:
04221       cp = (char *) data;
04222       if (*cp) {
04223          ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
04224          dahdi_enable_ec(p);
04225       } else {
04226          ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
04227          dahdi_disable_ec(p);
04228       }
04229       break;
04230    }
04231    errno = 0;
04232 
04233    return 0;
04234 }

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

Definition at line 12142 of file chan_dahdi.c.

References ast_cli(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), dahdi_pvt::bearer, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::call, 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, iflock, dahdi_pvt::inalarm, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, ISTRUNK, dahdi_pvt::law, dahdi_subchannel::linear, lock, dahdi_pvt::logicalspan, dahdi_pvt::master, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_accept_on_offer, dahdi_pvt::mfcr2_allow_collect_calls, dahdi_pvt::mfcr2_charge_calls, dahdi_pvt::mfcr2_forced_release, dahdi_pvt::mfcr2block, dahdi_pvt::mfcr2call, ast_channel::name, dahdi_pvt::next, NUM_SPANS, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pri::pri, pris, dahdi_pvt::propconfno, dahdi_pvt::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::resetting, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, dahdi_pvt::sig, sig2str, dahdi_pvt::slaves, dahdi_pvt::span, SUB_CALLWAIT, SUB_THREEWAY, and dahdi_pvt::subs.

12143 {
12144    int channel;
12145    struct dahdi_pvt *tmp = NULL;
12146    struct dahdi_confinfo ci;
12147    struct dahdi_params ps;
12148    int x;
12149    ast_mutex_t *lock;
12150    struct dahdi_pvt *start;
12151 #ifdef HAVE_PRI
12152    char *c;
12153    int trunkgroup;
12154    struct dahdi_pri *pri=NULL;
12155 #endif
12156 
12157    lock = &iflock;
12158    start = iflist;
12159 
12160    if (argc != 4)
12161       return RESULT_SHOWUSAGE;
12162 #ifdef HAVE_PRI
12163    if ((c = strchr(argv[3], ':'))) {
12164       if (sscanf(argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
12165          return RESULT_SHOWUSAGE;
12166       if ((trunkgroup < 1) || (channel < 1))
12167          return RESULT_SHOWUSAGE;
12168       for (x = 0; x < NUM_SPANS; x++) {
12169          if (pris[x].trunkgroup == trunkgroup) {
12170             pri = pris + x;
12171             break;
12172          }
12173       }
12174       if (pri) {
12175          start = pri->crvs;
12176          lock = &pri->lock;
12177       } else {
12178          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
12179          return RESULT_FAILURE;
12180       }
12181    } else
12182 #endif
12183       channel = atoi(argv[3]);
12184 
12185    ast_mutex_lock(lock);
12186    tmp = start;
12187    while (tmp) {
12188       if (tmp->channel == channel) {
12189 #ifdef HAVE_PRI
12190          if (pri) 
12191             ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
12192          else
12193 #endif         
12194          ast_cli(fd, "Channel: %d\n", tmp->channel);
12195          ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
12196          ast_cli(fd, "Span: %d\n", tmp->span);
12197          ast_cli(fd, "Extension: %s\n", tmp->exten);
12198          ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
12199          ast_cli(fd, "Context: %s\n", tmp->context);
12200          ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
12201          ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
12202          ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
12203          ast_cli(fd, "Destroy: %d\n", tmp->destroy);
12204          ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
12205          ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
12206          ast_cli(fd, "Radio: %d\n", tmp->radio);
12207          ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
12208          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)" : "");
12209          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)" : "");
12210          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)" : "");
12211          ast_cli(fd, "Confno: %d\n", tmp->confno);
12212          ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
12213          ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
12214          ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
12215          ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
12216          ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
12217          ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
12218          ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
12219          ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
12220          ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
12221          if (tmp->master)
12222             ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
12223          for (x = 0; x < MAX_SLAVES; x++) {
12224             if (tmp->slaves[x])
12225                ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
12226          }
12227 #ifdef HAVE_OPENR2
12228          if (tmp->mfcr2) {
12229             char calldir[OR2_MAX_PATH];
12230             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
12231             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
12232             ast_cli(fd, "MFC/R2 Call: %s\n", tmp->mfcr2call ? "Yes" : "No");
12233             ast_cli(fd, "MFC/R2 Blocked: %s\n", tmp->mfcr2block ? "Yes" : "No");
12234             ast_cli(fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
12235             ast_cli(fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
12236             ast_cli(fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
12237             ast_cli(fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
12238             ast_cli(fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
12239             ast_cli(fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
12240             ast_cli(fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
12241             ast_cli(fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
12242 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
12243             ast_cli(fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
12244             ast_cli(fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
12245 #endif
12246             ast_cli(fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
12247             ast_cli(fd, "MFC/R2 Skip Category: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
12248             ast_cli(fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
12249             ast_cli(fd, "MFC/R2 Accept On Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
12250             ast_cli(fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
12251             ast_cli(fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
12252             ast_cli(fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
12253             ast_cli(fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
12254             ast_cli(fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
12255             ast_cli(fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
12256             ast_cli(fd, "MFC/R2 Tx CAS : %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
12257             ast_cli(fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
12258             ast_cli(fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
12259             ast_cli(fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
12260          }
12261 #endif
12262 #ifdef HAVE_PRI
12263          if (tmp->pri) {
12264             ast_cli(fd, "PRI Flags: ");
12265             if (tmp->resetting)
12266                ast_cli(fd, "Resetting ");
12267             if (tmp->call)
12268                ast_cli(fd, "Call ");
12269             if (tmp->bearer)
12270                ast_cli(fd, "Bearer ");
12271             ast_cli(fd, "\n");
12272             if (tmp->logicalspan) 
12273                ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
12274             else
12275                ast_cli(fd, "PRI Logical Span: Implicit\n");
12276          }
12277             
12278 #endif
12279          memset(&ci, 0, sizeof(ci));
12280          ps.channo = tmp->channel;
12281          if (tmp->subs[SUB_REAL].dfd > -1) {
12282             memset(&ci, 0, sizeof(ci));
12283             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
12284                ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
12285             }
12286 #ifdef DAHDI_GETCONFMUTE
12287             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
12288                ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
12289             }
12290 #endif
12291             memset(&ps, 0, sizeof(ps));
12292             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
12293                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
12294             } else {
12295                ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
12296             }
12297          }
12298          if (ISTRUNK(tmp)) {
12299             ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");  
12300             if (!ast_strlen_zero(progzone))
12301                ast_cli(fd, "Progress Zone: %s\n", progzone);
12302             ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");  
12303             if(tmp->busydetect) {
12304                ast_cli(fd, "Busy Count: %d\n", tmp->busycount);
12305                if(tmp->busytonelength > 0) {
12306                   ast_cli(fd, "Busy Pattern:\n");
12307                   ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
12308                   if (tmp->busyquietlength > 0) 
12309                      ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
12310                   else 
12311                      ast_cli(fd, " -- Detect Tone Only\n");
12312                   if(tmp->busyfuzziness > 0)
12313                      ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
12314                }
12315             }
12316          }
12317          ast_mutex_unlock(lock);
12318          return RESULT_SUCCESS;
12319       }
12320       tmp = tmp->next;
12321    }
12322    
12323    ast_cli(fd, "Unable to find given channel %d\n", channel);
12324    ast_mutex_unlock(lock);
12325    return RESULT_FAILURE;
12326 }

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

Definition at line 12081 of file chan_dahdi.c.

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

12082 {
12083 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
12084 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
12085    struct dahdi_pvt *tmp = NULL;
12086    char tmps[20] = "";
12087    ast_mutex_t *lock;
12088    struct dahdi_pvt *start;
12089 #ifdef HAVE_PRI
12090    int trunkgroup;
12091    struct dahdi_pri *pri = NULL;
12092    int x;
12093 #endif
12094 
12095    lock = &iflock;
12096    start = iflist;
12097 
12098 #ifdef HAVE_PRI
12099    if (argc == 4) {
12100       if ((trunkgroup = atoi(argv[3])) < 1)
12101          return RESULT_SHOWUSAGE;
12102       for (x = 0; x < NUM_SPANS; x++) {
12103          if (pris[x].trunkgroup == trunkgroup) {
12104             pri = pris + x;
12105             break;
12106          }
12107       }
12108       if (pri) {
12109          start = pri->crvs;
12110          lock = &pri->lock;
12111       } else {
12112          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
12113          return RESULT_FAILURE;
12114       }
12115    } else
12116 #endif
12117    if (argc != 3)
12118       return RESULT_SHOWUSAGE;
12119 
12120    ast_mutex_lock(lock);
12121 #ifdef HAVE_PRI
12122    ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
12123 #else
12124    ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
12125 #endif   
12126    
12127    tmp = start;
12128    while (tmp) {
12129       if (tmp->channel > 0) {
12130          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
12131       } else
12132          ast_copy_string(tmps, "pseudo", sizeof(tmps));
12133       ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
12134       tmp = tmp->next;
12135    }
12136    ast_mutex_unlock(lock);
12137    return RESULT_SUCCESS;
12138 #undef FORMAT
12139 #undef FORMAT2
12140 }

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

Definition at line 12359 of file chan_dahdi.c.

References alarms, ast_cli(), ast_log(), DAHDI_FILE_CTL, errno, FORMAT, FORMAT2, RESULT_FAILURE, and dahdi_pri::span.

12359                                                              {
12360    #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
12361    #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
12362 
12363    int span;
12364    int res;
12365    char alarms[50];
12366 
12367    int ctl;
12368    struct dahdi_spaninfo s;
12369 
12370    if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) {
12371       ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno));
12372       ast_cli(fd, "No " DAHDI_NAME " interface found.\n");
12373       return RESULT_FAILURE;
12374    }
12375    ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
12376 
12377    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
12378       s.spanno = span;
12379       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
12380       if (res) {
12381          continue;
12382       }
12383       alarms[0] = '\0';
12384       if (s.alarms > 0) {
12385          if (s.alarms & DAHDI_ALARM_BLUE)
12386             strcat(alarms, "BLU/");
12387          if (s.alarms & DAHDI_ALARM_YELLOW)
12388             strcat(alarms, "YEL/");
12389          if (s.alarms & DAHDI_ALARM_RED)
12390             strcat(alarms, "RED/");
12391          if (s.alarms & DAHDI_ALARM_LOOPBACK)
12392             strcat(alarms, "LB/");
12393          if (s.alarms & DAHDI_ALARM_RECOVER)
12394             strcat(alarms, "REC/");
12395          if (s.alarms & DAHDI_ALARM_NOTOPEN)
12396             strcat(alarms, "NOP/");
12397          if (!strlen(alarms))
12398             strcat(alarms, "UUU/");
12399          if (strlen(alarms)) {
12400             /* Strip trailing / */
12401             alarms[strlen(alarms) - 1] = '\0';
12402          }
12403       } else {
12404          if (s.numchans)
12405             strcpy(alarms, "OK");
12406          else
12407             strcpy(alarms, "UNCONFIGURED");
12408       }
12409 
12410       ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
12411    }
12412    close(ctl);
12413 
12414    return RESULT_SUCCESS;
12415 #undef FORMAT
12416 #undef FORMAT2
12417 }

static char* dahdi_sig2str ( int  sig  )  [static]

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

02105 {
02106    static char buf[256];
02107    switch (sig) {
02108    case SIG_EM:
02109       return "E & M Immediate";
02110    case SIG_EMWINK:
02111       return "E & M Wink";
02112    case SIG_EM_E1:
02113       return "E & M E1";
02114    case SIG_FEATD:
02115       return "Feature Group D (DTMF)";
02116    case SIG_FEATDMF:
02117       return "Feature Group D (MF)";
02118    case SIG_FEATDMF_TA:
02119       return "Feature Groud D (MF) Tandem Access";
02120    case SIG_FEATB:
02121       return "Feature Group B (MF)";
02122    case SIG_E911:
02123       return "E911 (MF)";
02124    case SIG_FGC_CAMA:
02125       return "FGC/CAMA (Dialpulse)";
02126    case SIG_FGC_CAMAMF:
02127       return "FGC/CAMA (MF)";
02128    case SIG_FXSLS:
02129       return "FXS Loopstart";
02130    case SIG_FXSGS:
02131       return "FXS Groundstart";
02132    case SIG_FXSKS:
02133       return "FXS Kewlstart";
02134    case SIG_FXOLS:
02135       return "FXO Loopstart";
02136    case SIG_FXOGS:
02137       return "FXO Groundstart";
02138    case SIG_FXOKS:
02139       return "FXO Kewlstart";
02140    case SIG_PRI:
02141       return "ISDN PRI";
02142    case SIG_MFCR2:
02143       return "MFC/R2";
02144    case SIG_SF:
02145       return "SF (Tone) Immediate";
02146    case SIG_SFWINK:
02147       return "SF (Tone) Wink";
02148    case SIG_SF_FEATD:
02149       return "SF (Tone) with Feature Group D (DTMF)";
02150    case SIG_SF_FEATDMF:
02151       return "SF (Tone) with Feature Group D (MF)";
02152    case SIG_SF_FEATB:
02153       return "SF (Tone) with Feature Group B (MF)";
02154    case SIG_GR303FXOKS:
02155       return "GR-303 with FXOKS";
02156    case SIG_GR303FXSKS:
02157       return "GR-303 with FXSKS";
02158    case 0:
02159       return "Pseudo";
02160    default:
02161       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
02162       return buf;
02163    }
02164 }

static void dahdi_softhangup_all ( void   )  [static]

Definition at line 11933 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, iflock, dahdi_pvt::lock, ast_channel::name, dahdi_pvt::next, option_debug, dahdi_pvt::owner, and dahdi_pvt::restartpending.

Referenced by dahdi_restart().

11934 {
11935    struct dahdi_pvt *p;
11936 retry:
11937    ast_mutex_lock(&iflock);
11938     for (p = iflist; p; p = p->next) {
11939       ast_mutex_lock(&p->lock);
11940         if (p->owner && !p->restartpending) {
11941          if (ast_channel_trylock(p->owner)) {
11942             if (option_debug > 2)
11943                ast_verbose("Avoiding deadlock\n");
11944             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
11945             ast_mutex_unlock(&p->lock);
11946             ast_mutex_unlock(&iflock);
11947             goto retry;
11948          }
11949          if (option_debug > 2)
11950             ast_verbose("Softhanging up on %s\n", p->owner->name);
11951          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
11952          p->restartpending = 1;
11953          num_restart_pending++;
11954          ast_channel_unlock(p->owner);
11955       }
11956       ast_mutex_unlock(&p->lock);
11957     }
11958    ast_mutex_unlock(&iflock);
11959 }

static void dahdi_train_ec ( struct dahdi_pvt p  )  [static]

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

02386 {
02387    int x;
02388    int res;
02389    if (p && p->echocancel && p->echotraining) {
02390       x = p->echotraining;
02391       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02392       if (res)
02393          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02394       else {
02395          ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
02396       }
02397    } else
02398       ast_log(LOG_DEBUG, "No echo training requested\n");
02399 }

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

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

04256 {
04257    /* Unlink a specific slave or all slaves/masters from a given master */
04258    int x;
04259    int hasslaves;
04260    if (!master)
04261       return;
04262    if (needlock) {
04263       ast_mutex_lock(&master->lock);
04264       if (slave) {
04265          while (ast_mutex_trylock(&slave->lock)) {
04266             DEADLOCK_AVOIDANCE(&master->lock);
04267          }
04268       }
04269    }
04270    hasslaves = 0;
04271    for (x = 0; x < MAX_SLAVES; x++) {
04272       if (master->slaves[x]) {
04273          if (!slave || (master->slaves[x] == slave)) {
04274             /* Take slave out of the conference */
04275             ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
04276             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
04277             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
04278             master->slaves[x]->master = NULL;
04279             master->slaves[x] = NULL;
04280          } else
04281             hasslaves = 1;
04282       }
04283       if (!hasslaves)
04284          master->inconference = 0;
04285    }
04286    if (!slave) {
04287       if (master->master) {
04288          /* Take master out of the conference */
04289          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
04290          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
04291          hasslaves = 0;
04292          for (x = 0; x < MAX_SLAVES; x++) {
04293             if (master->master->slaves[x] == master)
04294                master->master->slaves[x] = NULL;
04295             else if (master->master->slaves[x])
04296                hasslaves = 1;
04297          }
04298          if (!hasslaves)
04299             master->master->inconference = 0;
04300       }
04301       master->master = NULL;
04302    }
04303    update_conf(master);
04304    if (needlock) {
04305       if (slave)
04306          ast_mutex_unlock(&slave->lock);
04307       ast_mutex_unlock(&master->lock);
04308    }
04309 }

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

Avoid the silly dahdi_waitevent which ignores a bunch of events.

Definition at line 281 of file chan_dahdi.c.

Referenced by ss_thread().

00282 {
00283    int i, j = 0;
00284    i = DAHDI_IOMUX_SIGEVENT;
00285    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00286       return -1;
00287    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00288       return -1;
00289    return j;
00290 }

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

Definition at line 6739 of file chan_dahdi.c.

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

Referenced by ss_thread().

06740 {
06741    int j;
06742    dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
06743    for (;;)
06744    {
06745          /* set bits of interest */
06746       j = DAHDI_IOMUX_SIGEVENT;
06747           /* wait for some happening */
06748       if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
06749          /* exit loop if we have it */
06750       if (j & DAHDI_IOMUX_SIGEVENT) break;
06751    }
06752      /* get the event info */
06753    if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
06754    return 0;
06755 }

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

Definition at line 6252 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::call, 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(), ast_channel::name, option_debug, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, PVT_TO_CHANNEL, dahdi_pvt::sig, SIG_PRI, dahdi_pvt::span, ast_frame::subclass, dahdi_pvt::subs, and ast_channel::tech_pvt.

06253 {
06254    struct dahdi_pvt *p = ast->tech_pvt;
06255    int res;
06256    int index;
06257    index = dahdi_get_index(ast, p, 0);
06258    if (index < 0) {
06259       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
06260       return -1;
06261    }
06262 
06263 #if 0
06264 #ifdef HAVE_PRI
06265    ast_mutex_lock(&p->lock);
06266    if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06267       if (p->pri->pri) {      
06268          if (!pri_grab(p, p->pri)) {
06269                pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06270                pri_rel(p->pri);
06271          } else
06272                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06273       }
06274       p->proceeding=1;
06275    }
06276    ast_mutex_unlock(&p->lock);
06277 #endif
06278 #endif
06279    /* Write a frame of (presumably voice) data */
06280    if (frame->frametype != AST_FRAME_VOICE) {
06281       if (frame->frametype != AST_FRAME_IMAGE)
06282          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
06283       return 0;
06284    }
06285    if ((frame->subclass != AST_FORMAT_SLINEAR) && 
06286        (frame->subclass != AST_FORMAT_ULAW) &&
06287        (frame->subclass != AST_FORMAT_ALAW)) {
06288       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
06289       return -1;
06290    }
06291    if (p->dialing) {
06292       if (option_debug)
06293          ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
06294       return 0;
06295    }
06296    if (!p->owner) {
06297       if (option_debug)
06298          ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
06299       return 0;
06300    }
06301    if (p->cidspill) {
06302       if (option_debug)
06303          ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
06304       return 0;
06305    }
06306    /* Return if it's not valid data */
06307    if (!frame->data || !frame->datalen)
06308       return 0;
06309 
06310    if (frame->subclass == AST_FORMAT_SLINEAR) {
06311       if (!p->subs[index].linear) {
06312          p->subs[index].linear = 1;
06313          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06314          if (res)
06315             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
06316       }
06317       res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
06318    } else {
06319       /* x-law already */
06320       if (p->subs[index].linear) {
06321          p->subs[index].linear = 0;
06322          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06323          if (res)
06324             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
06325       }
06326       res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
06327    }
06328    if (res < 0) {
06329       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
06330       return -1;
06331    } 
06332    return 0;
06333 }

static void destroy_all_channels ( void   )  [static]

Definition at line 3256 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, iflock, dahdi_pvt::next, option_verbose, and VERBOSE_PREFIX_2.

Referenced by __unload_module(), and dahdi_restart().

03257 {
03258    int x;
03259    struct dahdi_pvt *p, *pl;
03260 
03261    while (num_restart_pending) {
03262       usleep(1);
03263    }
03264 
03265    ast_mutex_lock(&iflock);
03266    /* Destroy all the interfaces and free their memory */
03267    p = iflist;
03268    while (p) {
03269       /* Free any callerid */
03270       if (p->cidspill)
03271          ast_free(p->cidspill);
03272       pl = p;
03273       p = p->next;
03274       x = pl->channel;
03275       /* Free associated memory */
03276       if (pl)
03277          destroy_dahdi_pvt(&pl);
03278       if (option_verbose > 2) 
03279          ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03280    }
03281    iflist = NULL;
03282    ifcount = 0;
03283    ast_mutex_unlock(&iflock);
03284 }

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

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

03207 {
03208    int owned = 0;
03209    int i = 0;
03210 
03211    if (!now) {
03212       if (cur->owner) {
03213          owned = 1;
03214       }
03215 
03216       for (i = 0; i < 3; i++) {
03217          if (cur->subs[i].owner) {
03218             owned = 1;
03219          }
03220       }
03221       if (!owned) {
03222          if (prev) {
03223             prev->next = cur->next;
03224             if (prev->next)
03225                prev->next->prev = prev;
03226             else
03227                ifend = prev;
03228          } else {
03229             iflist = cur->next;
03230             if (iflist)
03231                iflist->prev = NULL;
03232             else
03233                ifend = NULL;
03234          }
03235          destroy_dahdi_pvt(&cur);
03236       }
03237    } else {
03238       if (prev) {
03239          prev->next = cur->next;
03240          if (prev->next)
03241             prev->next->prev = prev;
03242          else
03243             ifend = prev;
03244       } else {
03245          iflist = cur->next;
03246          if (iflist)
03247             iflist->prev = NULL;
03248          else
03249             ifend = NULL;
03250       }
03251       destroy_dahdi_pvt(&cur);
03252    }
03253    return 0;
03254 }

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

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

03189 {
03190    struct dahdi_pvt *p = *pvt;
03191    /* Remove channel from the list */
03192    if (p->prev)
03193       p->prev->next = p->next;
03194    if (p->next)
03195       p->next->prev = p->prev;
03196    if (p->use_smdi)
03197       ast_smdi_interface_unref(p->smdi_iface);
03198    ast_mutex_destroy(&p->lock);
03199    dahdi_close_sub(p, SUB_REAL);
03200    if (p->owner)
03201       p->owner->tech_pvt = NULL;
03202    free(p);
03203    *pvt = NULL;
03204 }

static char* dialplan2str ( int  dialplan  )  [static]

Definition at line 2095 of file chan_dahdi.c.

Referenced by dahdi_call(), and mkintf().

02096 {
02097    if (dialplan == -1) {
02098       return("Dynamically set dialplan in ISDN");
02099    }
02100    return (pri_plan2str(dialplan));
02101 }

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 1928 of file chan_dahdi.c.

Referenced by dahdi_digit_begin().

01929 {
01930    if (isdigit(digit))
01931       return DAHDI_TONE_DTMF_BASE + (digit - '0');
01932    else if (digit >= 'A' && digit <= 'D')
01933       return DAHDI_TONE_DTMF_A + (digit - 'A');
01934    else if (digit >= 'a' && digit <= 'd')
01935       return DAHDI_TONE_DTMF_A + (digit - 'a');
01936    else if (digit == '*')
01937       return DAHDI_TONE_DTMF_s;
01938    else if (digit == '#')
01939       return DAHDI_TONE_DTMF_p;
01940    else
01941       return -1;
01942 }

static void disable_dtmf_detect ( struct dahdi_pvt p  )  [static]

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

04335 {
04336 #ifdef DAHDI_TONEDETECT
04337    int val;
04338 #endif
04339 
04340    p->ignoredtmf = 1;
04341 
04342 #ifdef DAHDI_TONEDETECT
04343    val = 0;
04344    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04345 #endif      
04346    if (!p->hardwaredtmf && p->dsp) {
04347       p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
04348       ast_dsp_set_features(p->dsp, p->dsp_features);
04349    }
04350 }

static void* do_idle_thread ( void *  vchan  )  [static]

Definition at line 9804 of file chan_dahdi.c.

References ast_call(), AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, ast_copy_string(), AST_FRAME_CONTROL, ast_frfree, ast_hangup(), ast_log(), ast_pbx_run(), ast_read(), ast_verbose(), ast_waitfor(), dahdi_pvt::channel, ast_channel::context, ast_channel::exten, f, dahdi_pri::idlecontext, dahdi_pri::idledial, dahdi_pri::idleext, ast_channel::name, option_verbose, dahdi_pvt::pri, ast_channel::priority, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.

Referenced by pri_dchannel().

09805 {
09806    struct ast_channel *chan = vchan;
09807    struct dahdi_pvt *pvt = chan->tech_pvt;
09808    struct ast_frame *f;
09809    char ex[80];
09810    /* Wait up to 30 seconds for an answer */
09811    int newms, ms = 30000;
09812    if (option_verbose > 2) 
09813       ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
09814    snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
09815    if (ast_call(chan, ex, 0)) {
09816       ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
09817       ast_hangup(chan);
09818       return NULL;
09819    }
09820    while ((newms = ast_waitfor(chan, ms)) > 0) {
09821       f = ast_read(chan);
09822       if (!f) {
09823          /* Got hangup */
09824          break;
09825       }
09826       if (f->frametype == AST_FRAME_CONTROL) {
09827          switch (f->subclass) {
09828          case AST_CONTROL_ANSWER:
09829             /* Launch the PBX */
09830             ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
09831             ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
09832             chan->priority = 1;
09833             if (option_verbose > 3) 
09834                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
09835             ast_pbx_run(chan);
09836             /* It's already hungup, return immediately */
09837             return NULL;
09838          case AST_CONTROL_BUSY:
09839             if (option_verbose > 3) 
09840                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
09841             break;
09842          case AST_CONTROL_CONGESTION:
09843             if (option_verbose > 3) 
09844                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
09845             break;
09846          };
09847       }
09848       ast_frfree(f);
09849       ms = newms;
09850    }
09851    /* Hangup the channel since nothing happend */
09852    ast_hangup(chan);
09853    return NULL;
09854 }

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

Definition at line 8165 of file chan_dahdi.c.

References ast_calloc, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, dahdi_pvt::cidspill, free, iflist, iflock, last, LOG_DEBUG, dahdi_pvt::owner, dahdi_pvt::radio, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, SUB_REAL, and dahdi_pvt::subs.

Referenced by restart_monitor().

08166 {
08167    int count, res, res2, spoint, pollres=0;
08168    struct dahdi_pvt *i;
08169    struct dahdi_pvt *last = NULL;
08170    struct dahdi_pvt *doomed;
08171    time_t thispass = 0, lastpass = 0;
08172    int found;
08173    char buf[1024];
08174    struct pollfd *pfds=NULL;
08175    int lastalloc = -1;
08176    /* This thread monitors all the frame relay interfaces which are not yet in use
08177       (and thus do not have a separate thread) indefinitely */
08178    /* From here on out, we die whenever asked */
08179 #if 0
08180    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
08181       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
08182       return NULL;
08183    }
08184    ast_log(LOG_DEBUG, "Monitor starting...\n");
08185 #endif
08186    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08187 
08188    for (;;) {
08189       /* Lock the interface list */
08190       ast_mutex_lock(&iflock);
08191       if (!pfds || (lastalloc != ifcount)) {
08192          if (pfds) {
08193             free(pfds);
08194             pfds = NULL;
08195          }
08196          if (ifcount) {
08197             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
08198                ast_mutex_unlock(&iflock);
08199                return NULL;
08200             }
08201          }
08202          lastalloc = ifcount;
08203       }
08204       /* Build the stuff we're going to poll on, that is the socket of every
08205          dahdi_pvt that does not have an associated owner channel */
08206       count = 0;
08207       i = iflist;
08208       while (i) {
08209          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
08210             if (!i->owner && !i->subs[SUB_REAL].owner) {
08211                /* This needs to be watched, as it lacks an owner */
08212                pfds[count].fd = i->subs[SUB_REAL].dfd;
08213                pfds[count].events = POLLPRI;
08214                pfds[count].revents = 0;
08215                /* Message waiting or r2 channels also get watched for reading */
08216                if (i->cidspill ||
08217                    (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
08218                   pfds[count].events |= POLLIN;
08219                }
08220                count++;
08221             }
08222          }
08223          i = i->next;
08224       }
08225       /* Okay, now that we know what to do, release the interface lock */
08226       ast_mutex_unlock(&iflock);
08227       
08228       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08229       pthread_testcancel();
08230       /* Wait at least a second for something to happen */
08231       res = poll(pfds, count, 1000);
08232       pthread_testcancel();
08233       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08234 
08235       /* Okay, poll has finished.  Let's see what happened.  */
08236       if (res < 0) {
08237          if ((errno != EAGAIN) && (errno != EINTR))
08238             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
08239          continue;
08240       }
08241       /* Alright, lock the interface list again, and let's look and see what has
08242          happened */
08243       ast_mutex_lock(&iflock);
08244       found = 0;
08245       spoint = 0;
08246       lastpass = thispass;
08247       thispass = time(NULL);
08248       doomed = NULL;
08249       for (i = iflist;; i = i->next) {
08250          if (doomed) {
08251             int res;
08252             res = dahdi_destroy_channel_bynum(doomed->channel);
08253             if (!res) {
08254                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
08255             }
08256             doomed = NULL;
08257          }
08258          if (!i) {
08259             break;
08260          }
08261          if (thispass != lastpass) {
08262             if (!found && ((i == last) || ((i == iflist) && !last))) {
08263                last = i;
08264                if (last) {
08265                   if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
08266                      (last->sig & __DAHDI_SIG_FXO)) {
08267                      res = ast_app_has_voicemail(last->mailbox, NULL);
08268                      if (last->msgstate != res) {
08269                         int x;
08270                         ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
08271                         x = DAHDI_FLUSH_BOTH;
08272                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
08273                         if (res2)
08274                            ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
08275                         if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
08276                            /* Turn on on hook transfer for 4 seconds */
08277                            x = 4000;
08278                            ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
08279                            last->cidlen = ast_callerid_vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
08280                            last->cidpos = 0;
08281                            last->msgstate = res;
08282                            last->onhooktime = thispass;
08283                         }
08284                         found ++;
08285                      }
08286                   }
08287                   last = last->next;
08288                }
08289             }
08290          }
08291          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
08292             if (i->radio && !i->owner)
08293             {
08294                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08295                if (res)
08296                {
08297                   if (option_debug)
08298                      ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
08299                   /* Don't hold iflock while handling init events */
08300                   ast_mutex_unlock(&iflock);
08301                   doomed = handle_init_event(i, res);
08302                   ast_mutex_lock(&iflock);   
08303                }
08304                continue;
08305             }              
08306             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
08307             if (pollres & POLLIN) {
08308                if (i->owner || i->subs[SUB_REAL].owner) {
08309 #ifdef HAVE_PRI
08310                   if (!i->pri)
08311 #endif                  
08312                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
08313                   continue;
08314                }
08315                //             if (!i->cidspill) {
08316                // ast_log(LOG_WARNING, "Whoa....  I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
08317                // continue;
08318                //}
08319                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
08320                if (res > 0) {
08321                   /* We read some number of bytes.  Write an equal amount of data */
08322 /*                   if (res > i->cidlen - i->cidpos)  */
08323 /*                      res = i->cidlen - i->cidpos; */
08324 /*                   res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res); */
08325 /*                   if (res2 > 0) { */
08326 /*                      i->cidpos += res2; */
08327 /*                      if (i->cidpos >= i->cidlen) { */
08328 /*                         free(i->cidspill); */
08329 /*                         i->cidspill = 0; */
08330 /*                         i->cidpos = 0; */
08331 /*                         i->cidlen = 0; */
08332                   /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
08333                   if (i->cid_start == CID_START_DTMF_NOALERT) {
08334                      int energy;
08335                      struct timeval now;
08336                      /* State machine dtmfcid_holdoff_state allows for the line to settle
08337                       * before checking agin for dtmf energy.  Presently waits for 500 mS before checking again
08338                      */
08339                      if (1 == i->dtmfcid_holdoff_state) {
08340                         gettimeofday(&i->dtmfcid_delay, NULL);
08341                         i->dtmfcid_holdoff_state = 2;
08342                      } else if (2 == i->dtmfcid_holdoff_state) {
08343                         gettimeofday(&now, NULL);
08344                         if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
08345                            i->dtmfcid_holdoff_state = 0;
08346                         }
08347                      } else {
08348                         energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
08349                         if (energy > dtmfcid_level) {
08350                            pthread_t threadid;
08351                            struct ast_channel *chan;
08352                            ast_mutex_unlock(&iflock);
08353                            chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08354                            if (!chan) {
08355                               ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08356                            } else {
08357                               pthread_attr_t attr;
08358                               pthread_attr_init(&attr);
08359                               pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08360                               res = ast_pthread_create(&threadid, &attr, ss_thread, chan);
08361                               if (res) {
08362                                  ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08363                               } else {
08364                                  i->dtmfcid_holdoff_state = 1;
08365                               }
08366                            }
08367                            ast_mutex_lock(&iflock);
08368                         }
08369                      }
08370 /*                   } else { */
08371 /*                      ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno)); */
08372 /*                      i->msgstate = -1; */
08373                   }
08374                } else {
08375                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
08376                }
08377             }
08378             if (pollres & POLLPRI) {
08379                if (i->owner || i->subs[SUB_REAL].owner) {
08380 #ifdef HAVE_PRI
08381                   if (!i->pri)
08382 #endif                  
08383                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
08384                   continue;
08385                }
08386                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08387                if (option_debug)
08388                   ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
08389                /* Don't hold iflock while handling init events */
08390                ast_mutex_unlock(&iflock);
08391                doomed = handle_init_event(i, res);
08392                ast_mutex_lock(&iflock);   
08393             }
08394          }
08395       }
08396       ast_mutex_unlock(&iflock);
08397    }
08398    /* Never reached */
08399    return NULL;
08400    
08401 }

static void enable_dtmf_detect ( struct dahdi_pvt p  )  [static]

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

04353 {
04354 #ifdef DAHDI_TONEDETECT
04355    int val;
04356 #endif
04357 
04358    if (p->channel == CHAN_PSEUDO)
04359       return;
04360 
04361    p->ignoredtmf = 0;
04362 
04363 #ifdef DAHDI_TONEDETECT
04364    val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
04365    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04366 #endif      
04367    if (!p->hardwaredtmf && p->dsp) {
04368       p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
04369       ast_dsp_set_features(p->dsp, p->dsp_features);
04370    }
04371 }

static char* event2str ( int  event  )  [static]

Definition at line 2085 of file chan_dahdi.c.

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

02086 {
02087    static char buf[256];
02088    if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
02089       return events[event];
02090    sprintf(buf, "Event %d", event); /* safe */
02091    return buf;
02092 }

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

Definition at line 2450 of file chan_dahdi.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_rxgain().

02451 {
02452    int j;
02453    int k;
02454    float linear_gain = pow(10.0, gain / 20.0);
02455 
02456    switch (law) {
02457    case DAHDI_LAW_ALAW:
02458       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
02459          if (gain) {
02460             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02461             if (k > 32767) k = 32767;
02462             if (k < -32767) k = -32767;
02463             g->rxgain[j] = AST_LIN2A(k);
02464          } else {
02465             g->rxgain[j] = j;
02466          }
02467       }
02468       break;
02469    case DAHDI_LAW_MULAW:
02470       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
02471          if (gain) {
02472             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02473             if (k > 32767) k = 32767;
02474             if (k < -32767) k = -32767;
02475             g->rxgain[j] = AST_LIN2MU(k);
02476          } else {
02477             g->rxgain[j] = j;
02478          }
02479       }
02480       break;
02481    }
02482 }

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

Definition at line 2416 of file chan_dahdi.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_txgain().

02417 {
02418    int j;
02419    int k;
02420    float linear_gain = pow(10.0, gain / 20.0);
02421 
02422    switch (law) {
02423    case DAHDI_LAW_ALAW:
02424       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
02425          if (gain) {
02426             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02427             if (k > 32767) k = 32767;
02428             if (k < -32767) k = -32767;
02429             g->txgain[j] = AST_LIN2A(k);
02430          } else {
02431             g->txgain[j] = j;
02432          }
02433       }
02434       break;
02435    case DAHDI_LAW_MULAW:
02436       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
02437          if (gain) {
02438             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02439             if (k > 32767) k = 32767;
02440             if (k < -32767) k = -32767;
02441             g->txgain[j] = AST_LIN2MU(k);
02442          } else {
02443             g->txgain[j] = j;
02444          }
02445       }
02446       break;
02447    }
02448 }

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

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

12518 {
12519    struct dahdi_pvt *p = iflist;
12520    while (p) {
12521       if (p->channel == channel) {
12522          break;
12523       }
12524       p = p->next;
12525    }
12526    return p;
12527 }

static int get_alarms ( struct dahdi_pvt p  )  [static]

Definition at line 4792 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(), dahdi_r2_on_hardware_alarm(), and handle_init_event().

04793 {
04794    int res;
04795    struct dahdi_spaninfo zi;
04796 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
04797    /*
04798     * The conditional compilation is needed only in asterisk-1.4 for
04799     * backward compatibility with old zaptel drivers that don't have
04800     * a DAHDI_PARAMS.chan_alarms field.
04801     */
04802    struct dahdi_params params;
04803 #endif
04804 
04805    memset(&zi, 0, sizeof(zi));
04806    zi.spanno = p->span;
04807 
04808    /* First check for span alarms */
04809    if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) {
04810       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
04811       return 0;
04812    }
04813    if (zi.alarms != DAHDI_ALARM_NONE)
04814       return zi.alarms;
04815 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
04816    /* No alarms on the span. Check for channel alarms. */
04817    memset(&params, 0, sizeof(params));
04818    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
04819       return params.chan_alarms;
04820    /* ioctl failed */
04821    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
04822 #endif
04823    return DAHDI_ALARM_NONE;
04824 }

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

Definition at line 4908 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(), dahdi_r2_on_hardware_alarm(), and handle_init_event().

04909 {
04910    const char *alarm_str = alarm2str(alarms);
04911    
04912    /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code
04913     * doesn't know what to do with it.  Don't confuse users with log messages. */
04914    if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
04915       p->unknown_alarm = 1;
04916       return;
04917    } else {
04918       p->unknown_alarm = 0;
04919    }
04920    
04921    ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
04922    manager_event(EVENT_FLAG_SYSTEM, "Alarm",
04923             "Alarm: %s\r\n"
04924             "Channel: %d\r\n",
04925             alarm_str, p->channel);
04926 }

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

Definition at line 12332 of file chan_dahdi.c.

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

12333 {
12334    int i, j;
12335    for (i = 0; i < num_cadence; i++) {
12336       char output[1024];
12337       char tmp[16], tmp2[64];
12338       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
12339       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
12340 
12341       for (j = 0; j < 16; j++) {
12342          if (cadences[i].ringcadence[j] == 0)
12343             break;
12344          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
12345          if (cidrings[i] * 2 - 1 == j)
12346             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
12347          else
12348             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
12349          if (j != 0)
12350             strncat(output, ",", sizeof(output) - strlen(output) - 1);
12351          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
12352       }
12353       ast_cli(fd,"%s\n",output);
12354    }
12355    return 0;
12356 }

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

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

07956 {
07957    int res;
07958    pthread_t threadid;
07959    pthread_attr_t attr;
07960    struct ast_channel *chan;
07961    pthread_attr_init(&attr);
07962    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
07963    /* Handle an event on a given channel for the monitor thread. */
07964    switch (event) {
07965    case DAHDI_EVENT_NONE:
07966    case DAHDI_EVENT_BITSCHANGED:
07967       break;
07968    case DAHDI_EVENT_WINKFLASH:
07969    case DAHDI_EVENT_RINGOFFHOOK:
07970       if (i->inalarm) break;
07971       if (i->radio) break;
07972       /* Got a ring/answer.  What kind of channel are we? */
07973       switch (i->sig) {
07974       case SIG_FXOLS:
07975       case SIG_FXOGS:
07976       case SIG_FXOKS:
07977          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07978          if (res && (errno == EBUSY))
07979             break;
07980          if (i->cidspill) {
07981             /* Cancel VMWI spill */
07982             free(i->cidspill);
07983             i->cidspill = NULL;
07984          }
07985          if (i->immediate) {
07986             dahdi_enable_ec(i);
07987             /* The channel is immediately up.  Start right away */
07988             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07989             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
07990             if (!chan) {
07991                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
07992                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07993                if (res < 0)
07994                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07995             }
07996          } else {
07997             /* Check for callerid, digits, etc */
07998             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
07999             if (chan) {
08000                if (has_voicemail(i))
08001                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08002                else
08003                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08004                if (res < 0) 
08005                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
08006                if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08007                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08008                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08009                   if (res < 0)
08010                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08011                   ast_hangup(chan);
08012                }
08013             } else
08014                ast_log(LOG_WARNING, "Unable to create channel\n");
08015          }
08016          break;
08017       case SIG_FXSLS:
08018       case SIG_FXSGS:
08019       case SIG_FXSKS:
08020             i->ringt = i->ringt_base;
08021             /* Fall through */
08022       case SIG_EMWINK:
08023       case SIG_FEATD:
08024       case SIG_FEATDMF:
08025       case SIG_FEATDMF_TA:
08026       case SIG_E911:
08027       case SIG_FGC_CAMA:
08028       case SIG_FGC_CAMAMF:
08029       case SIG_FEATB:
08030       case SIG_EM:
08031       case SIG_EM_E1:
08032       case SIG_SFWINK:
08033       case SIG_SF_FEATD:
08034       case SIG_SF_FEATDMF:
08035       case SIG_SF_FEATB:
08036       case SIG_SF:
08037             /* Check for callerid, digits, etc */
08038             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
08039             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08040                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08041                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08042                if (res < 0)
08043                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08044                ast_hangup(chan);
08045             } else if (!chan) {
08046                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08047             }
08048             break;
08049       default:
08050          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08051          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08052          if (res < 0)
08053                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08054          pthread_attr_destroy(&attr);
08055          return NULL;
08056       }
08057       break;
08058    case DAHDI_EVENT_NOALARM:
08059       i->inalarm = 0;
08060       if (!i->unknown_alarm) {
08061          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
08062          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
08063                   "Channel: %d\r\n", i->channel);
08064       } else {
08065          i->unknown_alarm = 0;
08066       }
08067       break;
08068    case DAHDI_EVENT_ALARM:
08069       i->inalarm = 1;
08070       res = get_alarms(i);
08071       handle_alarms(i, res);
08072       /* fall thru intentionally */
08073    case DAHDI_EVENT_ONHOOK:
08074       if (i->radio)
08075          break;
08076       /* Back on hook.  Hang up. */
08077       switch (i->sig) {
08078       case SIG_FXOLS:
08079       case SIG_FXOGS:
08080       case SIG_FEATD:
08081       case SIG_FEATDMF:
08082       case SIG_FEATDMF_TA:
08083       case SIG_E911:
08084       case SIG_FGC_CAMA:
08085       case SIG_FGC_CAMAMF:
08086       case SIG_FEATB:
08087       case SIG_EM:
08088       case SIG_EM_E1:
08089       case SIG_EMWINK:
08090       case SIG_SF_FEATD:
08091       case SIG_SF_FEATDMF:
08092       case SIG_SF_FEATB:
08093       case SIG_SF:
08094       case SIG_SFWINK:
08095       case SIG_FXSLS:
08096       case SIG_FXSGS:
08097       case SIG_FXSKS:
08098       case SIG_GR303FXSKS:
08099          dahdi_disable_ec(i);
08100          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08101          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08102          break;
08103       case SIG_GR303FXOKS:
08104       case SIG_FXOKS:
08105          dahdi_disable_ec(i);
08106          /* Diddle the battery for the zhone */
08107 #ifdef ZHONE_HACK
08108          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08109          usleep(1);
08110 #endif         
08111          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08112          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08113          break;
08114       case SIG_PRI:
08115          dahdi_disable_ec(i);
08116          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08117          break;
08118       default:
08119          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08120          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08121          pthread_attr_destroy(&attr);
08122          return NULL;
08123       }
08124       break;
08125    case DAHDI_EVENT_POLARITY:
08126       switch (i->sig) {
08127       case SIG_FXSLS:
08128       case SIG_FXSKS:
08129       case SIG_FXSGS:
08130          /* We have already got a PR before the channel was 
08131             created, but it wasn't handled. We need polarity 
08132             to be REV for remote hangup detection to work. 
08133             At least in Spain */
08134          if (i->hanguponpolarityswitch)
08135             i->polarity = POLARITY_REV;
08136 
08137          if (i->cid_start == CID_START_POLARITY) {
08138             i->polarity = POLARITY_REV;
08139             ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
08140                    "CID detection on channel %d\n",
08141                    i->channel);
08142             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08143             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08144                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08145             }
08146          }
08147          break;
08148       default:
08149          ast_log(LOG_WARNING, "handle_init_event detected "
08150             "polarity reversal on non-FXO (SIG_FXS) "
08151             "interface %d\n", i->channel);
08152       }
08153       break;
08154    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
08155       ast_log(LOG_NOTICE, 
08156             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 
08157             i->channel);
08158       pthread_attr_destroy(&attr);
08159       return i;
08160    }
08161    pthread_attr_destroy(&attr);
08162    return NULL;
08163 }

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

Definition at line 11740 of file chan_dahdi.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_true(), dahdi_pvt::channel, iflist, iflock, dahdi_pvt::next, dahdi_pvt::r2chan, RESULT_SHOWUSAGE, RESULT_SUCCESS, dahdi_pvt::sig, and SIG_MFCR2.

11741 {
11742    struct dahdi_pvt *p = NULL;
11743    int channo = 0;
11744    if (argc < 4) {
11745       return RESULT_SHOWUSAGE;
11746    }
11747    channo = (argc == 5) ? atoi(argv[4]) : -1;
11748    ast_mutex_lock(&iflock);
11749    p = iflist;
11750    while (p) {
11751       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11752          p = p->next;
11753          continue;
11754       }
11755       if ((channo != -1) && (p->channel != channo )) {
11756          p = p->next;
11757          continue;
11758       }
11759       if (ast_true(argv[3])) {
11760          openr2_chan_enable_call_files(p->r2chan);
11761       } else {
11762          openr2_chan_disable_call_files(p->r2chan);
11763       }
11764       if (channo != -1) {
11765          if (ast_true(argv[3])) {
11766             ast_cli(fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
11767          } else {
11768             ast_cli(fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
11769          }
11770          break;
11771       } else {
11772          p = p->next;
11773       }
11774    }
11775    if ((channo != -1) && !p) {
11776       ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11777    }
11778    if (channo == -1) {
11779       if (ast_true(argv[3])) {
11780          ast_cli(fd, "MFC/R2 Call files enabled for all channels.\n");
11781       } else {
11782          ast_cli(fd, "MFC/R2 Call files disabled for all channels.\n");
11783       }  
11784    }
11785    ast_mutex_unlock(&iflock);
11786    return RESULT_SUCCESS;
11787 }  

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

Definition at line 11824 of file chan_dahdi.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, DAHDI_R2_LOCAL_BLOCK, iflist, iflock, dahdi_pvt::lock, dahdi_pvt::mfcr2block, dahdi_pvt::next, dahdi_pvt::r2chan, RESULT_SUCCESS, dahdi_pvt::sig, and SIG_MFCR2.

11825 {
11826    struct dahdi_pvt *p = NULL;
11827    int channo = 0;
11828    channo = (argc == 4) ? atoi(argv[3]) : -1;
11829    ast_mutex_lock(&iflock);
11830    p = iflist;
11831    while (p) {
11832       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11833          p = p->next;
11834          continue;
11835       }
11836       if ((channo != -1) && (p->channel != channo )) {
11837          p = p->next;
11838          continue;
11839       }
11840       if (!openr2_chan_set_blocked(p->r2chan)) {
11841          ast_mutex_lock(&p->lock);
11842          p->mfcr2block |= DAHDI_R2_LOCAL_BLOCK;
11843          ast_mutex_unlock(&p->lock);
11844       } else {
11845          ast_cli(fd, "MFC/R2 channel %d could not be blocked.\n", p->channel);
11846       }
11847       if (channo != -1) {
11848          break;
11849       } else {
11850          p = p->next;
11851       }
11852    }
11853    if ((channo != -1) && !p) {
11854       ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11855    }
11856    ast_mutex_unlock(&iflock);
11857    return RESULT_SUCCESS;
11858 }

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

Definition at line 11681 of file chan_dahdi.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, dahdi_pvt::channel, iflist, iflock, dahdi_pvt::next, dahdi_pvt::r2chan, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, dahdi_pvt::sig, and SIG_MFCR2.

11682 {
11683    struct dahdi_pvt *p = NULL;
11684    int channo = 0;
11685    char *toklevel = NULL;
11686    char *saveptr = NULL;
11687    char *logval = NULL;
11688    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
11689    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
11690    if (argc < 4) {
11691       return RESULT_SHOWUSAGE;
11692    }
11693    channo = (argc == 5) ? atoi(argv[4]) : -1;
11694    logval = ast_strdupa(argv[3]);
11695    toklevel = strtok_r(logval, ",", &saveptr);
11696    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
11697       ast_cli(fd, "Invalid MFC/R2 logging level '%s'.\n", argv[3]);
11698       return RESULT_FAILURE;
11699    } else if (OR2_LOG_NOTHING == tmplevel) {
11700       loglevel = tmplevel;
11701    } else {
11702       loglevel |= tmplevel;
11703       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
11704          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
11705             ast_cli(fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
11706             continue;
11707          }
11708          loglevel |= tmplevel;
11709       }
11710    }
11711    ast_mutex_lock(&iflock);
11712    p = iflist;
11713    while (p) {
11714       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11715          p = p->next;
11716          continue;
11717       }
11718       if ((channo != -1) && (p->channel != channo )) {
11719          p = p->next;
11720          continue;
11721       }
11722       openr2_chan_set_log_level(p->r2chan, loglevel);
11723       if (channo != -1) {
11724          ast_cli(fd, "MFC/R2 debugging set to '%s' for channel %d.\n", argv[3], p->channel);
11725          break;
11726       } else {
11727          p = p->next;
11728       }
11729    }
11730    if ((channo != -1) && !p) {
11731       ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11732    }
11733    if (channo == -1) {
11734       ast_cli(fd, "MFC/R2 debugging set to '%s' for all channels.\n", argv[3]);
11735    }
11736    ast_mutex_unlock(&iflock);
11737    return RESULT_SUCCESS;
11738 }

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

Definition at line 11789 of file chan_dahdi.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, DAHDI_R2_LOCAL_BLOCK, iflist, iflock, dahdi_pvt::lock, dahdi_pvt::mfcr2block, dahdi_pvt::mfcr2call, dahdi_pvt::next, dahdi_pvt::r2chan, RESULT_SUCCESS, dahdi_pvt::sig, and SIG_MFCR2.

11790 {
11791    struct dahdi_pvt *p = NULL;
11792    int channo = 0;
11793    channo = (argc == 4) ? atoi(argv[3]) : -1;
11794    ast_mutex_lock(&iflock);
11795    p = iflist;
11796    while (p) {
11797       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11798          p = p->next;
11799          continue;
11800       }
11801       if ((channo != -1) && (p->channel != channo )) {
11802          p = p->next;
11803          continue;
11804       }
11805       if (!openr2_chan_set_idle(p->r2chan)) {
11806          ast_mutex_lock(&p->lock);
11807          p->mfcr2call = 0;
11808          p->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK;
11809          ast_mutex_unlock(&p->lock);
11810       }
11811       if (channo != -1) {
11812          break;
11813       } else {
11814          p = p->next;
11815       }
11816    }
11817    if ((channo != -1) && !p) {
11818       ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11819    }
11820    ast_mutex_unlock(&iflock);
11821    return RESULT_SUCCESS;
11822 }

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

Definition at line 11612 of file chan_dahdi.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, dahdi_pvt::context, FORMAT, dahdi_pvt::group, iflist, iflock, dahdi_pvt::next, dahdi_pvt::r2chan, RESULT_SHOWUSAGE, RESULT_SUCCESS, dahdi_pvt::sig, and SIG_MFCR2.

11613 {
11614 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
11615    int filtertype = 0;
11616    int targetnum = 0;
11617    char channo[5];
11618    char anino[5];
11619    char dnisno[5];
11620    struct dahdi_pvt *p;
11621    openr2_context_t *r2context;
11622    openr2_variant_t r2variant;
11623    if (!((argc == 3) || (argc == 5))) {
11624       return RESULT_SHOWUSAGE;
11625    }
11626    if (argc == 5) {
11627       if (!strcasecmp(argv[3], "group")) {
11628          targetnum = atoi(argv[4]);
11629          if ((targetnum < 0) || (targetnum > 63))
11630             return RESULT_SHOWUSAGE;
11631          targetnum = 1 << targetnum;
11632          filtertype = 1;
11633       } else if (!strcasecmp(argv[3], "context")) {
11634          filtertype = 2;
11635       } else {
11636          return RESULT_SHOWUSAGE;
11637       }
11638    }
11639    ast_cli(fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
11640    ast_mutex_lock(&iflock);
11641    p = iflist;
11642    while (p) {
11643       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11644          p = p->next;
11645          continue;
11646       }
11647       if (filtertype) {
11648          switch(filtertype) {
11649          case 1: /* mfcr2 show channels group <group> */
11650             if (p->group != targetnum) {
11651                p = p->next;
11652                continue;
11653             }
11654             break;
11655          case 2: /* mfcr2 show channels context <context> */
11656             if (strcasecmp(p->context, argv[4])) {
11657                p= p->next;
11658                continue;
11659             }
11660             break;
11661          default:
11662             ;
11663          }
11664       }
11665       r2context = openr2_chan_get_context(p->r2chan);
11666       r2variant = openr2_context_get_variant(r2context);
11667       snprintf(channo, sizeof(channo), "%d", p->channel);
11668       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
11669       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
11670       ast_cli(fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant), 
11671             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",  
11672             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
11673             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
11674       p = p->next;
11675    }
11676    ast_mutex_unlock(&iflock);
11677    return RESULT_SUCCESS;
11678 #undef FORMAT
11679 }

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

Definition at line 11594 of file chan_dahdi.c.

References ast_cli(), country, FORMAT, name, RESULT_FAILURE, and RESULT_SUCCESS.

11595 {
11596 #define FORMAT "%4s %40s\n"
11597    int numvariants = 0;
11598    int i;
11599    const openr2_variant_entry_t *variants;
11600    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
11601       ast_cli(fd, "Failed to get list of variants.\n");
11602       return RESULT_FAILURE;
11603    }
11604    ast_cli(fd, FORMAT, "Variant Code", "Country");
11605    for (i = 0; i < numvariants; i++) {
11606       ast_cli(fd, FORMAT, variants[i].name, variants[i].country);
11607    }
11608    return RESULT_SUCCESS;
11609 #undef FORMAT
11610 }  

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

Definition at line 11588 of file chan_dahdi.c.

References ast_cli(), and RESULT_SUCCESS.

11589 {
11590    ast_cli(fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
11591    return RESULT_SUCCESS;
11592 }

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

Definition at line 11341 of file chan_dahdi.c.

References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

11342 {
11343    int span;
11344    int x;
11345    if (argc < 4) {
11346       return RESULT_SHOWUSAGE;
11347    }
11348    span = atoi(argv[3]);
11349    if ((span < 1) || (span > NUM_SPANS)) {
11350       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
11351       return RESULT_SUCCESS;
11352    }
11353    if (!pris[span-1].pri) {
11354       ast_cli(fd, "No PRI running on span %d\n", span);
11355       return RESULT_SUCCESS;
11356    }
11357    for (x = 0; x < NUM_DCHANS; x++) {
11358       if (pris[span-1].dchans[x])
11359          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11360                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11361                                                PRI_DEBUG_Q921_STATE);
11362    }
11363    ast_cli(fd, "Enabled debugging on span %d\n", span);
11364    return RESULT_SUCCESS;
11365 }

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

Definition at line 11369 of file chan_dahdi.c.

References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

11370 {
11371    int span;
11372    int x;
11373    if (argc < 5)
11374       return RESULT_SHOWUSAGE;
11375    span = atoi(argv[4]);
11376    if ((span < 1) || (span > NUM_SPANS)) {
11377       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
11378       return RESULT_SUCCESS;
11379    }
11380    if (!pris[span-1].pri) {
11381       ast_cli(fd, "No PRI running on span %d\n", span);
11382       return RESULT_SUCCESS;
11383    }
11384    for (x = 0; x < NUM_DCHANS; x++) {
11385       if (pris[span-1].dchans[x])
11386          pri_set_debug(pris[span-1].dchans[x], 0);
11387    }
11388    ast_cli(fd, "Disabled debugging on span %d\n", span);
11389    return RESULT_SUCCESS;
11390 }

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

Definition at line 11392 of file chan_dahdi.c.

References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

11393 {
11394    int span;
11395    int x;
11396    if (argc < 5)
11397       return RESULT_SHOWUSAGE;
11398    span = atoi(argv[4]);
11399    if ((span < 1) || (span > NUM_SPANS)) {
11400       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
11401       return RESULT_SUCCESS;
11402    }
11403    if (!pris[span-1].pri) {
11404       ast_cli(fd, "No PRI running on span %d\n", span);
11405       return RESULT_SUCCESS;
11406    }
11407    for (x = 0; x < NUM_DCHANS; x++) {
11408       if (pris[span-1].dchans[x])
11409          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11410                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11411                                                PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
11412    }
11413    ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
11414    return RESULT_SUCCESS;
11415 }

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

Definition at line 11294 of file chan_dahdi.c.

References ast_cli(), ast_copy_string(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), pridebugfdlock, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

11295 {
11296    int myfd;
11297 
11298    if (!strncasecmp(argv[1], "set", 3)) {
11299       if (argc < 5) 
11300          return RESULT_SHOWUSAGE;
11301 
11302       if (ast_strlen_zero(argv[4]))
11303          return RESULT_SHOWUSAGE;
11304 
11305       myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
11306       if (myfd < 0) {
11307          ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
11308          return RESULT_SUCCESS;
11309       }
11310 
11311       ast_mutex_lock(&pridebugfdlock);
11312 
11313       if (pridebugfd >= 0)
11314          close(pridebugfd);
11315 
11316       pridebugfd = myfd;
11317       ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
11318       
11319       ast_mutex_unlock(&pridebugfdlock);
11320 
11321       ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
11322    } else {
11323       /* Assume it is unset */
11324       ast_mutex_lock(&pridebugfdlock);
11325       close(pridebugfd);
11326       pridebugfd = -1;
11327       ast_cli(fd, "PRI debug output to file disabled\n");
11328       ast_mutex_unlock(&pridebugfdlock);
11329    }
11330 
11331    return RESULT_SUCCESS;
11332 }

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

Definition at line 11498 of file chan_dahdi.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), debug, NUM_SPANS, pridebugfdlock, pris, and RESULT_SUCCESS.

11499 {
11500    int x;
11501    int span;
11502    int count=0;
11503    int debug=0;
11504 
11505    for (span = 0; span < NUM_SPANS; span++) {
11506            if (pris[span].pri) {
11507          for (x = 0; x < NUM_DCHANS; x++) {
11508             debug = 0;
11509                if (pris[span].dchans[x]) {
11510                   debug = pri_get_debug(pris[span].dchans[x]);
11511                ast_cli(fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
11512                count++;
11513             }
11514          }
11515       }
11516 
11517    }
11518    ast_mutex_lock(&pridebugfdlock);
11519    if (pridebugfd >= 0) 
11520       ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
11521    ast_mutex_unlock(&pridebugfdlock);
11522        
11523    if (!count) 
11524       ast_cli(fd, "No debug set or no PRI running\n");
11525    return RESULT_SUCCESS;
11526 }

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

Definition at line 11459 of file chan_dahdi.c.

References ast_cli(), build_status(), DAHDI_OVERLAPDIAL_INCOMING, free, NUM_SPANS, pri_order(), pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

11460 {
11461    int span;
11462    int x;
11463    char status[256];
11464    if (argc < 4)
11465       return RESULT_SHOWUSAGE;
11466    span = atoi(argv[3]);
11467    if ((span < 1) || (span > NUM_SPANS)) {
11468       ast_cli(fd, "Invalid span '%s'.  Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
11469       return RESULT_SUCCESS;
11470    }
11471    if (!pris[span-1].pri) {
11472       ast_cli(fd, "No PRI running on span %d\n", span);
11473       return RESULT_SUCCESS;
11474    }
11475    for (x = 0; x < NUM_DCHANS; x++) {
11476       if (pris[span-1].dchannels[x]) {
11477 #ifdef PRI_DUMP_INFO_STR
11478          char *info_str = NULL;
11479 #endif
11480          ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
11481          build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
11482          ast_cli(fd, "Status: %s\n", status);
11483 #ifdef PRI_DUMP_INFO_STR
11484          info_str = pri_dump_info_str(pris[span-1].pri);
11485          if (info_str) {
11486             ast_cli(fd, "%s", info_str);
11487             free(info_str);
11488          }
11489 #else
11490          pri_dump_info(pris[span-1].pri);
11491 #endif
11492          ast_cli(fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
11493       }
11494    }
11495    return RESULT_SUCCESS;
11496 }

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

Definition at line 11438 of file chan_dahdi.c.

References ast_cli(), build_status(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

11439 {
11440    int span;
11441    int x;
11442    char status[256];
11443    if (argc != 3)
11444       return RESULT_SHOWUSAGE;
11445 
11446    for (span = 0; span < NUM_SPANS; span++) {
11447       if (pris[span].pri) {
11448          for (x = 0; x < NUM_DCHANS; x++) {
11449             if (pris[span].dchannels[x]) {
11450                build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
11451                ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
11452             }
11453          }
11454       }
11455    }
11456    return RESULT_SUCCESS;
11457 }

static int handle_pri_version ( int  fd,
int  agc,
char *  argv[] 
) [static]

Definition at line 11335 of file chan_dahdi.c.

References ast_cli(), and RESULT_SUCCESS.

11335                                                              {
11336    ast_cli(fd, "libpri version: %s\n", pri_get_version());
11337    return RESULT_SUCCESS;
11338 }

static int has_voicemail ( struct dahdi_pvt p  )  [static]

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

02648 {
02649 
02650    return ast_app_has_voicemail(p->mailbox, NULL);
02651 }

static void init_mfcr2_globals ( void   )  [static]

Definition at line 1266 of file chan_dahdi.c.

References AST_PTHREADT_NULL, master, NUM_SPANS, and r2links.

Referenced by dahdi_restart(), and load_module().

01267 {
01268    int r;
01269    mfcr2_cur_context_index = 0;
01270    mfcr2_cur_variant = OR2_VAR_UNKNOWN;
01271    mfcr2_cur_mfback_timeout = -1;
01272    mfcr2_cur_metering_pulse_timeout = -1;
01273    mfcr2_cur_max_ani = 10;
01274    mfcr2_cur_max_dnis = 4;
01275    mfcr2_cur_get_ani_first = -1;
01276 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
01277    mfcr2_cur_dtmf_dialing = -1;
01278    mfcr2_cur_dtmf_detection = -1;
01279    mfcr2_cur_dtmf_time_on = OR2_DEFAULT_DTMF_ON;
01280    mfcr2_cur_dtmf_time_off = OR2_DEFAULT_DTMF_OFF;
01281 #endif
01282    mfcr2_cur_skip_category = -1;
01283    mfcr2_cur_call_files = 0;
01284    mfcr2_cur_allow_collect_calls = 0;
01285    mfcr2_cur_forced_release = 0;
01286    mfcr2_cur_double_answer = 0;
01287    mfcr2_cur_immediate_accept = -1;
01288    mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING;
01289    mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
01290    memset(mfcr2_cur_logdir, 0, sizeof(mfcr2_cur_logdir));
01291    memset(mfcr2_cur_r2proto_file, 0, sizeof(mfcr2_cur_r2proto_file));
01292    memset(r2links, 0, sizeof(r2links));
01293    for (r = 0; r < NUM_SPANS; r++) {
01294       r2links[r].master = AST_PTHREADT_NULL;
01295    }
01296 }

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

Definition at line 2206 of file chan_dahdi.c.

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

Referenced by conf_del().

02207 {
02208    /* If they're listening to our channel, they're ours */  
02209    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
02210       return 1;
02211    /* If they're a talker on our (allocated) conference, they're ours */
02212    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
02213       return 1;
02214    return 0;
02215 }

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

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

02237 {
02238    int x;
02239    int useslavenative;
02240    struct dahdi_pvt *slave = NULL;
02241    /* Start out optimistic */
02242    useslavenative = 1;
02243    /* Update conference state in a stateless fashion */
02244    for (x = 0; x < 3; x++) {
02245       /* Any three-way calling makes slave native mode *definitely* out
02246          of the question */
02247       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
02248          useslavenative = 0;
02249    }
02250    /* If we don't have any 3-way calls, check to see if we have
02251       precisely one slave */
02252    if (useslavenative) {
02253       for (x = 0; x < MAX_SLAVES; x++) {
02254          if (p->slaves[x]) {
02255             if (slave) {
02256                /* Whoops already have a slave!  No 
02257                   slave native and stop right away */
02258                slave = NULL;
02259                useslavenative = 0;
02260                break;
02261             } else {
02262                /* We have one slave so far */
02263                slave = p->slaves[x];
02264             }
02265          }
02266       }
02267    }
02268    /* If no slave, slave native definitely out */
02269    if (!slave)
02270       useslavenative = 0;
02271    else if (slave->law != p->law) {
02272       useslavenative = 0;
02273       slave = NULL;
02274    }
02275    if (out)
02276       *out = slave;
02277    return useslavenative;
02278 }

static int load_module ( void   )  [static]

Definition at line 13933 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_accept_r2_call_exec(), dahdi_chan_mode, dahdi_cli, dahdi_mfcr2_cli, dahdi_pri_cli, dahdi_pri_error(), dahdi_pri_message(), dahdi_send_keypad_facility_exec(), dahdi_tech, init_mfcr2_globals(), inuse, local_astman_register, lock, LOG_ERROR, name, NUM_SPANS, pris, round_robin, setup_dahdi(), ast_channel_tech::type, zap_accept_r2_call_exec(), zap_send_keypad_facility_exec(), and zap_tech.

13934 {
13935    int res;
13936 
13937 #ifdef HAVE_PRI
13938    int y,i;
13939    memset(pris, 0, sizeof(pris));
13940    for (y = 0; y < NUM_SPANS; y++) {
13941       ast_mutex_init(&pris[y].lock);
13942       pris[y].offset = -1;
13943       pris[y].master = AST_PTHREADT_NULL;
13944       for (i = 0; i < NUM_DCHANS; i++)
13945          pris[y].fds[i] = -1;
13946    }
13947    pri_set_error(dahdi_pri_error);
13948    pri_set_message(dahdi_pri_message);
13949    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13950       ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
13951          dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
13952    }
13953    ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
13954       zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
13955 #endif
13956 #ifdef HAVE_OPENR2
13957    init_mfcr2_globals();
13958    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13959       ast_register_application(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec,
13960          dahdi_accept_r2_call_synopsis, dahdi_accept_r2_call_descrip);
13961    }
13962    ast_register_application(zap_accept_r2_call_app, zap_accept_r2_call_exec,
13963       zap_accept_r2_call_synopsis, zap_accept_r2_call_descrip);
13964 #endif
13965    if ((res = setup_dahdi(0))) {
13966       return AST_MODULE_LOAD_DECLINE;
13967    }
13968    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13969       chan_tech = &dahdi_tech;
13970    } else {
13971       chan_tech = &zap_tech;
13972    }
13973    if (ast_channel_register(chan_tech)) {
13974       ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
13975       __unload_module();
13976       return -1;
13977    }
13978 #ifdef HAVE_PRI
13979    ast_string_field_init(&inuse, 16);
13980    ast_string_field_set(&inuse, name, "GR-303InUse");
13981    ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
13982 #endif   
13983 #ifdef HAVE_OPENR2
13984    ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
13985 #endif
13986    ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
13987    
13988    memset(round_robin, 0, sizeof(round_robin));
13989    local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
13990    local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
13991    local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
13992    local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
13993    local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
13994    local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
13995    local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
13996 
13997    ast_cond_init(&ss_thread_complete, NULL);
13998 
13999    return res;
14000 }

static struct dahdi_mfcr2* mfcr2_get_context ( int  id  )  [static]

Definition at line 8435 of file chan_dahdi.c.

References ast_log(), LOG_ERROR, and r2links.

Referenced by mkintf().

08436 {
08437    if ((id < 0) || (id >= (sizeof(r2links)/sizeof(r2links[0])))) {
08438       ast_log(LOG_ERROR, "No more R2 links available!.\n");
08439       return NULL;
08440    }
08441    return &r2links[id];
08442 }

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

Definition at line 9591 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, DAHDI_R2_LOCAL_BLOCK, dahdi_pvt::lock, LOG_ERROR, and dahdi_pvt::r2chan.

Referenced by setup_dahdi().

09592 {
09593    struct dahdi_pvt *p;
09594    struct dahdi_mfcr2 *mfcr2 = data;
09595    /* we should be using pthread_key_create
09596       and allocate pollers dynamically.
09597       I think do_monitor() could be leaking, since it
09598       could be cancelled at any time and is not
09599       using thread keys, why?, */
09600    struct pollfd pollers[sizeof(mfcr2->pvts)];
09601    int maxsleep = 20;
09602    int res = 0;
09603    int i = 0;
09604    int pollsize = 0;
09605    int oldstate = 0;
09606    int was_idle = 0;
09607    int quit_loop = 0;
09608    /* now that we're ready to get calls, unblock our side and
09609       get current line state */
09610    for (i = 0; i < mfcr2->numchans; i++) {
09611       p = mfcr2->pvts[i];
09612       if (openr2_chan_set_idle(p->r2chan)) {
09613          ast_log(LOG_ERROR, "Failed to set channel %d in IDLE\n", p->channel);
09614       } else {
09615          ast_mutex_lock(&p->lock);
09616          mfcr2->pvts[i]->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK;
09617          mfcr2->pvts[i]->mfcr2call = 0;
09618          ast_mutex_unlock(&p->lock);
09619       }
09620       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
09621    }
09622    while(1) {
09623       /* we trust here that the mfcr2 channel list will not ever change once
09624          the module is loaded */
09625       pollsize = 0;
09626       for (i = 0; i < mfcr2->numchans; i++) {
09627          pollers[i].revents = 0;
09628          pollers[i].events = 0;
09629          if (mfcr2->pvts[i]->owner) {
09630             continue;
09631          }
09632          if (!mfcr2->pvts[i]->r2chan) {
09633             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
09634             quit_loop = 1;
09635             break;
09636          }
09637          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
09638          pollers[i].events = POLLIN | POLLPRI;
09639          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
09640          pollsize++;
09641       }
09642       if (quit_loop) {
09643          break;
09644       }
09645 
09646       if (pollsize == 0) {
09647          if (!was_idle) {
09648             ast_log(LOG_NOTICE, "Monitor thread going idle since everybody has an owner\n");
09649             was_idle = 1;
09650          }
09651          poll(NULL, 0, maxsleep);
09652          continue;
09653       }
09654       was_idle = 0;
09655 
09656       /* probably poll() is a valid cancel point, lets just be on the safe side
09657          by calling pthread_testcancel */
09658       pthread_testcancel();
09659       res = poll(pollers, pollsize, maxsleep);
09660       pthread_testcancel();
09661       if ((res < 0) && (errno != EINTR)) {
09662          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
09663          break;
09664       } 
09665       /* do we want to allow to cancel while processing events? */
09666       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
09667       for (i = 0; i < mfcr2->numchans; i++) {
09668          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
09669             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
09670          }
09671       }
09672       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
09673    }
09674    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
09675    return 0;
09676 }

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

Definition at line 8568 of file chan_dahdi.c.

References ast_calloc, ast_config_AST_LOG_DIR, ast_copy_string(), ast_log(), ast_mutex_init(), ast_strlen_zero(), dahdi_pvt::call, dahdi_chan_conf::chan, CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pri::crvend, dahdi_pri::crvs, dahdi_open(), DAHDI_R2_LOCAL_BLOCK, dahdi_r2_on_chan_log(), DAHDI_R2_REMOTE_BLOCK, destroy_dahdi_pvt(), dahdi_subchannel::dfd, dahdi_pri::dialplan, dialplan2str(), errno, dahdi_pri::facilityenable, free, dahdi_pri::idledial, dahdi_pri::idleext, iflist, dahdi_pri::inbanddisconnect, dahdi_pri::internationalprefix, dahdi_pvt::law, dahdi_pri::localdialplan, dahdi_pri::localprefix, LOG_ERROR, dahdi_pvt::logicalspan, MAX_CHANNELS, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_accept_on_offer, dahdi_pvt::mfcr2_allow_collect_calls, dahdi_pvt::mfcr2_ani_index, dahdi_pvt::mfcr2_category, dahdi_pvt::mfcr2_charge_calls, dahdi_pvt::mfcr2_dnis_index, dahdi_pvt::mfcr2_forced_release, mfcr2_get_context(), dahdi_pvt::mfcr2block, dahdi_pvt::mfcr2call, dahdi_pri::minidle, dahdi_pri::minunused, dahdi_pri::nationalprefix, dahdi_pvt::next, dahdi_pri::nodetype, dahdi_pri::nsf, NUM_DCHANS, NUM_SPANS, dahdi_mfcr2::numchans, dahdi_pri::numchans, offset, dahdi_pri::overlapdial, dahdi_pvt::prev, dahdi_pvt::pri, dahdi_chan_conf::pri, pri_resolve_span(), dahdi_pvt::priindication_oob, dahdi_pri::prilogicalspan, dahdi_pvt::prioffset, pris, dahdi_pri::privateprefix, dahdi_mfcr2::protocol_context, dahdi_mfcr2::pvts, dahdi_pri::pvts, dahdi_pvt::r2chan, dahdi_pri::resetinterval, dahdi_pvt::sig, sig2str, SIG_FXOKS, SIG_FXSKS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_MFCR2, SIG_PRI, dahdi_pvt::span, SUB_REAL, dahdi_pvt::subs, dahdi_pri::switchtype, and dahdi_pri::unknownprefix.

Referenced by build_channels().

08569 {
08570    /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
08571    struct dahdi_pvt *tmp = NULL, *tmp2,  *prev = NULL;
08572    char fn[80];
08573 #if 1
08574    struct dahdi_bufferinfo bi;
08575 #endif
08576    int res;
08577    int span=0;
08578    int here = 0;
08579    int x;
08580    struct dahdi_pvt **wlist;
08581    struct dahdi_pvt **wend;
08582    struct dahdi_params p;
08583 
08584    wlist = &iflist;
08585    wend = &ifend;
08586 
08587 #ifdef HAVE_PRI
08588    if (pri) {
08589       wlist = &pri->crvs;
08590       wend = &pri->crvend;
08591    }
08592 #endif
08593 
08594    tmp2 = *wlist;
08595    prev = NULL;
08596 
08597    while (tmp2) {
08598       if (!tmp2->destroy) {
08599          if (tmp2->channel == channel) {
08600             tmp = tmp2;
08601             here = 1;
08602             break;
08603          }
08604          if (tmp2->channel > channel) {
08605             break;
08606          }
08607       }
08608       prev = tmp2;
08609       tmp2 = tmp2->next;
08610    }
08611 
08612    if (!here && reloading != 1) {
08613       if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
08614          if (tmp)
08615             free(tmp);
08616          return NULL;
08617       }
08618       ast_mutex_init(&tmp->lock);
08619       ifcount++;
08620       for (x = 0; x < 3; x++)
08621          tmp->subs[x].dfd = -1;
08622       tmp->channel = channel;
08623       tmp->priindication_oob = conf->chan.priindication_oob;
08624    }
08625 
08626    if (tmp) {
08627       int chan_sig = conf->chan.sig;
08628       if (!here) {
08629          if ((channel != CHAN_PSEUDO) && !pri) {
08630             int count = 0;
08631             snprintf(fn, sizeof(fn), "%d", channel);
08632             /* Open non-blocking */
08633             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08634             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 */
08635                usleep(1);
08636                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08637                count++;
08638             }
08639             /* Allocate a DAHDI structure */
08640             if (tmp->subs[SUB_REAL].dfd < 0) {
08641                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);
08642                destroy_dahdi_pvt(&tmp);
08643                return NULL;
08644             }
08645             memset(&p, 0, sizeof(p));
08646             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08647             if (res < 0) {
08648                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
08649                destroy_dahdi_pvt(&tmp);
08650                return NULL;
08651             }
08652             if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
08653                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));
08654                destroy_dahdi_pvt(&tmp);
08655                return NULL;
08656             }
08657             tmp->law = p.curlaw;
08658             tmp->span = p.spanno;
08659             span = p.spanno - 1;
08660          } else {
08661             if (channel == CHAN_PSEUDO)
08662                chan_sig = 0;
08663             else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
08664                ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
08665                return NULL;
08666             }
08667          }
08668 #ifdef HAVE_PRI
08669          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
08670             int offset;
08671             int myswitchtype;
08672             int matchesdchan;
08673             int x,y;
08674             offset = 0;
08675             if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
08676                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08677                destroy_dahdi_pvt(&tmp);
08678                return NULL;
08679             }
08680             if (span >= NUM_SPANS) {
08681                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
08682                destroy_dahdi_pvt(&tmp);
08683                return NULL;
08684             } else {
08685                struct dahdi_spaninfo si;
08686                si.spanno = 0;
08687                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
08688                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
08689                   destroy_dahdi_pvt(&tmp);
08690                   return NULL;
08691                }
08692                /* Store the logical span first based upon the real span */
08693                tmp->logicalspan = pris[span].prilogicalspan;
08694                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
08695                if (span < 0) {
08696                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
08697                   destroy_dahdi_pvt(&tmp);
08698                   return NULL;
08699                }
08700                if (chan_sig == SIG_PRI)
08701                   myswitchtype = conf->pri.switchtype;
08702                else
08703                   myswitchtype = PRI_SWITCH_GR303_TMC;
08704                /* Make sure this isn't a d-channel */
08705                matchesdchan=0;
08706                for (x = 0; x < NUM_SPANS; x++) {
08707                   for (y = 0; y < NUM_DCHANS; y++) {
08708                      if (pris[x].dchannels[y] == tmp->channel) {
08709                         matchesdchan = 1;
08710                         break;
08711                      }
08712                   }
08713                }
08714                offset = p.chanpos;
08715                if (!matchesdchan) {
08716                   if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
08717                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
08718                      destroy_dahdi_pvt(&tmp);
08719                      return NULL;
08720                   }
08721                   if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
08722                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
08723                      destroy_dahdi_pvt(&tmp);
08724                      return NULL;
08725                   }
08726                   if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
08727                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
08728                      destroy_dahdi_pvt(&tmp);
08729                      return NULL;
08730                   }
08731                   if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
08732                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
08733                      destroy_dahdi_pvt(&tmp);
08734                      return NULL;
08735                   }
08736                   if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
08737                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
08738                      destroy_dahdi_pvt(&tmp);
08739                      return NULL;
08740                   }
08741                   if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
08742                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
08743                      destroy_dahdi_pvt(&tmp);
08744                      return NULL;
08745                   }
08746                   if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
08747                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
08748                      destroy_dahdi_pvt(&tmp);
08749                      return NULL;
08750                   }
08751                   if (pris[span].numchans >= MAX_CHANNELS) {
08752                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
08753                         pris[span].trunkgroup);
08754                      destroy_dahdi_pvt(&tmp);
08755                      return NULL;
08756                   }
08757                   pris[span].nodetype = conf->pri.nodetype;
08758                   pris[span].switchtype = myswitchtype;
08759                   pris[span].nsf = conf->pri.nsf;
08760                   pris[span].dialplan = conf->pri.dialplan;
08761                   pris[span].localdialplan = conf->pri.localdialplan;
08762                   pris[span].pvts[pris[span].numchans++] = tmp;
08763                   pris[span].minunused = conf->pri.minunused;
08764                   pris[span].minidle = conf->pri.minidle;
08765                   pris[span].overlapdial = conf->pri.overlapdial;
08766 #ifdef HAVE_PRI_INBANDDISCONNECT
08767                   pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
08768 #endif
08769                   pris[span].facilityenable = conf->pri.facilityenable;
08770                   ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
08771                   ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
08772                   ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
08773                   ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
08774                   ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
08775                   ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
08776                   ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
08777                   pris[span].resetinterval = conf->pri.resetinterval;
08778                   
08779                   tmp->pri = &pris[span];
08780                   tmp->prioffset = offset;
08781                   tmp->call = NULL;
08782                } else {
08783                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
08784                   destroy_dahdi_pvt(&tmp);
08785                   return NULL;
08786                }
08787             }
08788          } else {
08789             tmp->prioffset = 0;
08790          }
08791 #endif
08792 #ifdef HAVE_OPENR2
08793          if (chan_sig == SIG_MFCR2 && reloading != 1) {
08794             char logdir[OR2_MAX_PATH];
08795             struct dahdi_mfcr2 *dahdi_r2;
08796             int threshold = 0;
08797             int snres = 0;
08798             dahdi_r2 = mfcr2_get_context(mfcr2_cur_context_index);
08799             if (!dahdi_r2) {
08800                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
08801             } else if (!dahdi_r2->protocol_context){
08802                char tmplogdir[] = "/tmp";
08803                dahdi_r2->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface, 
08804                      &dahdi_r2_transcode_iface, mfcr2_cur_variant, mfcr2_cur_max_ani, mfcr2_cur_max_dnis);
08805                if (!dahdi_r2->protocol_context) {
08806                   ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
08807                   destroy_dahdi_pvt(&tmp);
08808                   return NULL;
08809                } 
08810                openr2_context_set_log_level(dahdi_r2->protocol_context, mfcr2_cur_loglevel);
08811                openr2_context_set_ani_first(dahdi_r2->protocol_context, mfcr2_cur_get_ani_first);
08812                openr2_context_set_skip_category_request(dahdi_r2->protocol_context, mfcr2_cur_skip_category);
08813                openr2_context_set_mf_threshold(dahdi_r2->protocol_context, threshold);
08814                openr2_context_set_mf_back_timeout(dahdi_r2->protocol_context, mfcr2_cur_mfback_timeout);
08815                openr2_context_set_metering_pulse_timeout(dahdi_r2->protocol_context, mfcr2_cur_metering_pulse_timeout);
08816                openr2_context_set_double_answer(dahdi_r2->protocol_context, mfcr2_cur_double_answer);
08817                openr2_context_set_immediate_accept(dahdi_r2->protocol_context, mfcr2_cur_immediate_accept);
08818 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
08819                openr2_context_set_dtmf_dialing(dahdi_r2->protocol_context, mfcr2_cur_dtmf_dialing, mfcr2_cur_dtmf_time_on, mfcr2_cur_dtmf_time_off);
08820                openr2_context_set_dtmf_detection(dahdi_r2->protocol_context, mfcr2_cur_dtmf_detection);
08821 #endif
08822                if (ast_strlen_zero(mfcr2_cur_logdir)) {
08823                   if (openr2_context_set_log_directory(dahdi_r2->protocol_context, tmplogdir)) {
08824                      ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
08825                   }
08826                } else {
08827                   snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", mfcr2_cur_logdir);
08828                   if (snres >= sizeof(logdir)) {
08829                      ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
08830                      if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) {
08831                         ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
08832                      }
08833                   } else {
08834                      if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) {
08835                         ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
08836                      }
08837                   }  
08838                }
08839                if (!ast_strlen_zero(mfcr2_cur_r2proto_file)) {
08840                   if (openr2_context_configure_from_advanced_file(dahdi_r2->protocol_context, mfcr2_cur_r2proto_file)) {
08841                      ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", mfcr2_cur_r2proto_file);
08842                   }
08843                }
08844             } 
08845             if (dahdi_r2) {
08846                /* TODO: should we check numchans overflow, or is it already done by DAHDI? */
08847                dahdi_r2->pvts[dahdi_r2->numchans++] = tmp;
08848                tmp->r2chan = openr2_chan_new_from_fd(dahdi_r2->protocol_context,
08849                      tmp->subs[SUB_REAL].dfd, NULL, NULL);
08850                if (!tmp->r2chan) {
08851                   openr2_liberr_t err = openr2_context_get_last_error(dahdi_r2->protocol_context);
08852                   ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
08853                   destroy_dahdi_pvt(&tmp);
08854                   return NULL;
08855                }
08856                openr2_chan_set_client_data(tmp->r2chan, tmp);
08857                /* cast seems to be needed to get rid of the annoying warning regarding format attribute */
08858                openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
08859                openr2_chan_set_log_level(tmp->r2chan, mfcr2_cur_loglevel);
08860                if (mfcr2_cur_call_files) {
08861                   openr2_chan_enable_call_files(tmp->r2chan);
08862                }
08863                tmp->mfcr2_category = mfcr2_cur_category;
08864                tmp->mfcr2 = dahdi_r2;
08865                tmp->mfcr2call = 0;
08866                tmp->mfcr2block = DAHDI_R2_REMOTE_BLOCK | DAHDI_R2_LOCAL_BLOCK;
08867                tmp->mfcr2_accept_on_offer = mfcr2_cur_accept_on_offer;
08868                tmp->mfcr2_charge_calls = mfcr2_cur_charge_calls;
08869                tmp->mfcr2_ani_index = 0;
08870                tmp->mfcr2_dnis_index = 0;
08871                tmp->mfcr2_allow_collect_calls = mfcr2_cur_allow_collect_calls;
08872                tmp->mfcr2_forced_release = mfcr2_cur_forced_release;
08873             }
08874          }
08875 #endif
08876       } else {
08877          chan_sig = tmp->sig;
08878          if (tmp->subs[SUB_REAL].dfd > -1) {
08879             memset(&p, 0, sizeof(p));
08880             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08881          }
08882       }
08883       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
08884       switch (chan_sig) {
08885       case SIG_FXSKS:
08886       case SIG_FXSLS:
08887       case SIG_EM:
08888       case SIG_EM_E1:
08889       case SIG_EMWINK:
08890       case SIG_FEATD:
08891       case SIG_FEATDMF:
08892       case SIG_FEATDMF_TA:
08893       case SIG_FEATB:
08894       case SIG_E911:
08895       case SIG_SF:
08896       case SIG_SFWINK:
08897       case SIG_FGC_CAMA:
08898       case SIG_FGC_CAMAMF:
08899       case SIG_SF_FEATD:
08900       case SIG_SF_FEATDMF:
08901       case SIG_SF_FEATB:
08902          p.starttime = 250;
08903          break;
08904       }
08905 
08906       if (tmp->radio) {
08907          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
08908          p.channo = channel;
08909          p.rxwinktime = 1;
08910          p.rxflashtime = 1;
08911          p.starttime = 1;
08912          p.debouncetime = 5;
08913       }
08914       if (!tmp->radio) {
08915          p.channo = channel;
08916          /* Override timing settings based on config file */
08917          if (conf->timing.prewinktime >= 0)
08918             p.prewinktime = conf->timing.prewinktime;
08919          if (conf->timing.preflashtime >= 0)
08920             p.preflashtime = conf->timing.preflashtime;
08921          if (conf->timing.winktime >= 0)
08922             p.winktime = conf->timing.winktime;
08923          if (conf->timing.flashtime >= 0)
08924             p.flashtime = conf->timing.flashtime;
08925          if (conf->timing.starttime >= 0)
08926             p.starttime = conf->timing.starttime;
08927          if (conf->timing.rxwinktime >= 0)
08928             p.rxwinktime = conf->timing.rxwinktime;
08929          if (conf->timing.rxflashtime >= 0)
08930             p.rxflashtime = conf->timing.rxflashtime;
08931          if (conf->timing.debouncetime >= 0)
08932             p.debouncetime = conf->timing.debouncetime;
08933       }
08934       
08935       /* dont set parms on a pseudo-channel (or CRV) */
08936       if (tmp->subs[SUB_REAL].dfd >= 0)
08937       {
08938          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
08939          if (res < 0) {
08940             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
08941             destroy_dahdi_pvt(&tmp);
08942             return NULL;
08943          }
08944       }
08945 #if 1
08946       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
08947          memset(&bi, 0, sizeof(bi));
08948          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
08949          if (!res) {
08950             bi.txbufpolicy = conf->chan.buf_policy;
08951             bi.rxbufpolicy = conf->chan.buf_policy;
08952             bi.numbufs = conf->chan.buf_no;
08953             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
08954             if (res < 0) {
08955                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
08956             }
08957          } else
08958             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
08959       }
08960 #endif
08961       tmp->immediate = conf->chan.immediate;
08962       tmp->transfertobusy = conf->chan.transfertobusy;
08963       tmp->sig = chan_sig;
08964       tmp->outsigmod = conf->chan.outsigmod;
08965       tmp->ringt_base = ringt_base;
08966       tmp->firstradio = 0;
08967       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
08968          tmp->permcallwaiting = conf->chan.callwaiting;
08969       else
08970          tmp->permcallwaiting = 0;
08971       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
08972       tmp->destroy = 0;
08973       tmp->drings = drings;
08974       tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
08975       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
08976       tmp->threewaycalling = conf->chan.threewaycalling;
08977       tmp->adsi = conf->chan.adsi;
08978       tmp->use_smdi = conf->chan.use_smdi;
08979       tmp->permhidecallerid = conf->chan.hidecallerid;
08980       tmp->callreturn = conf->chan.callreturn;
08981       tmp->echocancel = conf->chan.echocancel;
08982       tmp->echotraining = conf->chan.echotraining;
08983       tmp->pulse = conf->chan.pulse;
08984       if (tmp->echocancel)
08985          tmp->echocanbridged = conf->chan.echocanbridged;
08986       else {
08987          if (conf->chan.echocanbridged)
08988             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
08989          tmp->echocanbridged = 0;
08990       }
08991       tmp->busydetect = conf->chan.busydetect;
08992       tmp->busycount = conf->chan.busycount;
08993       tmp->busycompare = conf->chan.busycompare;
08994       tmp->busytonelength = conf->chan.busytonelength;
08995       tmp->busyquietlength = conf->chan.busyquietlength;
08996       tmp->busyfuzziness = conf->chan.busyfuzziness;
08997       tmp->silencethreshold = conf->chan.silencethreshold;
08998       tmp->callprogress = conf->chan.callprogress;
08999       tmp->cancallforward = conf->chan.cancallforward;
09000       tmp->dtmfrelax = conf->chan.dtmfrelax;
09001       tmp->callwaiting = tmp->permcallwaiting;
09002       tmp->hidecallerid = tmp->permhidecallerid;
09003       tmp->channel = channel;
09004       tmp->stripmsd = conf->chan.stripmsd;
09005       tmp->use_callerid = conf->chan.use_callerid;
09006       tmp->cid_signalling = conf->chan.cid_signalling;
09007       tmp->cid_start = conf->chan.cid_start;
09008       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
09009       tmp->restrictcid = conf->chan.restrictcid;
09010       tmp->use_callingpres = conf->chan.use_callingpres;
09011       tmp->priexclusive = conf->chan.priexclusive;
09012       if (tmp->usedistinctiveringdetection) {
09013          if (!tmp->use_callerid) {
09014             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
09015             tmp->use_callerid = 1;
09016          }
09017       }
09018 
09019       if (tmp->cid_signalling == CID_SIG_SMDI) {
09020          if (!tmp->use_smdi) {
09021             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
09022             tmp->use_smdi = 1;
09023          }
09024       }
09025       if (tmp->use_smdi) {
09026          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
09027          if (!(tmp->smdi_iface)) {
09028             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
09029             tmp->use_smdi = 0;
09030          }
09031       }
09032 
09033       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
09034       tmp->amaflags = conf->chan.amaflags;
09035       if (!here) {
09036          tmp->confno = -1;
09037          tmp->propconfno = -1;
09038       }
09039       tmp->canpark = conf->chan.canpark;
09040       tmp->transfer = conf->chan.transfer;
09041       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
09042       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
09043       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
09044       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
09045       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
09046       tmp->cid_ton = 0;
09047       if (chan_sig != SIG_PRI) {
09048          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
09049          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
09050       } else {
09051          tmp->cid_num[0] = '\0';
09052          tmp->cid_name[0] = '\0';
09053       }
09054       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
09055       tmp->msgstate = -1;
09056       tmp->group = conf->chan.group;
09057       tmp->callgroup = conf->chan.callgroup;
09058       tmp->pickupgroup= conf->chan.pickupgroup;
09059       tmp->rxgain = conf->chan.rxgain;
09060       tmp->txgain = conf->chan.txgain;
09061       tmp->tonezone = conf->chan.tonezone;
09062       tmp->onhooktime = time(NULL);
09063       if (tmp->subs[SUB_REAL].dfd > -1) {
09064          set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
09065          if (tmp->dsp)
09066             ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
09067          update_conf(tmp);
09068          if (!here) {
09069             if ((chan_sig != SIG_PRI) && (chan_sig != SIG_MFCR2))
09070                /* Hang it up to be sure it's good */
09071                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09072          }
09073          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
09074 #ifdef HAVE_PRI
09075          /* the dchannel is down so put the channel in alarm */
09076          if (tmp->pri && !pri_is_up(tmp->pri)) {
09077             tmp->inalarm = 1;
09078          }
09079 #endif            
09080          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
09081             tmp->inalarm = 1;
09082             handle_alarms(tmp, res);
09083          } else {
09084             /* yes, this looks strange... the unknown_alarm flag is only used to
09085                control whether an 'alarm cleared' message gets generated when we
09086                get an indication that the channel is no longer in alarm status.
09087                however, the channel *could* be in an alarm status that we aren't
09088                aware of (since get_alarms() only reports span alarms, not channel
09089                alarms). setting this flag will cause any potential 'alarm cleared'
09090                message to be suppressed, but if a real alarm occurs before that
09091                happens, this flag will get cleared by it and the situation will
09092                be normal.
09093             */
09094             tmp->unknown_alarm = 1;
09095          }
09096       }
09097 
09098       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
09099       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
09100       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
09101       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
09102 
09103    }
09104    if (tmp && !here) {
09105       /* nothing on the iflist */
09106       if (!*wlist) {
09107          *wlist = tmp;
09108          tmp->prev = NULL;
09109          tmp->next = NULL;
09110          *wend = tmp;
09111       } else {
09112          /* at least one member on the iflist */
09113          struct dahdi_pvt *working = *wlist;
09114 
09115          /* check if we maybe have to put it on the begining */
09116          if (working->channel > tmp->channel) {
09117             tmp->next = *wlist;
09118             tmp->prev = NULL;
09119             (*wlist)->prev = tmp;
09120             *wlist = tmp;
09121          } else {
09122          /* go through all the members and put the member in the right place */
09123             while (working) {
09124                /* in the middle */
09125                if (working->next) {
09126                   if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
09127                      tmp->next = working->next;
09128                      tmp->prev = working;
09129                      working->next->prev = tmp;
09130                      working->next = tmp;
09131                      break;
09132                   }
09133                } else {
09134                /* the last */
09135                   if (working->channel < tmp->channel) {
09136                      working->next = tmp;
09137                      tmp->next = NULL;
09138                      tmp->prev = working;
09139                      *wend = tmp;
09140                      break;
09141                   }
09142                }
09143                working = working->next;
09144             }
09145          }
09146       }
09147    }
09148    return tmp;
09149 }

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

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

06230 {
06231    int sent=0;
06232    int size;
06233    int res;
06234    int fd;
06235    fd = p->subs[index].dfd;
06236    while (len) {
06237       size = len;
06238       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
06239          size = (linear ? READ_SIZE * 2 : READ_SIZE);
06240       res = write(fd, buf, size);
06241       if (res != size) {
06242          if (option_debug)
06243             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06244          return sent;
06245       }
06246       len -= size;
06247       buf += size;
06248    }
06249    return sent;
06250 }

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

Definition at line 6720 of file chan_dahdi.c.

References ast_waitfordigit().

Referenced by ss_thread().

06721 {
06722    char c;
06723 
06724    *str = 0; /* start with empty output buffer */
06725    for (;;)
06726    {
06727       /* Wait for the first digit (up to specified ms). */
06728       c = ast_waitfordigit(chan, ms);
06729       /* if timeout, hangup or error, return as such */
06730       if (c < 1)
06731          return c;
06732       *str++ = c;
06733       *str = 0;
06734       if (strchr(term, c))
06735          return 1;
06736    }
06737 }

static int pri_active_dchan_fd ( struct dahdi_pri pri  )  [static]

Definition at line 3391 of file chan_dahdi.c.

References dahdi_pri::dchans, dahdi_pri::fds, NUM_DCHANS, dahdi_pri::pri, and dahdi_pvt::pri.

Referenced by pri_find_principle().

03392 {
03393    int x = -1;
03394 
03395    for (x = 0; x < NUM_DCHANS; x++) {
03396       if ((pri->dchans[x] == pri->pri))
03397          break;
03398    }
03399 
03400    return pri->fds[x];
03401 }

static int pri_assign_bearer ( struct dahdi_pvt crv,
struct dahdi_pri pri,
struct dahdi_pvt bearer 
) [static]

Definition at line 3361 of file chan_dahdi.c.

References dahdi_pvt::bearer, dahdi_pvt::call, dahdi_subchannel::dfd, ast_channel::fds, inuse, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::realcall, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_request().

03362 {
03363    bearer->owner = &inuse;
03364    bearer->realcall = crv;
03365    crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
03366    if (crv->subs[SUB_REAL].owner)
03367       crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
03368    crv->bearer = bearer;
03369    crv->call = bearer->call;
03370    crv->pri = pri;
03371    return 0;
03372 }

static int pri_check_restart ( struct dahdi_pri pri  )  [static]

Definition at line 9943 of file chan_dahdi.c.

References dahdi_pri::lastreset, dahdi_pri::numchans, dahdi_pri::pri, PVT_TO_CHANNEL, dahdi_pri::pvts, dahdi_pri::resetpos, dahdi_pri::resetting, and dahdi_pvt::resetting.

Referenced by pri_dchannel().

09944 {
09945    do {
09946       pri->resetpos++;
09947    } while ((pri->resetpos < pri->numchans) &&
09948        (!pri->pvts[pri->resetpos] ||
09949         pri->pvts[pri->resetpos]->call ||
09950         pri->pvts[pri->resetpos]->resetting));
09951    if (pri->resetpos < pri->numchans) {
09952       /* Mark the channel as resetting and restart it */
09953       pri->pvts[pri->resetpos]->resetting = 1;
09954       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
09955    } else {
09956       pri->resetting = 0;
09957       time(&pri->lastreset);
09958    }
09959    return 0;
09960 }

static int pri_create_spanmap ( int  span,
int  trunkgroup,
int  logicalspan 
) [static]

Definition at line 8555 of file chan_dahdi.c.

References ast_log(), dahdi_pri::mastertrunkgroup, dahdi_pri::prilogicalspan, and pris.

Referenced by setup_dahdi().

08556 {
08557    if (pris[span].mastertrunkgroup) {
08558       ast_log(LOG_WARNING, "Span %d is already part of trunk group %d, cannot add to trunk group %d\n", span + 1, pris[span].mastertrunkgroup, trunkgroup);
08559       return -1;
08560    }
08561    pris[span].mastertrunkgroup = trunkgroup;
08562    pris[span].prilogicalspan = logicalspan;
08563    return 0;
08564 }

static int pri_create_trunkgroup ( int  trunkgroup,
int *  channels 
) [static]

Definition at line 8492 of file chan_dahdi.c.

References ast_log(), DAHDI_FILE_CHANNEL, DCHAN_PROVISIONED, dahdi_pri::dchanavail, dahdi_pri::dchannels, errno, NUM_DCHANS, NUM_SPANS, dahdi_pri::offset, pris, dahdi_pri::span, and dahdi_pri::trunkgroup.

Referenced by setup_dahdi().

08493 {
08494    struct dahdi_spaninfo si;
08495    struct dahdi_params p;
08496    int fd;
08497    int span;
08498    int ospan=0;
08499    int x,y;
08500    for (x = 0; x < NUM_SPANS; x++) {
08501       if (pris[x].trunkgroup == trunkgroup) {
08502          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
08503          return -1;
08504       }
08505    }
08506    for (y = 0; y < NUM_DCHANS; y++) {
08507       if (!channels[y]) 
08508          break;
08509       memset(&si, 0, sizeof(si));
08510       memset(&p, 0, sizeof(p));
08511       fd = open(DAHDI_FILE_CHANNEL, O_RDWR);
08512       if (fd < 0) {
08513          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
08514          return -1;
08515       }
08516       x = channels[y];
08517       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
08518          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
08519          close(fd);
08520          return -1;
08521       }
08522       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
08523          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
08524          return -1;
08525       }
08526       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
08527          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
08528          close(fd);
08529          return -1;
08530       }
08531       span = p.spanno - 1;
08532       if (pris[span].trunkgroup) {
08533          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
08534          close(fd);
08535          return -1;
08536       }
08537       if (pris[span].pvts[0]) {
08538          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
08539          close(fd);
08540          return -1;
08541       }
08542       if (!y) {
08543          pris[span].trunkgroup = trunkgroup;
08544          pris[span].offset = channels[y] - p.chanpos;
08545          ospan = span;
08546       }
08547       pris[ospan].dchannels[y] = channels[y];
08548       pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
08549       pris[span].span = span + 1;
08550       close(fd);
08551    }
08552    return 0;   
08553 }

static void* pri_dchannel ( void *  vpri  )  [static]

Definition at line 10042 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_copy_string(), ast_exists_extension(), AST_FORMAT_ULAW, ast_log(), ast_mutex_lock(), ast_pthread_create_background, AST_SOFTHANGUP_DEV, ast_strlen_zero(), ast_tv(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), dahdi_pvt::call, dahdi_pvt::channel, dahdi_chan_name, dahdi_hangup(), dahdi_request(), dahdi_pri::dchannels, dahdi_pri::dchans, do_idle_thread(), dahdi_pri::fds, dahdi_pri::idlecontext, dahdi_pri::idledial, dahdi_pri::idleext, dahdi_pvt::isidlecall, dahdi_pri::lastreset, dahdi_pri::lock, dahdi_pri::minidle, dahdi_pri::minunused, ast_channel::name, dahdi_pri::numchans, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pri::pri, pri_check_restart(), pri_is_up(), dahdi_pri::pvts, dahdi_pri::resetinterval, dahdi_pri::resetpos, dahdi_pvt::resetting, dahdi_pri::resetting, dahdi_pri::switchtype, and t.

10043 {
10044    struct dahdi_pri *pri = vpri;
10045    pri_event *e;
10046    struct pollfd fds[NUM_DCHANS];
10047    int res;
10048    int chanpos = 0;
10049    int x;
10050    int haveidles;
10051    int activeidles;
10052    int nextidle = -1;
10053    struct ast_channel *c;
10054    struct timeval tv, lowest, *next;
10055    struct timeval lastidle = { 0, 0 };
10056    int doidling=0;
10057    char *cc;
10058    char idlen[80];
10059    struct ast_channel *idle;
10060    pthread_t p;
10061    time_t t;
10062    int i, which=-1;
10063    int numdchans;
10064    int cause=0;
10065    struct dahdi_pvt *crv;
10066    pthread_t threadid;
10067    pthread_attr_t attr;
10068    char ani2str[6];
10069    char plancallingnum[256];
10070    char plancallingani[256];
10071    char calledtonstr[10];
10072    
10073    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10074 
10075    gettimeofday(&lastidle, NULL);
10076    if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
10077       /* Need to do idle dialing, check to be sure though */
10078       cc = strchr(pri->idleext, '@');
10079       if (cc) {
10080          *cc = '\0';
10081          cc++;
10082          ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
10083 #if 0
10084          /* Extensions may not be loaded yet */
10085          if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
10086             ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
10087          else
10088 #endif
10089             doidling = 1;
10090       } else
10091          ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
10092    }
10093    for (;;) {
10094       for (i = 0; i < NUM_DCHANS; i++) {
10095          if (!pri->dchannels[i])
10096             break;
10097          fds[i].fd = pri->fds[i];
10098          fds[i].events = POLLIN | POLLPRI;
10099          fds[i].revents = 0;
10100       }
10101       numdchans = i;
10102       time(&t);
10103       ast_mutex_lock(&pri->lock);
10104       if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
10105          if (pri->resetting && pri_is_up(pri)) {
10106             if (pri->resetpos < 0)
10107                pri_check_restart(pri);
10108          } else {
10109             if (!pri->resetting  && (t - pri->lastreset) >= pri->resetinterval) {
10110                pri->resetting = 1;
10111                pri->resetpos = -1;
10112             }
10113          }
10114       }
10115       /* Look for any idle channels if appropriate */
10116       if (doidling && pri_is_up(pri)) {
10117          nextidle = -1;
10118          haveidles = 0;
10119          activeidles = 0;
10120          for (x = pri->numchans; x >= 0; x--) {
10121             if (pri->pvts[x] && !pri->pvts[x]->owner && 
10122                 !pri->pvts[x]->call) {
10123                if (haveidles < pri->minunused) {
10124                   haveidles++;
10125                } else if (!pri->pvts[x]->resetting) {
10126                   nextidle = x;
10127                   break;
10128                }
10129             } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
10130                activeidles++;
10131          }
10132          if (nextidle > -1) {
10133             if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
10134                /* Don't create a new idle call more than once per second */
10135                snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
10136                idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
10137                if (idle) {
10138                   pri->pvts[nextidle]->isidlecall = 1;
10139                   if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
10140                      ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
10141                      dahdi_hangup(idle);
10142                   }
10143                } else
10144                   ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
10145                gettimeofday(&lastidle, NULL);
10146             }
10147          } else if ((haveidles < pri->minunused) &&
10148                (activeidles > pri->minidle)) {
10149             /* Mark something for hangup if there is something 
10150                that can be hungup */
10151             for (x = pri->numchans; x >= 0; x--) {
10152                /* find a candidate channel */
10153                if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
10154                   pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10155                   haveidles++;
10156                   /* Stop if we have enough idle channels or
10157                     can't spare any more active idle ones */
10158                   if ((haveidles >= pri->minunused) ||
10159                       (activeidles <= pri->minidle))
10160                      break;
10161                } 
10162             }
10163          }
10164       }
10165       /* Start with reasonable max */
10166       lowest = ast_tv(60, 0);
10167       for (i = 0; i < NUM_DCHANS; i++) {
10168          /* Find lowest available d-channel */
10169          if (!pri->dchannels[i])
10170             break;
10171          if ((next = pri_schedule_next(pri->dchans[i]))) {
10172             /* We need relative time here */
10173             tv = ast_tvsub(*next, ast_tvnow());
10174             if (tv.tv_sec < 0) {
10175                tv = ast_tv(0,0);
10176             }
10177             if (doidling || pri->resetting) {
10178                if (tv.tv_sec > 1) {
10179                   tv = ast_tv(1, 0);
10180                }
10181             } else {
10182                if (tv.tv_sec > 60) {
10183                   tv = ast_tv(60, 0);
10184                }
10185             }
10186          } else if (doidling || pri->resetting) {
10187             /* Make sure we stop at least once per second if we're
10188                monitoring idle channels */
10189             tv = ast_tv(1,0);
10190          } else {
10191             /* Don't poll for more than 60 seconds */
10192             tv = ast_tv(60, 0);
10193          }
10194          if (!i || ast_tvcmp(tv, lowest) < 0) {
10195             lowest = tv;
10196          }
10197       }
10198       ast_mutex_unlock(&pri->lock);
10199 
10200       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
10201       pthread_testcancel();
10202       e = NULL;
10203       res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
10204       pthread_testcancel();
10205       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10206 
10207       ast_mutex_lock(&pri->lock);
10208       if (!res) {
10209          for (which = 0; which < NUM_DCHANS; which++) {
10210             if (!pri->dchans[which])
10211                break;
10212             /* Just a timeout, run the scheduler */
10213             e = pri_schedule_run(pri->dchans[which]);
10214             if (e)
10215                break;
10216          }
10217       } else if (res > -1) {
10218          for (which = 0; which < NUM_DCHANS; which++) {
10219             if (!pri->dchans[which])
10220                break;
10221             if (fds[which].revents & POLLPRI) {
10222                /* Check for an event */
10223                x = 0;
10224                res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
10225                if (x) 
10226                   ast_log(LOG_NOTICE, "PRI got event: %s (%d) on %s D-channel of span %d\n", event2str(x), x, pri_order(which), pri->span);
10227                /* Keep track of alarm state */  
10228                if (x == DAHDI_EVENT_ALARM) {
10229                   pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
10230                   pri_find_dchan(pri);
10231                } else if (x == DAHDI_EVENT_NOALARM) {
10232                   pri->dchanavail[which] |= DCHAN_NOTINALARM;
10233                   pri_restart(pri->dchans[which]);
10234                }
10235             
10236                if (option_debug)
10237                   ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
10238             } else if (fds[which].revents & POLLIN) {
10239                e = pri_check_event(pri->dchans[which]);
10240             }
10241             if (e)
10242                break;
10243          }
10244       } else if (errno != EINTR)
10245          ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
10246 
10247       if (e) {
10248          if (pri->debug)
10249             pri_dump_event(pri->dchans[which], e);
10250 
10251          if (e->e != PRI_EVENT_DCHAN_DOWN) {
10252             if (!(pri->dchanavail[which] & DCHAN_UP)) {
10253                if (option_verbose > 1) 
10254                   ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
10255             }
10256             pri->dchanavail[which] |= DCHAN_UP;
10257          } else {
10258             if (pri->dchanavail[which] & DCHAN_UP) {
10259                if (option_verbose > 1) 
10260                   ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
10261             }
10262             pri->dchanavail[which] &= ~DCHAN_UP;
10263          }
10264 
10265          if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
10266             /* Must be an NFAS group that has the secondary dchan active */
10267             pri->pri = pri->dchans[which];
10268 
10269          switch (e->e) {
10270          case PRI_EVENT_DCHAN_UP:
10271             if (!pri->pri) pri_find_dchan(pri);
10272 
10273             /* Note presense of D-channel */
10274             time(&pri->lastreset);
10275 
10276             /* Restart in 5 seconds */
10277             if (pri->resetinterval > -1) {
10278                pri->lastreset -= pri->resetinterval;
10279                pri->lastreset += 5;
10280             }
10281             pri->resetting = 0;
10282             /* Take the channels from inalarm condition */
10283             for (i = 0; i < pri->numchans; i++)
10284                if (pri->pvts[i]) {
10285                   pri->pvts[i]->inalarm = 0;
10286                }
10287             break;
10288          case PRI_EVENT_DCHAN_DOWN:
10289             pri_find_dchan(pri);
10290             if (!pri_is_up(pri)) {
10291                pri->resetting = 0;
10292                /* Hangup active channels and put them in alarm mode */
10293                for (i = 0; i < pri->numchans; i++) {
10294                   struct dahdi_pvt *p = pri->pvts[i];
10295                   if (p) {
10296                      if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
10297                         /* T309 is not enabled : hangup calls when alarm occurs */
10298                         if (p->call) {
10299                            if (p->pri && p->pri->pri) {
10300                               pri_hangup(p->pri->pri, p->call, -1);
10301                               pri_destroycall(p->pri->pri, p->call);
10302                               p->call = NULL;
10303                            } else
10304                               ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
10305                         }
10306                         if (p->realcall) {
10307                            pri_hangup_all(p->realcall, pri);
10308                         } else if (p->owner)
10309                            p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10310                      }
10311                      p->inalarm = 1;
10312                   }
10313                }
10314             }
10315             break;
10316          case PRI_EVENT_RESTART:
10317             if (e->restart.channel > -1) {
10318                chanpos = pri_find_principle(pri, e->restart.channel);
10319                if (chanpos < 0)
10320                   ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 
10321                      PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
10322                else {
10323                   if (option_verbose > 2)
10324                      ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n", 
10325                         PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
10326                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10327                   if (pri->pvts[chanpos]->call) {
10328                      pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
10329                      pri->pvts[chanpos]->call = NULL;
10330                   }
10331                   /* Force soft hangup if appropriate */
10332                   if (pri->pvts[chanpos]->realcall) 
10333                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10334                   else if (pri->pvts[chanpos]->owner)
10335                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10336                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10337                }
10338             } else {
10339                if (option_verbose > 2)
10340                   ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
10341                for (x = 0; x < pri->numchans; x++)
10342                   if (pri->pvts[x]) {
10343                      ast_mutex_lock(&pri->pvts[x]->lock);
10344                      if (pri->pvts[x]->call) {
10345                         pri_destroycall(pri->pri, pri->pvts[x]->call);
10346                         pri->pvts[x]->call = NULL;
10347                      }
10348                      if (pri->pvts[x]->realcall) 
10349                         pri_hangup_all(pri->pvts[x]->realcall, pri);
10350                      else if (pri->pvts[x]->owner)
10351                         pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10352                      ast_mutex_unlock(&pri->pvts[x]->lock);
10353                   }
10354             }
10355             break;
10356          case PRI_EVENT_KEYPAD_DIGIT:
10357             chanpos = pri_find_principle(pri, e->digit.channel);
10358             if (chanpos < 0) {
10359                ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 
10360                   PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
10361             } else {
10362                chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
10363                if (chanpos > -1) {
10364                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10365                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
10366                   if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
10367                      /* how to do that */
10368                      int digitlen = strlen(e->digit.digits);
10369                      char digit;
10370                      int i;               
10371                      for (i = 0; i < digitlen; i++) { 
10372                         digit = e->digit.digits[i];
10373                         {
10374                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
10375                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10376                         }
10377                      }
10378                   }
10379                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10380                }
10381             }
10382             break;
10383             
10384          case PRI_EVENT_INFO_RECEIVED:
10385             chanpos = pri_find_principle(pri, e->ring.channel);
10386             if (chanpos < 0) {
10387                ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 
10388                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10389             } else {
10390                chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
10391                if (chanpos > -1) {
10392                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10393                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
10394                   if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
10395                      /* how to do that */
10396                      int digitlen = strlen(e->ring.callednum);
10397                      char digit;
10398                      int i;               
10399                      for (i = 0; i < digitlen; i++) { 
10400                         digit = e->ring.callednum[i];
10401                         {
10402                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
10403                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10404                         }
10405                      }
10406                   }
10407                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10408                }
10409             }
10410             break;
10411          case PRI_EVENT_RING:
10412             crv = NULL;
10413             if (e->ring.channel == -1)
10414                chanpos = pri_find_empty_chan(pri, 1);
10415             else
10416                chanpos = pri_find_principle(pri, e->ring.channel);
10417             /* if no channel specified find one empty */
10418             if (chanpos < 0) {
10419                ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 
10420                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10421             } else {
10422                ast_mutex_lock(&pri->pvts[chanpos]->lock);
10423                if (pri->pvts[chanpos]->owner) {
10424                   if (pri->pvts[chanpos]->call == e->ring.call) {
10425                      ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 
10426                         PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10427                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10428                      break;
10429                   } else {
10430                      /* This is where we handle initial glare */
10431                      ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d.  Attempting to renegotiating channel.\n", 
10432                      PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10433                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10434                      chanpos = -1;
10435                   }
10436                }
10437                if (chanpos > -1)
10438                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10439             }
10440             if ((chanpos < 0) && (e->ring.flexible))
10441                chanpos = pri_find_empty_chan(pri, 1);
10442             if (chanpos > -1) {
10443                ast_mutex_lock(&pri->pvts[chanpos]->lock);
10444                if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
10445                   /* Should be safe to lock CRV AFAIK while bearer is still locked */
10446                   crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
10447                   if (crv)
10448                      ast_mutex_lock(&crv->lock);
10449                   if (!crv || crv->owner) {
10450                      pri->pvts[chanpos]->call = NULL;
10451                      if (crv) {
10452                         if (crv->owner)
10453                            crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10454                         ast_log(LOG_WARNING, "Call received for busy CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
10455                      } else
10456                         ast_log(LOG_NOTICE, "Call received for unconfigured CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
10457                      pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
10458                      if (crv)
10459                         ast_mutex_unlock(&crv->lock);
10460                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10461                      break;
10462                   }
10463                }
10464                pri->pvts[chanpos]->call = e->ring.call;
10465                apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
10466                if (pri->pvts[chanpos]->use_callerid) {
10467                   ast_shrink_phone_number(plancallingnum);
10468                   ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
10469 #ifdef PRI_ANI
10470                   if (!ast_strlen_zero(e->ring.callingani)) {
10471                      apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
10472                      ast_shrink_phone_number(plancallingani);
10473                      ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
10474                   } else {
10475                      pri->pvts[chanpos]->cid_ani[0] = '\0';
10476                   }
10477 #endif
10478                   ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
10479                   pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
10480                } else {
10481                   pri->pvts[chanpos]->cid_num[0] = '\0';
10482                   pri->pvts[chanpos]->cid_ani[0] = '\0';
10483                   pri->pvts[chanpos]->cid_name[0] = '\0';
10484                   pri->pvts[chanpos]->cid_ton = 0;
10485                }
10486                apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
10487                           e->ring.redirectingnum, e->ring.callingplanrdnis);
10488                /* If immediate=yes go to s|1 */
10489                if (pri->pvts[chanpos]->immediate) {
10490                   if (option_verbose > 2)
10491                      ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
10492                   pri->pvts[chanpos]->exten[0] = 's';
10493                   pri->pvts[chanpos]->exten[1] = '\0';
10494                }
10495                /* Get called number */
10496                else if (!ast_strlen_zero(e->ring.callednum)) {
10497                   ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
10498                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
10499                } else if (pri->overlapdial)
10500                   pri->pvts[chanpos]->exten[0] = '\0';
10501                else {
10502                   /* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
10503                   pri->pvts[chanpos]->exten[0] = 's';
10504                   pri->pvts[chanpos]->exten[1] = '\0';
10505                }
10506                /* Set DNID on all incoming calls -- even immediate */
10507                if (!ast_strlen_zero(e->ring.callednum))
10508                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
10509                /* No number yet, but received "sending complete"? */
10510                if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
10511                   if (option_verbose > 2)
10512                      ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
10513                   pri->pvts[chanpos]->exten[0] = 's';
10514                   pri->pvts[chanpos]->exten[1] = '\0';
10515                }
10516 
10517                /* Make sure extension exists (or in overlap dial mode, can exist) */
10518                if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
10519                   ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
10520                   /* Setup law */
10521                   int law;
10522                   if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
10523                      /* Set to audio mode at this point */
10524                      law = 1;
10525                      if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
10526                         ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
10527                   }
10528                   if (e->ring.layer1 == PRI_LAYER_1_ALAW)
10529                      law = DAHDI_LAW_ALAW;
10530                   else
10531                      law = DAHDI_LAW_MULAW;
10532                   res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
10533                   if (res < 0) 
10534                      ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
10535                   res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
10536                   if (res < 0)
10537                      ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
10538                   if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
10539                      /* Just announce proceeding */
10540                      pri->pvts[chanpos]->proceeding = 1;
10541                      pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
10542                   } else {
10543                      if (pri->switchtype != PRI_SWITCH_GR303_TMC) 
10544                         pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
10545                      else
10546                         pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
10547                   }
10548                   /* Get the use_callingpres state */
10549                   pri->pvts[chanpos]->callingpres = e->ring.callingpres;
10550                
10551                   /* Start PBX */
10552                   if (!e->ring.complete
10553                      && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
10554                      && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
10555                      /*
10556                       * Release the PRI lock while we create the channel
10557                       * so other threads can send D channel messages.
10558                       */
10559                      ast_mutex_unlock(&pri->lock);
10560                      if (crv) {
10561                         /* Set bearer and such */
10562                         pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
10563                         c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
10564                         pri->pvts[chanpos]->owner = &inuse;
10565                         ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
10566                      } else {
10567                         c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
10568                      }
10569                      ast_mutex_lock(&pri->lock);
10570                      if (c) {
10571                         if (!ast_strlen_zero(e->ring.callingsubaddr)) {
10572                            pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
10573                         }
10574                         if (e->ring.ani2 >= 0) {
10575                            snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
10576                            pbx_builtin_setvar_helper(c, "ANI2", ani2str);
10577                         }
10578 
10579 #ifdef SUPPORT_USERUSER
10580                         if (!ast_strlen_zero(e->ring.useruserinfo)) {
10581                            pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
10582                         }
10583 #endif
10584 
10585                         snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
10586                         pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
10587                         if (e->ring.redirectingreason >= 0)
10588                            pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
10589                      }
10590 
10591                      pthread_attr_init(&attr);
10592                      pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10593                      if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
10594                         if (option_verbose > 2)
10595                            ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
10596                               plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
10597                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10598                      } else {
10599                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
10600                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10601                         if (c)
10602                            ast_hangup(c);
10603                         else {
10604                            pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
10605                            pri->pvts[chanpos]->call = NULL;
10606                         }
10607                      }
10608                      pthread_attr_destroy(&attr);
10609                   } else {
10610                      /*
10611                       * Release the PRI lock while we create the channel
10612                       * so other threads can send D channel messages.
10613                       */
10614                      ast_mutex_unlock(&pri->lock);
10615                      c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
10616                      ast_mutex_lock(&pri->lock);
10617                      if (c) {
10618                         /*
10619                          * It is reasonably safe to set the following
10620                          * channel variables while the PRI and DAHDI private
10621                          * structures are locked.  The PBX has not been
10622                          * started yet and it is unlikely that any other task
10623                          * will do anything with the channel we have just
10624                          * created.
10625                          */
10626                         if (!ast_strlen_zero(e->ring.callingsubaddr)) {
10627                            pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
10628                         }
10629                         if (e->ring.ani2 >= 0) {
10630                            snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
10631                            pbx_builtin_setvar_helper(c, "ANI2", ani2str);
10632                         }
10633 
10634 #ifdef SUPPORT_USERUSER
10635                         if (!ast_strlen_zero(e->ring.useruserinfo)) {
10636                            pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
10637                         }
10638 #endif
10639 
10640                         if (e->ring.redirectingreason >= 0)
10641                            pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
10642 
10643                         snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
10644                         pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
10645                      }
10646                      if (c && !ast_pbx_start(c)) {
10647                         if (option_verbose > 2)
10648                            ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
10649                               plancallingnum, pri->pvts[chanpos]->exten,
10650                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10651 
10652                         dahdi_enable_ec(pri->pvts[chanpos]);
10653                      } else {
10654                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
10655                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10656                         if (c) {
10657                            ast_hangup(c);
10658                         } else {
10659                            pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
10660                            pri->pvts[chanpos]->call = NULL;
10661                         }
10662                      }
10663                   }
10664                } else {
10665                   if (option_verbose > 2)
10666                      ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist.  Rejecting call on channel %d/%d, span %d\n",
10667                         pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 
10668                            pri->pvts[chanpos]->prioffset, pri->span);
10669                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
10670                   pri->pvts[chanpos]->call = NULL;
10671                   pri->pvts[chanpos]->exten[0] = '\0';
10672                }
10673                if (crv)
10674                   ast_mutex_unlock(&crv->lock);
10675                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10676             } else {
10677                if (e->ring.flexible)
10678                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
10679                else
10680                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
10681             }
10682             break;
10683          case PRI_EVENT_RINGING:
10684             chanpos = pri_find_principle(pri, e->ringing.channel);
10685             if (chanpos < 0) {
10686                ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 
10687                   PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
10688             } else {
10689                chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
10690                if (chanpos < 0) {
10691                   ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 
10692                      PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
10693                } else {
10694                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10695                   if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
10696                      dahdi_enable_ec(pri->pvts[chanpos]);
10697                      pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
10698                      pri->pvts[chanpos]->alerting = 1;
10699                   } else
10700                      ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
10701 #ifdef PRI_PROGRESS_MASK
10702                   if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10703 #else
10704                   if (e->ringing.progress == 8) {
10705 #endif
10706                      /* Now we can do call progress detection */
10707                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10708                         /* RINGING detection isn't required because we got ALERTING signal */
10709                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
10710                         pri->pvts[chanpos]->dsp_features = 0;
10711                      }
10712                   }
10713 
10714 #ifdef SUPPORT_USERUSER
10715                   if (!ast_strlen_zero(e->ringing.useruserinfo)) {
10716                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
10717                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10718                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
10719                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
10720                   }
10721 #endif
10722 
10723                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10724                }
10725             }
10726             break;
10727          case PRI_EVENT_PROGRESS:
10728             /* Get chan value if e->e is not PRI_EVNT_RINGING */
10729             chanpos = pri_find_principle(pri, e->proceeding.channel);
10730             if (chanpos > -1) {
10731 #ifdef PRI_PROGRESS_MASK
10732                if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
10733 #else
10734                if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
10735 #endif
10736                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
10737 
10738                   if (e->proceeding.cause > -1) {
10739                      if (option_verbose > 2)
10740                         ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
10741 
10742                      /* Work around broken, out of spec USER_BUSY cause in a progress message */
10743                      if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
10744                         if (pri->pvts[chanpos]->owner) {
10745                            if (option_verbose > 2)
10746                               ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
10747 
10748                            pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
10749                            f.subclass = AST_CONTROL_BUSY;
10750                         }
10751                      }
10752                   }
10753                   
10754                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10755                   ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
10756                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
10757                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10758 #ifdef PRI_PROGRESS_MASK
10759                   if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10760 #else
10761                   if (e->proceeding.progress == 8) {
10762 #endif
10763                      /* Now we can do call progress detection */
10764                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10765                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
10766                         pri->pvts[chanpos]->dsp_features = 0;
10767                      }
10768                      /* Bring voice path up */
10769                      f.subclass = AST_CONTROL_PROGRESS;
10770                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10771                   }
10772                   pri->pvts[chanpos]->progress = 1;
10773                   pri->pvts[chanpos]->dialing = 0;
10774                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10775                }
10776             }
10777             break;
10778          case PRI_EVENT_PROCEEDING:
10779             chanpos = pri_find_principle(pri, e->proceeding.channel);
10780             if (chanpos > -1) {
10781                if (!pri->pvts[chanpos]->proceeding) {
10782                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
10783                   
10784                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10785                   ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
10786                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
10787                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10788 #ifdef PRI_PROGRESS_MASK
10789                   if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10790 #else
10791                   if (e->proceeding.progress == 8) {
10792 #endif
10793                      /* Now we can do call progress detection */
10794                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10795                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
10796                         pri->pvts[chanpos]->dsp_features = 0;
10797                      }
10798                      /* Bring voice path up */
10799                      f.subclass = AST_CONTROL_PROGRESS;
10800                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10801                   }
10802                   pri->pvts[chanpos]->proceeding = 1;
10803                   pri->pvts[chanpos]->dialing = 0;
10804                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10805                }
10806             }
10807             break;
10808          case PRI_EVENT_FACNAME:
10809             chanpos = pri_find_principle(pri, e->facname.channel);
10810             if (chanpos < 0) {
10811                ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 
10812                   PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
10813             } else {
10814                chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
10815                if (chanpos < 0) {
10816                   ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 
10817                      PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
10818                } else {
10819                   /* Re-use *69 field for PRI */
10820                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10821                   ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
10822                   ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
10823                   pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
10824                   dahdi_enable_ec(pri->pvts[chanpos]);
10825                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10826                }
10827             }
10828             break;            
10829          case PRI_EVENT_ANSWER:
10830             chanpos = pri_find_principle(pri, e->answer.channel);
10831             if (chanpos < 0) {
10832                ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 
10833                   PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
10834             } else {
10835                chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
10836                if (chanpos < 0) {
10837                   ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 
10838                      PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
10839                } else {
10840                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10841                   /* Now we can do call progress detection */
10842 
10843                   /* We changed this so it turns on the DSP no matter what... progress or no progress.
10844                    * By this time, we need DTMF detection and other features that were previously disabled
10845                    * -- Matt F */
10846                   if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10847                      ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
10848                      pri->pvts[chanpos]->dsp_features = 0;
10849                   }
10850                   if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
10851                      ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
10852                      x = DAHDI_START;
10853                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
10854                      if (res < 0) {
10855                         if (errno != EINPROGRESS) {
10856                            ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
10857                         }
10858                      }
10859                   } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
10860                      pri->pvts[chanpos]->dialing = 1;
10861                      /* Send any "w" waited stuff */
10862                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
10863                      if (res < 0) {
10864                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
10865                         pri->pvts[chanpos]->dop.dialstr[0] = '\0';
10866                      } else 
10867                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
10868                      pri->pvts[chanpos]->dop.dialstr[0] = '\0';
10869                   } else if (pri->pvts[chanpos]->confirmanswer) {
10870                      ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
10871                   } else {
10872                      pri->pvts[chanpos]->dialing = 0;
10873                      pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
10874                      /* Enable echo cancellation if it's not on already */
10875                      dahdi_enable_ec(pri->pvts[chanpos]);
10876                   }
10877 
10878 #ifdef SUPPORT_USERUSER
10879                   if (!ast_strlen_zero(e->answer.useruserinfo)) {
10880                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
10881                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10882                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
10883                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
10884                   }
10885 #endif
10886 
10887                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10888                }
10889             }
10890             break;            
10891          case PRI_EVENT_HANGUP:
10892             chanpos = pri_find_principle(pri, e->hangup.channel);
10893             if (chanpos < 0) {
10894                ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 
10895                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10896             } else {
10897                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
10898                if (chanpos > -1) {
10899                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10900                   if (!pri->pvts[chanpos]->alreadyhungup) {
10901                      /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
10902                      pri->pvts[chanpos]->alreadyhungup = 1;
10903                      if (pri->pvts[chanpos]->realcall) 
10904                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10905                      else if (pri->pvts[chanpos]->owner) {
10906                         /* Queue a BUSY instead of a hangup if our cause is appropriate */
10907                         pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
10908                         switch (pri->pvts[chanpos]->owner->_state) {
10909                         case AST_STATE_BUSY:
10910                         case AST_STATE_UP:
10911                            pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10912                            break;
10913                         default:
10914                            switch (e->hangup.cause) {
10915                               case PRI_CAUSE_USER_BUSY:
10916                                  pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
10917                                  break;
10918                               case PRI_CAUSE_CALL_REJECTED:
10919                               case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
10920                               case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
10921                               case PRI_CAUSE_SWITCH_CONGESTION:
10922                               case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
10923                               case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
10924                                  pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
10925                                  break;
10926                               default:
10927                                  pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10928                            }
10929                            break;
10930                         }
10931                      }
10932                      if (option_verbose > 2) 
10933                         ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n", 
10934                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
10935                   } else {
10936                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
10937                      pri->pvts[chanpos]->call = NULL;
10938                   }
10939                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
10940                      if (option_verbose > 2)
10941                         ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 
10942                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10943                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
10944                      pri->pvts[chanpos]->resetting = 1;
10945                   }
10946                   if (e->hangup.aoc_units > -1)
10947                      if (option_verbose > 2)
10948                         ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
10949                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
10950 
10951 #ifdef SUPPORT_USERUSER
10952                   if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
10953                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
10954                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10955                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
10956                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
10957                   }
10958 #endif
10959 
10960                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10961                } else {
10962                   ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 
10963                      PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10964                }
10965             } 
10966             break;
10967 #ifndef PRI_EVENT_HANGUP_REQ
10968 #error please update libpri
10969 #endif
10970          case PRI_EVENT_HANGUP_REQ:
10971             chanpos = pri_find_principle(pri, e->hangup.channel);
10972             if (chanpos < 0) {
10973                ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 
10974                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10975             } else {
10976                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
10977                if (chanpos > -1) {
10978                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10979                   if (pri->pvts[chanpos]->realcall) 
10980                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10981                   else if (pri->pvts[chanpos]->owner) {
10982                      pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
10983                      switch (pri->pvts[chanpos]->owner->_state) {
10984                      case AST_STATE_BUSY:
10985                      case AST_STATE_UP:
10986                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10987                         break;
10988                      default:
10989                         switch (e->hangup.cause) {
10990                            case PRI_CAUSE_USER_BUSY:
10991                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
10992                               break;
10993                            case PRI_CAUSE_CALL_REJECTED:
10994                            case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
10995                            case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
10996                            case PRI_CAUSE_SWITCH_CONGESTION:
10997                            case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
10998                            case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
10999                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11000                               break;
11001                            default:
11002                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11003                         }
11004                         break;
11005                      }
11006                      if (option_verbose > 2) 
11007                         ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause);
11008                      if (e->hangup.aoc_units > -1)
11009                         if (option_verbose > 2)
11010                            ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11011                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11012                   } else {
11013                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11014                      pri->pvts[chanpos]->call = NULL;
11015                   }
11016                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11017                      if (option_verbose > 2)
11018                         ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n", 
11019                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11020                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11021                      pri->pvts[chanpos]->resetting = 1;
11022                   }
11023 
11024 #ifdef SUPPORT_USERUSER
11025                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11026                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
11027                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11028                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11029                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11030                   }
11031 #endif
11032 
11033                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11034                } else {
11035                   ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11036                }
11037             } 
11038             break;
11039          case PRI_EVENT_HANGUP_ACK:
11040             chanpos = pri_find_principle(pri, e->hangup.channel);
11041             if (chanpos < 0) {
11042                ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 
11043                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11044             } else {
11045                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11046                if (chanpos > -1) {
11047                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11048                   pri->pvts[chanpos]->call = NULL;
11049                   pri->pvts[chanpos]->resetting = 0;
11050                   if (pri->pvts[chanpos]->owner) {
11051                      if (option_verbose > 2) 
11052                         ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11053                   }
11054 
11055 #ifdef SUPPORT_USERUSER
11056                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11057                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
11058                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11059                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11060                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11061                   }
11062 #endif
11063 
11064                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11065                }
11066             }
11067             break;
11068          case PRI_EVENT_CONFIG_ERR:
11069             ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
11070             break;
11071          case PRI_EVENT_RESTART_ACK:
11072             chanpos = pri_find_principle(pri, e->restartack.channel);
11073             if (chanpos < 0) {
11074                /* Sometime switches (e.g. I421 / British Telecom) don't give us the
11075                   channel number, so we have to figure it out...  This must be why
11076                   everybody resets exactly a channel at a time. */
11077                for (x = 0; x < pri->numchans; x++) {
11078                   if (pri->pvts[x] && pri->pvts[x]->resetting) {
11079                      chanpos = x;
11080                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11081                      ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 
11082                            pri->pvts[chanpos]->prioffset, pri->span);
11083                      if (pri->pvts[chanpos]->realcall) 
11084                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11085                      else if (pri->pvts[chanpos]->owner) {
11086                         ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 
11087                            pri->pvts[chanpos]->prioffset, pri->span);
11088                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11089                      }
11090                      pri->pvts[chanpos]->resetting = 0;
11091                      if (option_verbose > 2)
11092                         ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 
11093                            pri->pvts[chanpos]->prioffset, pri->span);
11094                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11095                      if (pri->resetting)
11096                         pri_check_restart(pri);
11097                      break;
11098                   }
11099                }
11100                if (chanpos < 0) {
11101                   ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 
11102                      PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11103                }
11104             } else {
11105                if (pri->pvts[chanpos]) {
11106                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11107                   if (pri->pvts[chanpos]->realcall) 
11108                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11109                   else if (pri->pvts[chanpos]->owner) {
11110                      ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
11111                         PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11112                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11113                   }
11114                   pri->pvts[chanpos]->resetting = 0;
11115                   if (option_verbose > 2)
11116                      ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 
11117                            pri->pvts[chanpos]->prioffset, pri->span);
11118                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11119                   if (pri->resetting)
11120                      pri_check_restart(pri);
11121                }
11122             }
11123             break;
11124          case PRI_EVENT_SETUP_ACK:
11125             chanpos = pri_find_principle(pri, e->setup_ack.channel);
11126             if (chanpos < 0) {
11127                ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 
11128                   PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
11129             } else {
11130                chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
11131                if (chanpos > -1) {
11132                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11133                   pri->pvts[chanpos]->setup_ack = 1;
11134                   /* Send any queued digits */
11135                   for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
11136                      ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
11137                      pri_information(pri->pri, pri->pvts[chanpos]->call, 
11138                         pri->pvts[chanpos]->dialdest[x]);
11139                   }
11140                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11141                } else
11142                   ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
11143             }
11144             break;
11145          case PRI_EVENT_NOTIFY:
11146             chanpos = pri_find_principle(pri, e->notify.channel);
11147             if (chanpos < 0) {
11148                ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
11149                   PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
11150             } else {
11151                struct ast_frame f = { AST_FRAME_CONTROL, };
11152                ast_mutex_lock(&pri->pvts[chanpos]->lock);
11153                switch (e->notify.info) {
11154                case PRI_NOTIFY_REMOTE_HOLD:
11155                   f.subclass = AST_CONTROL_HOLD;
11156                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11157                   break;
11158                case PRI_NOTIFY_REMOTE_RETRIEVAL:
11159                   f.subclass = AST_CONTROL_UNHOLD;
11160                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11161                   break;
11162                }
11163                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11164             }
11165             break;
11166          default:
11167             ast_log(LOG_DEBUG, "Event: %d\n", e->e);
11168          }
11169       }  
11170       ast_mutex_unlock(&pri->lock);
11171    }
11172    /* Never reached */
11173    return NULL;
11174 }

static struct dahdi_pvt* pri_find_crv ( struct dahdi_pri pri,
int  crv 
) [static]

Definition at line 9681 of file chan_dahdi.c.

References dahdi_pvt::channel, dahdi_pri::crvs, dahdi_pvt::next, and dahdi_pvt::pri.

09682 {
09683    struct dahdi_pvt *p;
09684    p = pri->crvs;
09685    while (p) {
09686       if (p->channel == crv)
09687          return p;
09688       p = p->next;
09689    }
09690    return NULL;
09691 }

static int pri_find_dchan ( struct dahdi_pri pri  )  [static]

Definition at line 3403 of file chan_dahdi.c.

References DCHAN_AVAILABLE, dahdi_pri::dchanavail, dahdi_pri::dchans, NUM_DCHANS, and dahdi_pri::pri.

03404 {
03405    int oldslot = -1;
03406    struct pri *old;
03407    int newslot = -1;
03408    int x;
03409    old = pri->pri;
03410    for (x = 0; x < NUM_DCHANS; x++) {
03411       if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
03412          newslot = x;
03413       if (pri->dchans[x] == old) {
03414          oldslot = x;
03415       }
03416    }
03417    if (newslot < 0) {
03418       newslot = 0;
03419       ast_log(LOG_WARNING, "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
03420          pri->dchannels[newslot]);
03421    }
03422    if (old && (oldslot != newslot))
03423       ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
03424          pri->dchannels[oldslot], pri->dchannels[newslot]);
03425    pri->pri = pri->dchans[newslot];
03426    return 0;
03427 }

static int pri_find_empty_chan ( struct dahdi_pri pri,
int  backwards 
) [static]

Definition at line 9304 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::inalarm, LOG_DEBUG, dahdi_pvt::logicalspan, dahdi_pri::numchans, dahdi_pvt::owner, dahdi_pvt::prioffset, and dahdi_pri::pvts.

Referenced by dahdi_request().

09305 {
09306    int x;
09307    if (backwards)
09308       x = pri->numchans;
09309    else
09310       x = 0;
09311    for (;;) {
09312       if (backwards && (x < 0))
09313          break;
09314       if (!backwards && (x >= pri->numchans))
09315          break;
09316       if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
09317          ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n", 
09318             pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09319          return x;
09320       }
09321       if (backwards)
09322          x--;
09323       else
09324          x++;
09325    }
09326    return -1;
09327 }

static int pri_find_principle ( struct dahdi_pri pri,
int  channel 
) [static]

Definition at line 9694 of file chan_dahdi.c.

References dahdi_pvt::logicalspan, dahdi_pri::numchans, pri_active_dchan_fd(), PRI_CHANNEL, PRI_EXPLICIT, PRI_SPAN, dahdi_pri::prilogicalspan, dahdi_pvt::prioffset, pris, dahdi_pri::pvts, and dahdi_pvt::span.

09695 {
09696    int x;
09697    int span = PRI_SPAN(channel);
09698    int spanfd;
09699    struct dahdi_params param;
09700    int principle = -1;
09701    int explicit = PRI_EXPLICIT(channel);
09702    channel = PRI_CHANNEL(channel);
09703 
09704    if (!explicit) {
09705       spanfd = pri_active_dchan_fd(pri);
09706       memset(&param, 0, sizeof(param));
09707       if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
09708          return -1;
09709       span = pris[param.spanno - 1].prilogicalspan;
09710    }
09711 
09712    for (x = 0; x < pri->numchans; x++) {
09713       if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
09714          principle = x;
09715          break;
09716       }
09717    }
09718    
09719    return principle;
09720 }

static int pri_fixup_principle ( struct dahdi_pri pri,
int  principle,
q931_call *  c 
) [static]

Definition at line 9722 of file chan_dahdi.c.

References ast_log(), ast_string_field_build, ast_verbose(), dahdi_pvt::call, dahdi_chan_name, name, dahdi_pri::numchans, option_verbose, dahdi_pvt::pri, dahdi_pri::pvts, SUB_REAL, dahdi_pri::trunkgroup, and VERBOSE_PREFIX_3.

09723 {
09724    int x;
09725    struct dahdi_pvt *crv;
09726    if (!c) {
09727       if (principle < 0)
09728          return -1;
09729       return principle;
09730    }
09731    if ((principle > -1) && 
09732       (principle < pri->numchans) && 
09733       (pri->pvts[principle]) && 
09734       (pri->pvts[principle]->call == c))
09735       return principle;
09736    /* First, check for other bearers */
09737    for (x = 0; x < pri->numchans; x++) {
09738       if (!pri->pvts[x])
09739          continue;
09740       if (pri->pvts[x]->call == c) {
09741          /* Found our call */
09742          if (principle != x) {
09743             struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
09744 
09745             if (option_verbose > 2)
09746                ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
09747                   old->channel, new->channel);
09748             if (new->owner) {
09749                ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
09750                   old->channel, new->channel, new->channel);
09751                return -1;
09752             }
09753             /* Fix it all up now */
09754             new->owner = old->owner;
09755             old->owner = NULL;
09756             if (new->owner) {
09757                ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
09758                new->owner->tech_pvt = new;
09759                new->owner->fds[0] = new->subs[SUB_REAL].dfd;
09760                new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
09761                old->subs[SUB_REAL].owner = NULL;
09762             } else
09763                ast_log(LOG_WARNING, "Whoa, there's no owner, and we're having to fix up channel %d to channel %d\n", old->channel, new->channel);
09764             new->call = old->call;
09765             old->call = NULL;
09766 
09767             /* Copy any DSP that may be present */
09768             new->dsp = old->dsp;
09769             new->dsp_features = old->dsp_features;
09770             old->dsp = NULL;
09771             old->dsp_features = 0;
09772          }
09773          return principle;
09774       }
09775    }
09776    /* Now check for a CRV with no bearer */
09777    crv = pri->crvs;
09778    while (crv) {
09779       if (crv->call == c) {
09780          /* This is our match...  Perform some basic checks */
09781          if (crv->bearer)
09782             ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
09783          else if (pri->pvts[principle]->owner) 
09784             ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
09785          else {
09786             /* Looks good.  Drop the pseudo channel now, clear up the assignment, and
09787                wakeup the potential sleeper */
09788             dahdi_close_sub(crv, SUB_REAL);
09789             pri->pvts[principle]->call = crv->call;
09790             pri_assign_bearer(crv, pri, pri->pvts[principle]);
09791             ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
09792                            pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
09793                            pri->trunkgroup, crv->channel);
09794             wakeup_sub(crv, SUB_REAL, pri);
09795          }
09796          return principle;
09797       }
09798       crv = crv->next;
09799    }
09800    ast_log(LOG_WARNING, "Call specified, but not found?\n");
09801    return -1;
09802 }

static int pri_grab ( struct dahdi_pvt pvt,
struct dahdi_pri pri 
) [inline, static]

Definition at line 1145 of file chan_dahdi.c.

References ast_mutex_trylock(), AST_PTHREADT_NULL, DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_pri::lock, dahdi_pri::master, and dahdi_pvt::pri.

Referenced by dahdi_answer(), dahdi_call(), dahdi_digit_begin(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_write(), and send_keypad_facility_exec().

01146 {
01147    int res;
01148    /* Grab the lock first */
01149    do {
01150       res = ast_mutex_trylock(&pri->lock);
01151       if (res) {
01152          DEADLOCK_AVOIDANCE(&pvt->lock);
01153       }
01154    } while (res);
01155    /* Then break the poll */
01156    if (pri->master != AST_PTHREADT_NULL)
01157       pthread_kill(pri->master, SIGURG);
01158    return 0;
01159 }

static int pri_hangup_all ( struct dahdi_pvt p,
struct dahdi_pri pri 
) [static]

Definition at line 9962 of file chan_dahdi.c.

References ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_hangup(), DEADLOCK_AVOIDANCE, ast_channel::lock, dahdi_pvt::lock, dahdi_pri::lock, dahdi_subchannel::owner, and dahdi_pvt::subs.

09963 {
09964    int x;
09965    int redo;
09966    ast_mutex_unlock(&pri->lock);
09967    ast_mutex_lock(&p->lock);
09968    do {
09969       redo = 0;
09970       for (x = 0; x < 3; x++) {
09971          while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
09972             redo++;
09973             DEADLOCK_AVOIDANCE(&p->lock);
09974          }
09975          if (p->subs[x].owner) {
09976             ast_queue_hangup(p->subs[x].owner);
09977             ast_mutex_unlock(&p->subs[x].owner->lock);
09978          }
09979       }
09980    } while (redo);
09981    ast_mutex_unlock(&p->lock);
09982    ast_mutex_lock(&pri->lock);
09983    return 0;
09984 }

static int pri_is_up ( struct dahdi_pri pri  )  [static]

Definition at line 3351 of file chan_dahdi.c.

References DCHAN_AVAILABLE, dahdi_pri::dchanavail, NUM_DCHANS, and dahdi_pvt::pri.

Referenced by pri_dchannel().

03352 {
03353    int x;
03354    for (x = 0; x < NUM_DCHANS; x++) {
03355       if (pri->dchanavail[x] == DCHAN_AVAILABLE)
03356          return 1;
03357    }
03358    return 0;
03359 }

static char* pri_order ( int  level  )  [static]

Definition at line 3374 of file chan_dahdi.c.

Referenced by handle_pri_show_span().

03375 {
03376    switch (level) {
03377    case 0:
03378       return "Primary";
03379    case 1:
03380       return "Secondary";
03381    case 2:
03382       return "Tertiary";
03383    case 3:
03384       return "Quaternary";
03385    default:
03386       return "<Unknown>";
03387    }     
03388 }

static void pri_rel ( struct dahdi_pri pri  )  [inline, static]

Definition at line 416 of file chan_dahdi.c.

References ast_mutex_unlock(), and dahdi_pri::pri.

Referenced by dahdi_answer(), dahdi_call(), dahdi_digit_begin(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_write(), and send_keypad_facility_exec().

00417 {
00418    ast_mutex_unlock(&pri->lock);
00419 }

static int pri_resolve_span ( int *  span,
int  channel,
int  offset,
struct dahdi_spaninfo *  si 
) [static]

Definition at line 8446 of file chan_dahdi.c.

References ast_log(), DCHAN_PROVISIONED, dahdi_pri::dchanavail, dahdi_pri::dchannels, dahdi_pri::mastertrunkgroup, NUM_SPANS, dahdi_pri::offset, pris, and dahdi_pri::span.

Referenced by mkintf().

08447 {
08448    int x;
08449    int trunkgroup;
08450    /* Get appropriate trunk group if there is one */
08451    trunkgroup = pris[*span].mastertrunkgroup;
08452    if (trunkgroup) {
08453       /* Select a specific trunk group */
08454       for (x = 0; x < NUM_SPANS; x++) {
08455          if (pris[x].trunkgroup == trunkgroup) {
08456             *span = x;
08457             return 0;
08458          }
08459       }
08460       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
08461       *span = -1;
08462    } else {
08463       if (pris[*span].trunkgroup) {
08464          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
08465          *span = -1;
08466       } else if (pris[*span].mastertrunkgroup) {
08467          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
08468          *span = -1;
08469       } else {
08470          if (si->totalchans == 31) {
08471             /* E1 */
08472             pris[*span].dchannels[0] = 16 + offset;
08473          } else if (si->totalchans == 24) {
08474             /* T1 or J1 */
08475             pris[*span].dchannels[0] = 24 + offset;
08476          } else if (si->totalchans == 3) {
08477             /* BRI */
08478             pris[*span].dchannels[0] = 3 + offset;
08479          } else {
08480             ast_log(LOG_WARNING, "Unable to use span %d, since the D-channel cannot be located (unexpected span size of %d channels)\n", *span, si->totalchans);
08481             *span = -1;
08482             return 0;
08483          }
08484          pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
08485          pris[*span].offset = offset;
08486          pris[*span].span = *span + 1;
08487       }
08488    }
08489    return 0;
08490 }

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

Definition at line 12945 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_copy_string(), ast_get_group(), ast_jb_read_conf(), ast_log(), AST_MAX_EXTENSION, ast_strdupa, 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_DTMF_NOALERT, CID_START_POLARITY, CID_START_RING, dahdi_pvt::context, ringContextData::contextData, DAHDI_OVERLAPDIAL_BOTH, DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_NONE, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_pvt::dahditrcallerid, dahdi_pri::dialplan, drings, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echotraining, dahdi_pri::facilityenable, global_jbconf, dahdi_pvt::group, dahdi_pvt::hanguponpolarityswitch, HAVE_PRI, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pri::idledial, dahdi_pri::idleext, dahdi_pvt::immediate, dahdi_pri::inbanddisconnect, dahdi_pri::internationalprefix, dahdi_pvt::language, ast_variable::lineno, dahdi_pri::localdialplan, dahdi_pri::localprefix, LOG_ERROR, dahdi_pvt::mailbox, MAX_CHANLIST_LEN, dahdi_pri::minidle, dahdi_pri::minunused, dahdi_pvt::mohinterpret, dahdi_pvt::mohsuggest, ast_variable::name, dahdi_pri::nationalprefix, ast_variable::next, dahdi_pri::nodetype, dahdi_pri::nsf, option_verbose, dahdi_pvt::outsigmod, dahdi_pri::overlapdial, dahdi_pvt::pickupgroup, dahdi_pvt::polarityonanswerdelay, dahdi_chan_conf::pri, dahdi_pvt::priexclusive, dahdi_pvt::priindication_oob, dahdi_pri::privateprefix, dahdi_pvt::pulse, dahdi_pvt::radio, READ_SIZE, dahdi_pri::resetinterval, 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_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SFWINK, dahdi_pvt::silencethreshold, dahdi_chan_conf::smdi_port, dahdi_pvt::stripmsd, dahdi_pri::switchtype, dahdi_pvt::threewaycalling, dahdi_chan_conf::timing, dahdi_pvt::tonezone, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, dahdi_pvt::txgain, dahdi_pri::unknownprefix, 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().

12946 {
12947    struct dahdi_pvt *tmp;
12948    int y;
12949    int found_pseudo = 0;
12950         char dahdichan[MAX_CHANLIST_LEN] = {};
12951 
12952    for (; v; v = v->next) {
12953       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
12954          continue;
12955 
12956       /* Create the interface list */
12957       if (!strcasecmp(v->name, "channel")
12958 #ifdef HAVE_PRI
12959           || !strcasecmp(v->name, "crv")
12960 #endif         
12961          ) {
12962          int iscrv;
12963          if (skipchannels)
12964             continue;
12965          iscrv = !strcasecmp(v->name, "crv");
12966          if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
12967                return -1;
12968       } else if (!strcasecmp(v->name, "buffers")) {
12969          int res;
12970          char policy[21] = "";
12971 
12972          res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy);
12973          if (res != 2) {
12974             ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
12975             confp->chan.buf_no = numbufs;
12976             continue;
12977          }
12978          if (confp->chan.buf_no < 0)
12979             confp->chan.buf_no = numbufs;
12980          if (!strcasecmp(policy, "full")) {
12981             confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
12982          } else if (!strcasecmp(policy, "immediate")) {
12983             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
12984          } else {
12985             ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
12986          }
12987       } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) {
12988          ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
12989          if (v->name[0] == 'z' || v->name[0] == 'Z') {
12990             ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat);
12991          }
12992       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
12993          if (ast_true(v->value))
12994             confp->chan.usedistinctiveringdetection = 1;
12995       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
12996          if (ast_true(v->value))
12997             distinctiveringaftercid = 1;
12998       } else if (!strcasecmp(v->name, "dring1context")) {
12999          ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
13000       } else if (!strcasecmp(v->name, "dring2context")) {
13001          ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
13002       } else if (!strcasecmp(v->name, "dring3context")) {
13003          ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
13004       } else if (!strcasecmp(v->name, "dring1")) {
13005          sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
13006       } else if (!strcasecmp(v->name, "dring2")) {
13007          sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
13008       } else if (!strcasecmp(v->name, "dring3")) {
13009          sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
13010       } else if (!strcasecmp(v->name, "usecallerid")) {
13011          confp->chan.use_callerid = ast_true(v->value);
13012       } else if (!strcasecmp(v->name, "cidsignalling")) {
13013          if (!strcasecmp(v->value, "bell"))
13014             confp->chan.cid_signalling = CID_SIG_BELL;
13015          else if (!strcasecmp(v->value, "v23"))
13016             confp->chan.cid_signalling = CID_SIG_V23;
13017          else if (!strcasecmp(v->value, "dtmf"))
13018             confp->chan.cid_signalling = CID_SIG_DTMF;
13019          else if (!strcasecmp(v->value, "smdi"))
13020             confp->chan.cid_signalling = CID_SIG_SMDI;
13021          else if (!strcasecmp(v->value, "v23_jp"))
13022             confp->chan.cid_signalling = CID_SIG_V23_JP;
13023          else if (ast_true(v->value))
13024             confp->chan.cid_signalling = CID_SIG_BELL;
13025       } else if (!strcasecmp(v->name, "cidstart")) {
13026          if (!strcasecmp(v->value, "ring"))
13027             confp->chan.cid_start = CID_START_RING;
13028          else if (!strcasecmp(v->value, "polarity"))
13029             confp->chan.cid_start = CID_START_POLARITY;
13030          else if (!strcasecmp(v->value, "dtmf"))
13031             confp->chan.cid_start = CID_START_DTMF_NOALERT;
13032          else if (ast_true(v->value))
13033             confp->chan.cid_start = CID_START_RING;
13034       } else if (!strcasecmp(v->name, "threewaycalling")) {
13035          confp->chan.threewaycalling = ast_true(v->value);
13036       } else if (!strcasecmp(v->name, "cancallforward")) {
13037          confp->chan.cancallforward = ast_true(v->value);
13038       } else if (!strcasecmp(v->name, "relaxdtmf")) {
13039          if (ast_true(v->value)) 
13040             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
13041          else
13042             confp->chan.dtmfrelax = 0;
13043       } else if (!strcasecmp(v->name, "mailbox")) {
13044          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
13045       } else if (!strcasecmp(v->name, "hasvoicemail")) {
13046          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
13047             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
13048          }
13049       } else if (!strcasecmp(v->name, "adsi")) {
13050          confp->chan.adsi = ast_true(v->value);
13051       } else if (!strcasecmp(v->name, "usesmdi")) {
13052          confp->chan.use_smdi = ast_true(v->value);
13053       } else if (!strcasecmp(v->name, "smdiport")) {
13054          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
13055       } else if (!strcasecmp(v->name, "transfer")) {
13056          confp->chan.transfer = ast_true(v->value);
13057       } else if (!strcasecmp(v->name, "canpark")) {
13058          confp->chan.canpark = ast_true(v->value);
13059       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
13060          confp->chan.echocanbridged = ast_true(v->value);
13061       } else if (!strcasecmp(v->name, "busydetect")) {
13062          confp->chan.busydetect = ast_true(v->value);
13063       } else if (!strcasecmp(v->name, "busycount")) {
13064          confp->chan.busycount = atoi(v->value);
13065       } else if (!strcasecmp(v->name, "silencethreshold")) {
13066             confp->chan.silencethreshold = atoi(v->value);
13067       } else if (!strcasecmp(v->name, "busycompare")) {
13068             confp->chan.busycompare = ast_true(v->value);
13069       } else if (!strcasecmp(v->name, "busypattern")) {
13070          int count = sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
13071          if (count == 1)
13072             confp->chan.busyquietlength = 0;
13073          else if (count < 1)
13074                ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n");
13075       } else if (!strcasecmp(v->name, "busyfuzziness")) {
13076             confp->chan.busyfuzziness = atoi(v->value);
13077       } else if (!strcasecmp(v->name, "callprogress")) {
13078          if (ast_true(v->value))
13079             confp->chan.callprogress |= 1;
13080          else
13081             confp->chan.callprogress &= ~1;
13082       } else if (!strcasecmp(v->name, "faxdetect")) {
13083          if (!strcasecmp(v->value, "incoming")) {
13084             confp->chan.callprogress |= 4;
13085             confp->chan.callprogress &= ~2;
13086          } else if (!strcasecmp(v->value, "outgoing")) {
13087             confp->chan.callprogress &= ~4;
13088             confp->chan.callprogress |= 2;
13089          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
13090             confp->chan.callprogress |= 6;
13091          else
13092             confp->chan.callprogress &= ~6;
13093       } else if (!strcasecmp(v->name, "echocancel")) {
13094          if (!ast_strlen_zero(v->value)) {
13095             y = atoi(v->value);
13096          } else
13097             y = 0;
13098          if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
13099             confp->chan.echocancel = y;
13100          else {
13101             confp->chan.echocancel = ast_true(v->value);
13102             if (confp->chan.echocancel)
13103                confp->chan.echocancel=128;
13104          }
13105       } else if (!strcasecmp(v->name, "echotraining")) {
13106          if (sscanf(v->value, "%30d", &y) == 1) {
13107             if ((y < 10) || (y > 4000)) {
13108                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);              
13109             } else {
13110                confp->chan.echotraining = y;
13111             }
13112          } else if (ast_true(v->value)) {
13113             confp->chan.echotraining = 400;
13114          } else
13115             confp->chan.echotraining = 0;
13116       } else if (!strcasecmp(v->name, "hidecallerid")) {
13117          confp->chan.hidecallerid = ast_true(v->value);
13118       } else if (!strcasecmp(v->name, "hidecalleridname")) {
13119          confp->chan.hidecalleridname = ast_true(v->value);
13120       } else if (!strcasecmp(v->name, "pulsedial")) {
13121          confp->chan.pulse = ast_true(v->value);
13122       } else if (!strcasecmp(v->name, "callreturn")) {
13123          confp->chan.callreturn = ast_true(v->value);
13124       } else if (!strcasecmp(v->name, "callwaiting")) {
13125          confp->chan.callwaiting = ast_true(v->value);
13126       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
13127          confp->chan.callwaitingcallerid = ast_true(v->value);
13128       } else if (!strcasecmp(v->name, "context")) {
13129          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
13130       } else if (!strcasecmp(v->name, "language")) {
13131          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
13132       } else if (!strcasecmp(v->name, "progzone")) {
13133          ast_copy_string(progzone, v->value, sizeof(progzone));
13134       } else if (!strcasecmp(v->name, "mohinterpret") 
13135          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
13136          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
13137       } else if (!strcasecmp(v->name, "mohsuggest")) {
13138          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
13139       } else if (!strcasecmp(v->name, "stripmsd")) {
13140          confp->chan.stripmsd = atoi(v->value);
13141       } else if (!strcasecmp(v->name, "jitterbuffers")) {
13142          numbufs = atoi(v->value);
13143       } else if (!strcasecmp(v->name, "group")) {
13144          confp->chan.group = ast_get_group(v->value);
13145       } else if (!strcasecmp(v->name, "callgroup")) {
13146          confp->chan.callgroup = ast_get_group(v->value);
13147       } else if (!strcasecmp(v->name, "pickupgroup")) {
13148          confp->chan.pickupgroup = ast_get_group(v->value);
13149       } else if (!strcasecmp(v->name, "immediate")) {
13150          confp->chan.immediate = ast_true(v->value);
13151       } else if (!strcasecmp(v->name, "transfertobusy")) {
13152          confp->chan.transfertobusy = ast_true(v->value);
13153       } else if (!strcasecmp(v->name, "rxgain")) {
13154          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
13155             ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
13156          }
13157       } else if (!strcasecmp(v->name, "txgain")) {
13158          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
13159             ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
13160          }
13161       } else if (!strcasecmp(v->name, "tonezone")) {
13162          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
13163             ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
13164          }
13165       } else if (!strcasecmp(v->name, "callerid")) {
13166          if (!strcasecmp(v->value, "asreceived")) {
13167             confp->chan.cid_num[0] = '\0';
13168             confp->chan.cid_name[0] = '\0';
13169          } else {
13170             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
13171          } 
13172       } else if (!strcasecmp(v->name, "fullname")) {
13173          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
13174       } else if (!strcasecmp(v->name, "cid_number")) {
13175          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
13176       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
13177          confp->chan.dahditrcallerid = ast_true(v->value);
13178          if (strstr(v->name, "zap")) {
13179             ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat);
13180          }
13181       } else if (!strcasecmp(v->name, "restrictcid")) {
13182          confp->chan.restrictcid = ast_true(v->value);
13183       } else if (!strcasecmp(v->name, "usecallingpres")) {
13184          confp->chan.use_callingpres = ast_true(v->value);
13185       } else if (!strcasecmp(v->name, "accountcode")) {
13186          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
13187       } else if (!strcasecmp(v->name, "amaflags")) {
13188          y = ast_cdr_amaflags2int(v->value);
13189          if (y < 0) 
13190             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
13191          else
13192             confp->chan.amaflags = y;
13193       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
13194          confp->chan.polarityonanswerdelay = atoi(v->value);
13195       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
13196          confp->chan.answeronpolarityswitch = ast_true(v->value);
13197       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
13198          confp->chan.hanguponpolarityswitch = ast_true(v->value);
13199       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
13200          confp->chan.sendcalleridafter = atoi(v->value);
13201       } else if (reload != 1) {
13202           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
13203             confp->chan.outsigmod = -1;
13204             if (!strcasecmp(v->value, "em")) {
13205                confp->chan.sig = SIG_EM;
13206             } else if (!strcasecmp(v->value, "em_e1")) {
13207                confp->chan.sig = SIG_EM_E1;
13208             } else if (!strcasecmp(v->value, "em_w")) {
13209                confp->chan.sig = SIG_EMWINK;
13210                confp->chan.radio = 0;
13211             } else if (!strcasecmp(v->value, "fxs_ls")) {
13212                confp->chan.sig = SIG_FXSLS;
13213                confp->chan.radio = 0;
13214             } else if (!strcasecmp(v->value, "fxs_gs")) {
13215                confp->chan.sig = SIG_FXSGS;
13216                confp->chan.radio = 0;
13217             } else if (!strcasecmp(v->value, "fxs_ks")) {
13218                confp->chan.sig = SIG_FXSKS;
13219                confp->chan.radio = 0;
13220             } else if (!strcasecmp(v->value, "fxo_ls")) {
13221                confp->chan.sig = SIG_FXOLS;
13222                confp->chan.radio = 0;
13223             } else if (!strcasecmp(v->value, "fxo_gs")) {
13224                confp->chan.sig = SIG_FXOGS;
13225                confp->chan.radio = 0;
13226             } else if (!strcasecmp(v->value, "fxo_ks")) {
13227                confp->chan.sig = SIG_FXOKS;
13228                confp->chan.radio = 0;
13229             } else if (!strcasecmp(v->value, "fxs_rx")) {
13230                confp->chan.sig = SIG_FXSKS;
13231                confp->chan.radio = 1;
13232             } else if (!strcasecmp(v->value, "fxo_rx")) {
13233                confp->chan.sig = SIG_FXOLS;
13234                confp->chan.radio = 1;
13235             } else if (!strcasecmp(v->value, "fxs_tx")) {
13236                confp->chan.sig = SIG_FXSLS;
13237                confp->chan.radio = 1;
13238             } else if (!strcasecmp(v->value, "fxo_tx")) {
13239                confp->chan.sig = SIG_FXOGS;
13240                confp->chan.radio = 1;
13241             } else if (!strcasecmp(v->value, "em_rx")) {
13242                confp->chan.sig = SIG_EM;
13243                confp->chan.radio = 1;
13244             } else if (!strcasecmp(v->value, "em_tx")) {
13245                confp->chan.sig = SIG_EM;
13246                confp->chan.radio = 1;
13247             } else if (!strcasecmp(v->value, "em_rxtx")) {
13248                confp->chan.sig = SIG_EM;
13249                confp->chan.radio = 2;
13250             } else if (!strcasecmp(v->value, "em_txrx")) {
13251                confp->chan.sig = SIG_EM;
13252                confp->chan.radio = 2;
13253             } else if (!strcasecmp(v->value, "sf")) {
13254                confp->chan.sig = SIG_SF;
13255                confp->chan.radio = 0;
13256             } else if (!strcasecmp(v->value, "sf_w")) {
13257                confp->chan.sig = SIG_SFWINK;
13258                confp->chan.radio = 0;
13259             } else if (!strcasecmp(v->value, "sf_featd")) {
13260                confp->chan.sig = SIG_FEATD;
13261                confp->chan.radio = 0;
13262             } else if (!strcasecmp(v->value, "sf_featdmf")) {
13263                confp->chan.sig = SIG_FEATDMF;
13264                confp->chan.radio = 0;
13265             } else if (!strcasecmp(v->value, "sf_featb")) {
13266                confp->chan.sig = SIG_SF_FEATB;
13267                confp->chan.radio = 0;
13268             } else if (!strcasecmp(v->value, "sf")) {
13269                confp->chan.sig = SIG_SF;
13270                confp->chan.radio = 0;
13271             } else if (!strcasecmp(v->value, "sf_rx")) {
13272                confp->chan.sig = SIG_SF;
13273                confp->chan.radio = 1;
13274             } else if (!strcasecmp(v->value, "sf_tx")) {
13275                confp->chan.sig = SIG_SF;
13276                confp->chan.radio = 1;
13277             } else if (!strcasecmp(v->value, "sf_rxtx")) {
13278                confp->chan.sig = SIG_SF;
13279                confp->chan.radio = 2;
13280             } else if (!strcasecmp(v->value, "sf_txrx")) {
13281                confp->chan.sig = SIG_SF;
13282                confp->chan.radio = 2;
13283             } else if (!strcasecmp(v->value, "featd")) {
13284                confp->chan.sig = SIG_FEATD;
13285                confp->chan.radio = 0;
13286             } else if (!strcasecmp(v->value, "featdmf")) {
13287                confp->chan.sig = SIG_FEATDMF;
13288                confp->chan.radio = 0;
13289             } else if (!strcasecmp(v->value, "featdmf_ta")) {
13290                confp->chan.sig = SIG_FEATDMF_TA;
13291                confp->chan.radio = 0;
13292             } else if (!strcasecmp(v->value, "e911")) {
13293                confp->chan.sig = SIG_E911;
13294                confp->chan.radio = 0;
13295             } else if (!strcasecmp(v->value, "fgccama")) {
13296                confp->chan.sig = SIG_FGC_CAMA;
13297                confp->chan.radio = 0;
13298             } else if (!strcasecmp(v->value, "fgccamamf")) {
13299                confp->chan.sig = SIG_FGC_CAMAMF;
13300                confp->chan.radio = 0;
13301             } else if (!strcasecmp(v->value, "featb")) {
13302                confp->chan.sig = SIG_FEATB;
13303                confp->chan.radio = 0;
13304 #ifdef HAVE_OPENR2
13305             } else if (!strcasecmp(v->value, "mfcr2")) {
13306                confp->chan.sig = SIG_MFCR2;
13307 #endif
13308 #ifdef HAVE_PRI
13309             } else if (!strcasecmp(v->value, "pri_net")) {
13310                confp->chan.radio = 0;
13311                confp->chan.sig = SIG_PRI;
13312                confp->pri.nodetype = PRI_NETWORK;
13313             } else if (!strcasecmp(v->value, "pri_cpe")) {
13314                confp->chan.sig = SIG_PRI;
13315                confp->chan.radio = 0;
13316                confp->pri.nodetype = PRI_CPE;
13317             } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
13318                confp->chan.sig = SIG_GR303FXOKS;
13319                confp->chan.radio = 0;
13320                confp->pri.nodetype = PRI_NETWORK;
13321             } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
13322                confp->chan.sig = SIG_GR303FXSKS;
13323                confp->chan.radio = 0;
13324                confp->pri.nodetype = PRI_CPE;
13325 #endif
13326             } else {
13327                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
13328             }
13329           } else if (!strcasecmp(v->name, "outsignalling")) {
13330             if (!strcasecmp(v->value, "em")) {
13331                confp->chan.outsigmod = SIG_EM;
13332             } else if (!strcasecmp(v->value, "em_e1")) {
13333                confp->chan.outsigmod = SIG_EM_E1;
13334             } else if (!strcasecmp(v->value, "em_w")) {
13335                confp->chan.outsigmod = SIG_EMWINK;
13336             } else if (!strcasecmp(v->value, "sf")) {
13337                confp->chan.outsigmod = SIG_SF;
13338             } else if (!strcasecmp(v->value, "sf_w")) {
13339                confp->chan.outsigmod = SIG_SFWINK;
13340             } else if (!strcasecmp(v->value, "sf_featd")) {
13341                confp->chan.outsigmod = SIG_FEATD;
13342             } else if (!strcasecmp(v->value, "sf_featdmf")) {
13343                confp->chan.outsigmod = SIG_FEATDMF;
13344             } else if (!strcasecmp(v->value, "sf_featb")) {
13345                confp->chan.outsigmod = SIG_SF_FEATB;
13346             } else if (!strcasecmp(v->value, "sf")) {
13347                confp->chan.outsigmod = SIG_SF;
13348             } else if (!strcasecmp(v->value, "featd")) {
13349                confp->chan.outsigmod = SIG_FEATD;
13350             } else if (!strcasecmp(v->value, "featdmf")) {
13351                confp->chan.outsigmod = SIG_FEATDMF;
13352             } else if (!strcasecmp(v->value, "featdmf_ta")) {
13353                confp->chan.outsigmod = SIG_FEATDMF_TA;
13354             } else if (!strcasecmp(v->value, "e911")) {
13355                confp->chan.outsigmod = SIG_E911;
13356             } else if (!strcasecmp(v->value, "fgccama")) {
13357                confp->chan.outsigmod = SIG_FGC_CAMA;
13358             } else if (!strcasecmp(v->value, "fgccamamf")) {
13359                confp->chan.outsigmod = SIG_FGC_CAMAMF;
13360             } else if (!strcasecmp(v->value, "featb")) {
13361                confp->chan.outsigmod = SIG_FEATB;
13362             } else {
13363                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
13364             }
13365 #ifdef HAVE_PRI
13366          } else if (!strcasecmp(v->name, "pridialplan")) {
13367             if (!strcasecmp(v->value, "national")) {
13368                confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
13369             } else if (!strcasecmp(v->value, "unknown")) {
13370                confp->pri.dialplan = PRI_UNKNOWN + 1;
13371             } else if (!strcasecmp(v->value, "private")) {
13372                confp->pri.dialplan = PRI_PRIVATE + 1;
13373             } else if (!strcasecmp(v->value, "international")) {
13374                confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
13375             } else if (!strcasecmp(v->value, "local")) {
13376                confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
13377             } else if (!strcasecmp(v->value, "dynamic")) {
13378                confp->pri.dialplan = -1;
13379             } else {
13380                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
13381             }
13382          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
13383             if (!strcasecmp(v->value, "national")) {
13384                confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
13385             } else if (!strcasecmp(v->value, "unknown")) {
13386                confp->pri.localdialplan = PRI_UNKNOWN + 1;
13387             } else if (!strcasecmp(v->value, "private")) {
13388                confp->pri.localdialplan = PRI_PRIVATE + 1;
13389             } else if (!strcasecmp(v->value, "international")) {
13390                confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
13391             } else if (!strcasecmp(v->value, "local")) {
13392                confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
13393             } else if (!strcasecmp(v->value, "dynamic")) {
13394                confp->pri.localdialplan = -1;
13395             } else {
13396                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
13397             }
13398          } else if (!strcasecmp(v->name, "switchtype")) {
13399             if (!strcasecmp(v->value, "national")) 
13400                confp->pri.switchtype = PRI_SWITCH_NI2;
13401             else if (!strcasecmp(v->value, "ni1"))
13402                confp->pri.switchtype = PRI_SWITCH_NI1;
13403             else if (!strcasecmp(v->value, "dms100"))
13404                confp->pri.switchtype = PRI_SWITCH_DMS100;
13405             else if (!strcasecmp(v->value, "4ess"))
13406                confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
13407             else if (!strcasecmp(v->value, "5ess"))
13408                confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
13409             else if (!strcasecmp(v->value, "euroisdn"))
13410                confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
13411             else if (!strcasecmp(v->value, "qsig"))
13412                confp->pri.switchtype = PRI_SWITCH_QSIG;
13413             else {
13414                ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
13415                return -1;
13416             }
13417          } else if (!strcasecmp(v->name, "nsf")) {
13418             if (!strcasecmp(v->value, "sdn"))
13419                confp->pri.nsf = PRI_NSF_SDN;
13420             else if (!strcasecmp(v->value, "megacom"))
13421                confp->pri.nsf = PRI_NSF_MEGACOM;
13422             else if (!strcasecmp(v->value, "tollfreemegacom"))
13423                confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;           
13424             else if (!strcasecmp(v->value, "accunet"))
13425                confp->pri.nsf = PRI_NSF_ACCUNET;
13426             else if (!strcasecmp(v->value, "none"))
13427                confp->pri.nsf = PRI_NSF_NONE;
13428             else {
13429                ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
13430                confp->pri.nsf = PRI_NSF_NONE;
13431             }
13432          } else if (!strcasecmp(v->name, "priindication")) {
13433             if (!strcasecmp(v->value, "outofband"))
13434                confp->chan.priindication_oob = 1;
13435             else if (!strcasecmp(v->value, "inband"))
13436                confp->chan.priindication_oob = 0;
13437             else
13438                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
13439                   v->value, v->lineno);
13440          } else if (!strcasecmp(v->name, "priexclusive")) {
13441             confp->chan.priexclusive = ast_true(v->value);
13442          } else if (!strcasecmp(v->name, "internationalprefix")) {
13443             ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
13444          } else if (!strcasecmp(v->name, "nationalprefix")) {
13445             ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
13446          } else if (!strcasecmp(v->name, "localprefix")) {
13447             ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
13448          } else if (!strcasecmp(v->name, "privateprefix")) {
13449             ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
13450          } else if (!strcasecmp(v->name, "unknownprefix")) {
13451             ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
13452          } else if (!strcasecmp(v->name, "resetinterval")) {
13453             if (!strcasecmp(v->value, "never"))
13454                confp->pri.resetinterval = -1;
13455             else if (atoi(v->value) >= 60)
13456                confp->pri.resetinterval = atoi(v->value);
13457             else
13458                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
13459                   v->value, v->lineno);
13460          } else if (!strcasecmp(v->name, "minunused")) {
13461             confp->pri.minunused = atoi(v->value);
13462          } else if (!strcasecmp(v->name, "minidle")) {
13463             confp->pri.minidle = atoi(v->value); 
13464          } else if (!strcasecmp(v->name, "idleext")) {
13465             ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
13466          } else if (!strcasecmp(v->name, "idledial")) {
13467             ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
13468          } else if (!strcasecmp(v->name, "overlapdial")) {
13469             if (ast_true(v->value)) {
13470                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
13471             } else if (!strcasecmp(v->value, "incoming")) {
13472                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
13473             } else if (!strcasecmp(v->value, "outgoing")) {
13474                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
13475             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
13476                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
13477             } else {
13478                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
13479             }
13480 #ifdef HAVE_PRI_INBANDDISCONNECT
13481          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
13482             confp->pri.inbanddisconnect = ast_true(v->value);
13483 #endif
13484          } else if (!strcasecmp(v->name, "pritimer")) {
13485 #ifdef PRI_GETSET_TIMERS
13486             char tmp[20];
13487             char *timerc;
13488             char *c;
13489             int timer;
13490             int timeridx;
13491 
13492             ast_copy_string(tmp, v->value, sizeof(tmp));
13493             c = tmp;
13494             timerc = strsep(&c, ",");
13495             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
13496                timeridx = pri_timer2idx(timerc);
13497                timer = atoi(c);
13498                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
13499                   ast_log(LOG_WARNING,
13500                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
13501                      v->lineno);
13502                } else if (!timer) {
13503                   ast_log(LOG_WARNING,
13504                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
13505                      c, timerc, v->lineno);
13506                } else {
13507                   pritimers[timeridx] = timer;
13508                }
13509             } else {
13510                ast_log(LOG_WARNING,
13511                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
13512                   v->value, v->lineno);
13513             }
13514 #endif /* PRI_GETSET_TIMERS */
13515          } else if (!strcasecmp(v->name, "facilityenable")) {
13516             confp->pri.facilityenable = ast_true(v->value);
13517 #endif /* HAVE_PRI */
13518 #ifdef HAVE_OPENR2
13519          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
13520             ast_copy_string(mfcr2_cur_r2proto_file, v->value, sizeof(mfcr2_cur_r2proto_file));
13521             ast_log(LOG_WARNING, "MFC/R2 Protocol file '%s' will be used, you only should use this if you *REALLY  KNOW WHAT YOU ARE DOING*.\n", mfcr2_cur_r2proto_file);
13522          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
13523             ast_copy_string(mfcr2_cur_logdir, v->value, sizeof(mfcr2_cur_logdir));
13524          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
13525             mfcr2_cur_variant = openr2_proto_get_variant(v->value);
13526             if (OR2_VAR_UNKNOWN == mfcr2_cur_variant) {
13527                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d.\n", v->value, v->lineno);
13528             }
13529          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
13530             mfcr2_cur_mfback_timeout = atoi(v->value);
13531             if (!mfcr2_cur_mfback_timeout) {
13532                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
13533                mfcr2_cur_mfback_timeout = -1;
13534             } else if (mfcr2_cur_mfback_timeout > 0 && mfcr2_cur_mfback_timeout < 500) {
13535                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
13536             }
13537          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
13538             mfcr2_cur_metering_pulse_timeout = atoi(v->value);
13539             if (mfcr2_cur_metering_pulse_timeout > 500) {
13540                ast_log(LOG_WARNING, "mfcr2_metering_pulse_timeout greater than 500ms is not recommended, you have been warned!\n");
13541             }
13542 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
13543          } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) {
13544             mfcr2_cur_dtmf_detection = ast_true(v->value) ? 1 : 0;
13545          } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) {
13546             mfcr2_cur_dtmf_dialing = ast_true(v->value) ? 1 : 0;
13547          } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) {
13548             mfcr2_cur_dtmf_time_on = atoi(v->value);
13549          } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) {
13550             mfcr2_cur_dtmf_time_off = atoi(v->value);
13551 #endif
13552          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
13553             mfcr2_cur_get_ani_first = ast_true(v->value) ? 1 : 0;
13554          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
13555             mfcr2_cur_skip_category = ast_true(v->value) ? 1 : 0;
13556          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
13557             mfcr2_cur_double_answer = ast_true(v->value) ? 1 : 0;
13558          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
13559             mfcr2_cur_accept_on_offer = ast_true(v->value) ? 1 : 0;
13560          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
13561             mfcr2_cur_charge_calls = ast_true(v->value) ? 1 : 0;
13562          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
13563             mfcr2_cur_allow_collect_calls = ast_true(v->value) ? 1 : 0;
13564          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
13565             mfcr2_cur_forced_release= ast_true(v->value) ? 1 : 0;
13566          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
13567             mfcr2_cur_immediate_accept = ast_true(v->value) ? 1 : 0;
13568          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
13569             mfcr2_cur_call_files = ast_true(v->value) ? 1 : 0;
13570          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
13571             mfcr2_cur_max_ani = atoi(v->value);
13572             if (mfcr2_cur_max_ani >= AST_MAX_EXTENSION) {
13573                mfcr2_cur_max_ani = AST_MAX_EXTENSION - 1;
13574             }
13575          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
13576             mfcr2_cur_max_dnis = atoi(v->value);
13577             if (mfcr2_cur_max_dnis >= AST_MAX_EXTENSION) {
13578                mfcr2_cur_max_dnis = AST_MAX_EXTENSION - 1;
13579             }
13580          } else if (!strcasecmp(v->name, "mfcr2_category")) {
13581             mfcr2_cur_category = openr2_proto_get_category(v->value);
13582             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == mfcr2_cur_category) {
13583                mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
13584                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n", 
13585                      v->value, v->lineno);
13586             }
13587          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
13588             openr2_log_level_t tmplevel;
13589             char *toklevel = NULL;
13590             char *saveptr = NULL;
13591             char *logval = ast_strdupa(v->value);
13592             toklevel = strtok_r(logval, ",", &saveptr);
13593             if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
13594                ast_log(LOG_WARNING, "Invalid MFC/R2 logging level '%s' at line %d.\n", v->value, v->lineno);
13595             } else if (OR2_LOG_NOTHING == tmplevel) {
13596                mfcr2_cur_loglevel = tmplevel;
13597             } else {
13598                mfcr2_cur_loglevel |= tmplevel;
13599                while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
13600                   if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
13601                      ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", toklevel, v->lineno);
13602                      continue;
13603                   }
13604                   mfcr2_cur_loglevel |= tmplevel;
13605                }
13606             }
13607 #endif /* HAVE_OPENR2 */
13608 
13609          } else if (!strcasecmp(v->name, "cadence")) {
13610             /* setup to scan our argument */
13611             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
13612             int i;
13613             struct dahdi_ring_cadence new_cadence;
13614             int cid_location = -1;
13615             int firstcadencepos = 0;
13616             char original_args[80];
13617             int cadence_is_ok = 1;
13618 
13619             ast_copy_string(original_args, v->value, sizeof(original_args));
13620             /* 16 cadences allowed (8 pairs) */
13621             element_count = sscanf(v->value, "%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d", &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]);
13622    
13623             /* Cadence must be even (on/off) */
13624             if (element_count % 2 == 1) {
13625                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
13626                cadence_is_ok = 0;
13627             }
13628    
13629             /* Ring cadences cannot be negative */
13630             for (i = 0; i < element_count; i++) {
13631                if (c[i] == 0) {
13632                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
13633                   cadence_is_ok = 0;
13634                   break;
13635                } else if (c[i] < 0) {
13636                   if (i % 2 == 1) {
13637                      /* Silence duration, negative possibly okay */
13638                      if (cid_location == -1) {
13639                         cid_location = i;
13640                         c[i] *= -1;
13641                      } else {
13642                         ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
13643                         cadence_is_ok = 0;
13644                         break;
13645                      }
13646                   } else {
13647                      if (firstcadencepos == 0) {
13648                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
13649                                  /* duration will be passed negative to the DAHDI driver */
13650                      } else {
13651                          ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
13652                         cadence_is_ok = 0;
13653                         break;
13654                      }
13655                   }
13656                }
13657             }
13658    
13659             /* Substitute our scanned cadence */
13660             for (i = 0; i < 16; i++) {
13661                new_cadence.ringcadence[i] = c[i];
13662             }
13663    
13664             if (cadence_is_ok) {
13665                /* ---we scanned it without getting annoyed; now some sanity checks--- */
13666                if (element_count < 2) {
13667                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
13668                } else {
13669                   if (cid_location == -1) {
13670                      /* user didn't say; default to first pause */
13671                      cid_location = 1;
13672                   } else {
13673                      /* convert element_index to cidrings value */
13674                      cid_location = (cid_location + 1) / 2;
13675                   }
13676                   /* ---we like their cadence; try to install it--- */
13677                   if (!user_has_defined_cadences++)
13678                      /* this is the first user-defined cadence; clear the default user cadences */
13679                      num_cadence = 0;
13680                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
13681                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
13682                   else {
13683                      cadences[num_cadence] = new_cadence;
13684                      cidrings[num_cadence++] = cid_location;
13685                      if (option_verbose > 2)
13686                         ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
13687                   }
13688                }
13689             }
13690          } else if (!strcasecmp(v->name, "ringtimeout")) {
13691             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
13692          } else if (!strcasecmp(v->name, "prewink")) {
13693             confp->timing.prewinktime = atoi(v->value);
13694          } else if (!strcasecmp(v->name, "preflash")) {
13695             confp->timing.preflashtime = atoi(v->value);
13696          } else if (!strcasecmp(v->name, "wink")) {
13697             confp->timing.winktime = atoi(v->value);
13698          } else if (!strcasecmp(v->name, "flash")) {
13699             confp->timing.flashtime = atoi(v->value);
13700          } else if (!strcasecmp(v->name, "start")) {
13701             confp->timing.starttime = atoi(v->value);
13702          } else if (!strcasecmp(v->name, "rxwink")) {
13703             confp->timing.rxwinktime = atoi(v->value);
13704          } else if (!strcasecmp(v->name, "rxflash")) {
13705             confp->timing.rxflashtime = atoi(v->value);
13706          } else if (!strcasecmp(v->name, "debounce")) {
13707             confp->timing.debouncetime = atoi(v->value);
13708          } else if (!strcasecmp(v->name, "toneduration")) {
13709             int toneduration;
13710             int ctlfd;
13711             int res;
13712             struct dahdi_dialparams dps;
13713 
13714             ctlfd = open(DAHDI_FILE_CTL, O_RDWR);
13715 
13716             if (ctlfd == -1) {
13717                ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n");
13718                return -1;
13719             }
13720 
13721             toneduration = atoi(v->value);
13722             if (toneduration > -1) {
13723                memset(&dps, 0, sizeof(dps));
13724 
13725                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
13726                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
13727                if (res < 0) {
13728                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
13729                   return -1;
13730                }
13731             }
13732             close(ctlfd);
13733          } else if (!strcasecmp(v->name, "defaultcic")) {
13734             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
13735          } else if (!strcasecmp(v->name, "defaultozz")) {
13736             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
13737          } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
13738             dtmfcid_level = atoi(v->value);
13739          } 
13740       } else if (!skipchannels)
13741          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload)\n", v->name);
13742    }
13743    if (dahdichan[0]) { 
13744       /* The user has set 'dahdichan' */
13745       /*< \todo pass proper line number instead of 0 */
13746       if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
13747          return -1;
13748       }
13749    }
13750    /*< \todo why check for the pseudo in the per-channel section.
13751     * Any actual use for manual setup of the pseudo channel? */
13752    if (!found_pseudo && reload != 1) {
13753       /* use the default configuration for a channel, so
13754          that any settings from real configured channels
13755          don't "leak" into the pseudo channel config
13756       */
13757       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
13758 
13759       tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
13760 
13761       if (tmp) {
13762          if (option_verbose > 2)
13763             ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
13764       } else {
13765          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
13766       }
13767    }
13768    return 0;
13769 }

static char* redirectingreason2str ( int  redirectingreason  )  [static]

Definition at line 9986 of file chan_dahdi.c.

Referenced by __oh323_new().

09987 {
09988    switch (redirectingreason) {
09989    case 0:
09990       return "UNKNOWN";
09991    case 1:
09992       return "BUSY";
09993    case 2:
09994       return "NO_REPLY";
09995    case 0xF:
09996       return "UNCONDITIONAL";
09997    default:
09998       return "NOREDIRECT";
09999    }
10000 }

static int reload ( void   )  [static]

Definition at line 14103 of file chan_dahdi.c.

References ast_log(), and setup_dahdi().

14104 {
14105    int res = 0;
14106 
14107    res = setup_dahdi(1);
14108    if (res) {
14109       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
14110       return -1;
14111    }
14112    return 0;
14113 }

static int reset_conf ( struct dahdi_pvt p  )  [static]

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

02281 {
02282    p->confno = -1;
02283    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
02284    if (p->subs[SUB_REAL].dfd > -1) {
02285       struct dahdi_confinfo zi;
02286 
02287       memset(&zi, 0, sizeof(zi));
02288       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
02289          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
02290    }
02291    return 0;
02292 }

static int restart_monitor ( void   )  [static]

Definition at line 8403 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(), LOG_ERROR, and monlock.

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

08404 {
08405    pthread_attr_t attr;
08406    pthread_attr_init(&attr);
08407    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08408    /* If we're supposed to be stopped -- stay stopped */
08409    if (monitor_thread == AST_PTHREADT_STOP)
08410       return 0;
08411    ast_mutex_lock(&monlock);
08412    if (monitor_thread == pthread_self()) {
08413       ast_mutex_unlock(&monlock);
08414       ast_log(LOG_WARNING, "Cannot kill myself\n");
08415       return -1;
08416    }
08417    if (monitor_thread != AST_PTHREADT_NULL) {
08418       /* Wake up the thread */
08419       pthread_kill(monitor_thread, SIGURG);
08420    } else {
08421       /* Start a new monitor */
08422       if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
08423          ast_mutex_unlock(&monlock);
08424          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08425          pthread_attr_destroy(&attr);
08426          return -1;
08427       }
08428    }
08429    ast_mutex_unlock(&monlock);
08430    pthread_attr_destroy(&attr);
08431    return 0;
08432 }

static int restore_conference ( struct dahdi_pvt p  )  [static]

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

02614 {
02615    int res;
02616    if (p->saveconf.confmode) {
02617       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02618       p->saveconf.confmode = 0;
02619       if (res) {
02620          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02621          return -1;
02622       }
02623    }
02624    if (option_debug)
02625       ast_log(LOG_DEBUG, "Restored conferencing\n");
02626    return 0;
02627 }

static int restore_gains ( struct dahdi_pvt p  )  [static]

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

02541 {
02542    int res;
02543 
02544    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02545    if (res) {
02546       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02547       return -1;
02548    }
02549 
02550    return 0;
02551 }

static int save_conference ( struct dahdi_pvt p  )  [static]

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

02587 {
02588    struct dahdi_confinfo c;
02589    int res;
02590    if (p->saveconf.confmode) {
02591       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02592       return -1;
02593    }
02594    p->saveconf.chan = 0;
02595    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02596    if (res) {
02597       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02598       p->saveconf.confmode = 0;
02599       return -1;
02600    }
02601    memset(&c, 0, sizeof(c));
02602    c.confmode = DAHDI_CONF_NORMAL;
02603    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02604    if (res) {
02605       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02606       return -1;
02607    }
02608    if (option_debug)
02609       ast_log(LOG_DEBUG, "Disabled conferencing\n");
02610    return 0;
02611 }

static int send_callerid ( struct dahdi_pvt p  )  [static]

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

02654 {
02655    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
02656    int res;
02657    /* Take out of linear mode if necessary */
02658    if (p->subs[SUB_REAL].linear) {
02659       p->subs[SUB_REAL].linear = 0;
02660       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02661    }
02662    while (p->cidpos < p->cidlen) {
02663       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
02664       if (res < 0) {
02665          if (errno == EAGAIN)
02666             return 0;
02667          else {
02668             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
02669             return -1;
02670          }
02671       }
02672       if (!res)
02673          return 0;
02674       p->cidpos += res;
02675    }
02676    free(p->cidspill);
02677    p->cidspill = NULL;
02678    if (p->callwaitcas) {
02679       /* Wait for CID/CW to expire */
02680       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
02681    } else
02682       restore_conference(p);
02683    return 0;
02684 }

static int send_cwcidspill ( struct dahdi_pvt p  )  [static]

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

02632 {
02633    p->callwaitcas = 0;
02634    p->cidcwexpire = 0;
02635    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02636       return -1;
02637    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02638    /* Make sure we account for the end */
02639    p->cidlen += READ_SIZE * 4;
02640    p->cidpos = 0;
02641    send_callerid(p);
02642    if (option_verbose > 2)
02643       ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02644    return 0;
02645 }

static int send_keypad_facility_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 3300 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), dahdi_pvt::call, dahdi_pvt::lock, LOG_DEBUG, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), and ast_channel::tech_pvt.

Referenced by dahdi_send_keypad_facility_exec(), and zap_send_keypad_facility_exec().

03301 {
03302    /* Data will be our digit string */
03303    struct dahdi_pvt *p;
03304    char *digits = (char *) data;
03305 
03306    if (ast_strlen_zero(digits)) {
03307       ast_log(LOG_DEBUG, "No digit string sent to application!\n");
03308       return -1;
03309    }
03310 
03311    p = (struct dahdi_pvt *)chan->tech_pvt;
03312 
03313    if (!p) {
03314       ast_log(LOG_DEBUG, "Unable to find technology private\n");
03315       return -1;
03316    }
03317 
03318    ast_mutex_lock(&p->lock);
03319 
03320    if (!p->pri || !p->call) {
03321       ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
03322       ast_mutex_unlock(&p->lock);
03323       return -1;
03324    }
03325 
03326    if (!pri_grab(p, p->pri)) {
03327       pri_keypad_facility(p->pri->pri, p->call, digits);
03328       pri_rel(p->pri);
03329    } else {
03330       ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
03331       ast_mutex_unlock(&p->lock);
03332       return -1;
03333    }
03334 
03335    ast_mutex_unlock(&p->lock);
03336 
03337    return 0;
03338 }

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

Definition at line 2521 of file chan_dahdi.c.

References set_actual_rxgain(), and set_actual_txgain().

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

02522 {
02523    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02524 }

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

Definition at line 2503 of file chan_dahdi.c.

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

Referenced by dahdi_setoption(), and set_actual_gain().

02504 {
02505    struct dahdi_gains g;
02506    int res;
02507 
02508    memset(&g, 0, sizeof(g));
02509    g.chan = chan;
02510    res = ioctl(fd, DAHDI_GETGAINS, &g);
02511    if (res) {
02512       ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
02513       return res;
02514    }
02515 
02516    fill_rxgain(&g, gain, law);
02517 
02518    return ioctl(fd, DAHDI_SETGAINS, &g);
02519 }

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

Definition at line 2484 of file chan_dahdi.c.

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

Referenced by dahdi_setoption(), and set_actual_gain().

02485 {
02486    struct dahdi_gains g;
02487    int res;
02488 
02489    memset(&g, 0, sizeof(g));
02490    g.chan = chan;
02491    res = ioctl(fd, DAHDI_GETGAINS, &g);
02492    if (res) {
02493       if (option_debug)
02494          ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
02495       return res;
02496    }
02497 
02498    fill_txgain(&g, gain, law);
02499 
02500    return ioctl(fd, DAHDI_SETGAINS, &g);
02501 }

static int setup_dahdi ( int  reload  )  [static]

Definition at line 13771 of file chan_dahdi.c.

References ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, 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, iflock, ast_variable::lineno, LOG_ERROR, master, mfcr2_monitor(), ast_variable::name, ast_variable::next, NUM_SPANS, option_verbose, pri_create_spanmap(), pri_create_trunkgroup(), pris, process_dahdi(), r2links, restart_monitor(), start_pri(), ast_variable::value, and VERBOSE_PREFIX_2.

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

13772 {
13773    struct ast_config *cfg;
13774    struct ast_variable *v;
13775    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
13776    int res;
13777 
13778 #ifdef HAVE_PRI
13779    char *c;
13780    int spanno;
13781    int i, x;
13782    int logicalspan;
13783    int trunkgroup;
13784    int dchannels[NUM_DCHANS];
13785 #endif
13786 
13787 #ifdef HAVE_ZAPTEL
13788    int load_from_zapata_conf = 1;
13789 #else
13790    int load_from_zapata_conf = (*dahdi_chan_mode == CHAN_ZAP_MODE);
13791 #endif
13792 
13793    if (load_from_zapata_conf) {
13794       if (!(cfg = ast_config_load("zapata.conf"))) {
13795          ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
13796          return 0;
13797       }
13798    } else {
13799       if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
13800          ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
13801          return 0;
13802       }
13803    }
13804 
13805    /* It's a little silly to lock it, but we mind as well just to be sure */
13806    ast_mutex_lock(&iflock);
13807 #ifdef HAVE_PRI
13808    if (reload != 1) {
13809       /* Process trunkgroups first */
13810       v = ast_variable_browse(cfg, "trunkgroups");
13811       while (v) {
13812          if (!strcasecmp(v->name, "trunkgroup")) {
13813             trunkgroup = atoi(v->value);
13814             if (trunkgroup > 0) {
13815                if ((c = strchr(v->value, ','))) {
13816                   i = 0;
13817                   memset(dchannels, 0, sizeof(dchannels));
13818                   while (c && (i < NUM_DCHANS)) {
13819                      dchannels[i] = atoi(c + 1);
13820                      if (dchannels[i] < 0) {
13821                         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);
13822                      } else
13823                         i++;
13824                      c = strchr(c + 1, ',');
13825                   }
13826                   if (i) {
13827                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
13828                         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);
13829                      } else if (option_verbose > 1)
13830                         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");
13831                   } else
13832                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
13833                } else
13834                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
13835             } else
13836                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
13837          } else if (!strcasecmp(v->name, "spanmap")) {
13838             spanno = atoi(v->value);
13839             if (spanno > 0) {
13840                if ((c = strchr(v->value, ','))) {
13841                   trunkgroup = atoi(c + 1);
13842                   if (trunkgroup > 0) {
13843                      if ((c = strchr(c + 1, ','))) 
13844                         logicalspan = atoi(c + 1);
13845                      else
13846                         logicalspan = 0;
13847                      if (logicalspan >= 0) {
13848                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
13849                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
13850                         } else if (option_verbose > 1) 
13851                            ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
13852                      } else
13853                         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);
13854                   } else
13855                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
13856                } else
13857                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
13858             } else
13859                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
13860          } else {
13861             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
13862          }
13863          v = v->next;
13864       }
13865    }
13866 #endif
13867    
13868    /* Copy the default jb config over global_jbconf */
13869    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
13870 
13871    v = ast_variable_browse(cfg, "channels");
13872    res = process_dahdi(&conf, "", v, reload, 0);
13873    ast_mutex_unlock(&iflock);
13874    ast_config_destroy(cfg);
13875    if (res)
13876       return res;
13877    cfg = ast_config_load("users.conf");
13878    if (cfg) {
13879       char *cat;
13880       process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
13881       for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
13882          if (!strcasecmp(cat, "general"))
13883             continue;
13884          if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) {
13885             struct dahdi_chan_conf sect_conf;
13886             memcpy(&sect_conf, &conf, sizeof(sect_conf));
13887 
13888             process_dahdi(&sect_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
13889          }
13890       }
13891       ast_config_destroy(cfg);
13892    }
13893 #ifdef HAVE_PRI
13894    if (reload != 1) {
13895       for (x = 0; x < NUM_SPANS; x++) {
13896          if (pris[x].pvts[0]) {
13897             if (start_pri(pris + x)) {
13898                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
13899                return -1;
13900             } else if (option_verbose > 1)
13901                ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
13902          }
13903       }
13904    }
13905 #endif
13906 #ifdef HAVE_OPENR2
13907    if (reload != 1) {
13908       int x;
13909       for (x = 0; x < NUM_SPANS; x++) {
13910          if (r2links[x].protocol_context) {
13911             if (ast_pthread_create(&r2links[x].master, NULL, mfcr2_monitor, &r2links[x])) {
13912                ast_log(LOG_ERROR, "Unable to start R2 context on span %d\n", x + 1);
13913                return -1;
13914             } else {
13915                ast_verbose(VERBOSE_PREFIX_2 "Starting R2 context on span %d\n", x + 1);
13916             }
13917          }
13918       }
13919    }
13920 #endif
13921    /* And start the monitor for the first time */
13922    restart_monitor();
13923    return 0;
13924 }

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

Definition at line 6757 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_copy_string(), 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, 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_DTMF_NOALERT, 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, ast_smdi_md_message::fwd_st, ast_channel::hangupcause, dahdi_pvt::hardwaredtmf, dahdi_pvt::hidecallerid, dahdi_pvt::immediate, ISTRUNK, ast_channel::language, dahdi_pvt::lastcid_num, len(), dahdi_subchannel::linear, LOG_DEBUG, LOG_NOTICE, manager_event(), my_getsigstr(), ast_channel::name, name, NEED_MFDETECT, option_debug, option_verbose, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::pri, 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, ss_thread_lock, 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().

06758 {
06759    struct ast_channel *chan = data;
06760    struct dahdi_pvt *p = chan->tech_pvt;
06761    char exten[AST_MAX_EXTENSION] = "";
06762    char exten2[AST_MAX_EXTENSION] = "";
06763    unsigned char buf[256];
06764    char dtmfcid[300];
06765    char dtmfbuf[300];
06766    struct callerid_state *cs = NULL;
06767    char *name = NULL, *number = NULL;
06768    int distMatches;
06769    int curRingData[3];
06770    int receivedRingT;
06771    int counter1;
06772    int counter;
06773    int samples = 0;
06774    struct ast_smdi_md_message *smdi_msg = NULL;
06775    int flags = 0;
06776    int i;
06777    int timeout;
06778    int getforward = 0;
06779    char *s1, *s2;
06780    int len = 0;
06781    int res;
06782    int index;
06783 
06784    ast_mutex_lock(&ss_thread_lock);
06785    ss_thread_count++;
06786    ast_mutex_unlock(&ss_thread_lock);
06787    /* in the bizarre case where the channel has become a zombie before we
06788       even get started here, abort safely
06789    */
06790    if (!p) {
06791       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
06792       ast_hangup(chan);
06793       goto quit;
06794    }
06795    if (option_verbose > 2) 
06796       ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
06797    index = dahdi_get_index(chan, p, 1);
06798    if (index < 0) {
06799       ast_log(LOG_WARNING, "Huh?\n");
06800       ast_hangup(chan);
06801       goto quit;
06802    }
06803    if (p->dsp)
06804       ast_dsp_digitreset(p->dsp);
06805    switch (p->sig) {
06806 #ifdef HAVE_PRI
06807    case SIG_PRI:
06808       /* Now loop looking for an extension */
06809       ast_copy_string(exten, p->exten, sizeof(exten));
06810       len = strlen(exten);
06811       res = 0;
06812       while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06813          if (len && !ast_ignore_pattern(chan->context, exten))
06814             tone_zone_play_tone(p->subs[index].dfd, -1);
06815          else
06816             tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
06817          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
06818             timeout = matchdigittimeout;
06819          else
06820             timeout = gendigittimeout;
06821          res = ast_waitfordigit(chan, timeout);
06822          if (res < 0) {
06823             ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
06824             ast_hangup(chan);
06825             goto quit;
06826          } else if (res) {
06827             exten[len++] = res;
06828             exten[len] = '\0';
06829          } else
06830             break;
06831       }
06832       /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
06833       if (ast_strlen_zero(exten)) {
06834          if (option_verbose > 2)
06835             ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
06836          exten[0] = 's';
06837          exten[1] = '\0';
06838       }
06839       tone_zone_play_tone(p->subs[index].dfd, -1);
06840       if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
06841          /* Start the real PBX */
06842          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06843          if (p->dsp) ast_dsp_digitreset(p->dsp);
06844          dahdi_enable_ec(p);
06845          ast_setstate(chan, AST_STATE_RING);
06846          res = ast_pbx_run(chan);
06847          if (res) {
06848             ast_log(LOG_WARNING, "PBX exited non-zero!\n");
06849          }
06850       } else {
06851          ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
06852          chan->hangupcause = AST_CAUSE_UNALLOCATED;
06853          ast_hangup(chan);
06854          p->exten[0] = '\0';
06855          /* Since we send release complete here, we won't get one */
06856          p->call = NULL;
06857       }
06858       goto quit;
06859       break;
06860 #endif
06861    case SIG_FEATD:
06862    case SIG_FEATDMF:
06863    case SIG_FEATDMF_TA:
06864    case SIG_E911:
06865    case SIG_FGC_CAMAMF:
06866    case SIG_FEATB:
06867    case SIG_EMWINK:
06868    case SIG_SF_FEATD:
06869    case SIG_SF_FEATDMF:
06870    case SIG_SF_FEATB:
06871    case SIG_SFWINK:
06872       if (dahdi_wink(p, index))  
06873          goto quit;
06874       /* Fall through */
06875    case SIG_EM:
06876    case SIG_EM_E1:
06877    case SIG_SF:
06878    case SIG_FGC_CAMA:
06879       res = tone_zone_play_tone(p->subs[index].dfd, -1);
06880       if (p->dsp)
06881          ast_dsp_digitreset(p->dsp);
06882       /* set digit mode appropriately */
06883       if (p->dsp) {
06884          if (NEED_MFDETECT(p))
06885             ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 
06886          else 
06887             ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
06888       }
06889       memset(dtmfbuf, 0, sizeof(dtmfbuf));
06890       /* Wait for the first digit only if immediate=no */
06891       if (!p->immediate)
06892          /* Wait for the first digit (up to 5 seconds). */
06893          res = ast_waitfordigit(chan, 5000);
06894       else
06895          res = 0;
06896       if (res > 0) {
06897          /* save first char */
06898          dtmfbuf[0] = res;
06899          switch (p->sig) {
06900          case SIG_FEATD:
06901          case SIG_SF_FEATD:
06902             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06903             if (res > 0)
06904                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06905             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06906             break;
06907          case SIG_FEATDMF_TA:
06908             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06909             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06910             if (dahdi_wink(p, index)) goto quit;
06911             dtmfbuf[0] = 0;
06912             /* Wait for the first digit (up to 5 seconds). */
06913             res = ast_waitfordigit(chan, 5000);
06914             if (res <= 0) break;
06915             dtmfbuf[0] = res;
06916             /* fall through intentionally */
06917          case SIG_FEATDMF:
06918          case SIG_E911:
06919          case SIG_FGC_CAMAMF:
06920          case SIG_SF_FEATDMF:
06921             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06922             /* if international caca, do it again to get real ANO */
06923             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
06924             {
06925                if (dahdi_wink(p, index)) goto quit;
06926                dtmfbuf[0] = 0;
06927                /* Wait for the first digit (up to 5 seconds). */
06928                res = ast_waitfordigit(chan, 5000);
06929                if (res <= 0) break;
06930                dtmfbuf[0] = res;
06931                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06932             }
06933             if (res > 0) {
06934                /* if E911, take off hook */
06935                if (p->sig == SIG_E911)
06936                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06937                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
06938             }
06939             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06940             break;
06941          case SIG_FEATB:
06942          case SIG_SF_FEATB:
06943             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06944             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06945             break;
06946          case SIG_EMWINK:
06947             /* if we received a '*', we are actually receiving Feature Group D
06948                dial syntax, so use that mode; otherwise, fall through to normal
06949                mode
06950             */
06951             if (res == '*') {
06952                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06953                if (res > 0)
06954                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06955                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06956                break;
06957             }
06958          default:
06959             /* If we got the first digit, get the rest */
06960             len = 1;
06961             dtmfbuf[len] = '\0';
06962             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06963                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06964                   timeout = matchdigittimeout;
06965                } else {
06966                   timeout = gendigittimeout;
06967                }
06968                res = ast_waitfordigit(chan, timeout);
06969                if (res < 0) {
06970                   ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
06971                   ast_hangup(chan);
06972                   goto quit;
06973                } else if (res) {
06974                   dtmfbuf[len++] = res;
06975                   dtmfbuf[len] = '\0';
06976                } else {
06977                   break;
06978                }
06979             }
06980             break;
06981          }
06982       }
06983       if (res == -1) {
06984          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
06985          ast_hangup(chan);
06986          goto quit;
06987       } else if (res < 0) {
06988          ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
06989          ast_hangup(chan);
06990          goto quit;
06991       }
06992 
06993       if (p->sig == SIG_FGC_CAMA) {
06994          char anibuf[100];
06995 
06996          if (ast_safe_sleep(chan,1000) == -1) {
06997                            ast_hangup(chan);
06998                            goto quit;
06999          }
07000                         dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07001                         ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
07002                         res = my_getsigstr(chan, anibuf, "#", 10000);
07003                         if ((res > 0) && (strlen(anibuf) > 2)) {
07004             if (anibuf[strlen(anibuf) - 1] == '#')
07005                anibuf[strlen(anibuf) - 1] = 0;
07006             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
07007          }
07008                         ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
07009       }
07010 
07011       ast_copy_string(exten, dtmfbuf, sizeof(exten));
07012       if (ast_strlen_zero(exten))
07013          ast_copy_string(exten, "s", sizeof(exten));
07014       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
07015          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
07016          if (exten[0] == '*') {
07017             char *stringp=NULL;
07018             ast_copy_string(exten2, exten, sizeof(exten2));
07019             /* Parse out extension and callerid */
07020             stringp=exten2 +1;
07021             s1 = strsep(&stringp, "*");
07022             s2 = strsep(&stringp, "*");
07023             if (s2) {
07024                if (!ast_strlen_zero(p->cid_num))
07025                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07026                else
07027                   ast_set_callerid(chan, s1, NULL, s1);
07028                ast_copy_string(exten, s2, sizeof(exten));
07029             } else
07030                ast_copy_string(exten, s1, sizeof(exten));
07031          } else if (p->sig == SIG_FEATD)
07032             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
07033       }
07034       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07035          if (exten[0] == '*') {
07036             char *stringp=NULL;
07037             ast_copy_string(exten2, exten, sizeof(exten2));
07038             /* Parse out extension and callerid */
07039             stringp=exten2 +1;
07040             s1 = strsep(&stringp, "#");
07041             s2 = strsep(&stringp, "#");
07042             if (s2) {
07043                if (!ast_strlen_zero(p->cid_num))
07044                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07045                else
07046                   if (*(s1 + 2))
07047                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
07048                ast_copy_string(exten, s2 + 1, sizeof(exten));
07049             } else
07050                ast_copy_string(exten, s1 + 2, sizeof(exten));
07051          } else
07052             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
07053       }
07054       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
07055          if (exten[0] == '*') {
07056             char *stringp=NULL;
07057             ast_copy_string(exten2, exten, sizeof(exten2));
07058             /* Parse out extension and callerid */
07059             stringp=exten2 +1;
07060             s1 = strsep(&stringp, "#");
07061             s2 = strsep(&stringp, "#");
07062             if (s2 && (*(s2 + 1) == '0')) {
07063                if (*(s2 + 2))
07064                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
07065             }
07066             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
07067             else ast_copy_string(exten, "911", sizeof(exten));
07068          } else
07069             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
07070       }
07071       if (p->sig == SIG_FEATB) {
07072          if (exten[0] == '*') {
07073             char *stringp=NULL;
07074             ast_copy_string(exten2, exten, sizeof(exten2));
07075             /* Parse out extension and callerid */
07076             stringp=exten2 +1;
07077             s1 = strsep(&stringp, "#");
07078             ast_copy_string(exten, exten2 + 1, sizeof(exten));
07079          } else
07080             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
07081       }
07082       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07083          dahdi_wink(p, index);
07084                         /* some switches require a minimum guard time between
07085                            the last FGD wink and something that answers
07086                            immediately. This ensures it */
07087                         if (ast_safe_sleep(chan,100)) goto quit;
07088       }
07089       dahdi_enable_ec(p);
07090       if (NEED_MFDETECT(p)) {
07091          if (p->dsp) {
07092             if (!p->hardwaredtmf)
07093                ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 
07094             else {
07095                ast_dsp_free(p->dsp);
07096                p->dsp = NULL;
07097             }
07098          }
07099       }
07100 
07101       if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
07102          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07103          if (p->dsp) ast_dsp_digitreset(p->dsp);
07104          res = ast_pbx_run(chan);
07105          if (res) {
07106             ast_log(LOG_WARNING, "PBX exited non-zero\n");
07107             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07108          }
07109          goto quit;
07110       } else {
07111          if (option_verbose > 2)
07112             ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
07113          sleep(2);
07114          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
07115          if (res < 0)
07116             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
07117          else
07118             sleep(1);
07119          res = ast_streamfile(chan, "ss-noservice", chan->language);
07120          if (res >= 0)
07121             ast_waitstream(chan, "");
07122          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07123          ast_hangup(chan);
07124          goto quit;
07125       }
07126       break;
07127    case SIG_FXOLS:
07128    case SIG_FXOGS:
07129    case SIG_FXOKS:
07130       /* Read the first digit */
07131       timeout = firstdigittimeout;
07132       /* If starting a threeway call, never timeout on the first digit so someone
07133          can use flash-hook as a "hold" feature */
07134       if (p->subs[SUB_THREEWAY].owner) 
07135          timeout = 999999;
07136       while (len < AST_MAX_EXTENSION-1) {
07137          /* Read digit unless it's supposed to be immediate, in which case the
07138             only answer is 's' */
07139          if (p->immediate) 
07140             res = 's';
07141          else
07142             res = ast_waitfordigit(chan, timeout);
07143          timeout = 0;
07144          if (res < 0) {
07145             ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
07146             res = tone_zone_play_tone(p->subs[index].dfd, -1);
07147             ast_hangup(chan);
07148             goto quit;
07149          } else if (res)  {
07150             exten[len++]=res;
07151             exten[len] = '\0';
07152          }
07153          if (!ast_ignore_pattern(chan->context, exten))
07154             tone_zone_play_tone(p->subs[index].dfd, -1);
07155          else
07156             tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
07157          if (!strcmp(exten,ast_pickup_ext())) {
07158             /* Scan all channels and see if there are any
07159              * ringing channels that have call groups
07160              * that equal this channels pickup group
07161              */
07162             if (index == SUB_REAL) {
07163                /* Switch us from Third call to Call Wait */
07164                if (p->subs[SUB_THREEWAY].owner) {
07165                   /* If you make a threeway call and the *8# a call, it should actually
07166                      look like a callwait */
07167                   alloc_sub(p, SUB_CALLWAIT);
07168                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
07169                   unalloc_sub(p, SUB_THREEWAY);
07170                }
07171                dahdi_enable_ec(p);
07172                if (ast_pickup_call(chan)) {
07173                   ast_log(LOG_DEBUG, "No call pickup possible...\n");
07174                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07175                   dahdi_wait_event(p->subs[index].dfd);
07176                }
07177                ast_hangup(chan);
07178                goto quit;
07179             } else {
07180                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
07181                ast_hangup(chan);
07182                goto quit;
07183             }
07184 
07185          } else if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
07186             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
07187                if (getforward) {
07188                   /* Record this as the forwarding extension */
07189                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 
07190                   if (option_verbose > 2)
07191                      ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
07192                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07193                   if (res)
07194                      break;
07195                   usleep(500000);
07196                   res = tone_zone_play_tone(p->subs[index].dfd, -1);
07197                   sleep(1);
07198                   memset(exten, 0, sizeof(exten));
07199                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
07200                   len = 0;
07201                   getforward = 0;
07202                } else  {
07203                   res = tone_zone_play_tone(p->subs[index].dfd, -1);
07204                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07205                   if (!ast_strlen_zero(p->cid_num)) {
07206                      if (!p->hidecallerid)
07207                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 
07208                      else
07209                         ast_set_callerid(chan, NULL, NULL, p->cid_num); 
07210                   }
07211                   if (!ast_strlen_zero(p->cid_name)) {
07212                      if (!p->hidecallerid)
07213                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
07214                   }
07215                   ast_setstate(chan, AST_STATE_RING);
07216                   dahdi_enable_ec(p);
07217                   res = ast_pbx_run(chan);
07218                   if (res) {
07219                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
07220                      res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07221                   }
07222                   goto quit;
07223                }
07224             } else {
07225                /* It's a match, but they just typed a digit, and there is an ambiguous match,
07226                   so just set the timeout to matchdigittimeout and wait some more */
07227                timeout = matchdigittimeout;
07228             }
07229          } else if (res == 0) {
07230             ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
07231             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07232             dahdi_wait_event(p->subs[index].dfd);
07233             ast_hangup(chan);
07234             goto quit;
07235          } else if (p->callwaiting && !strcmp(exten, "*70")) {
07236             if (option_verbose > 2) 
07237                ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
07238             /* Disable call waiting if enabled */
07239             p->callwaiting = 0;
07240             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07241             if (res) {
07242                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
07243                   chan->name, strerror(errno));
07244             }
07245             len = 0;
07246             ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
07247             memset(exten, 0, sizeof(exten));
07248             timeout = firstdigittimeout;
07249                
07250          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
07251             if (option_verbose > 2) 
07252                ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
07253             /* Disable Caller*ID if enabled */
07254             p->hidecallerid = 1;
07255             if (chan->cid.cid_num)
07256                free(chan->cid.cid_num);
07257             chan->cid.cid_num = NULL;
07258             if (chan->cid.cid_name)
07259                free(chan->cid.cid_name);
07260             chan->cid.cid_name = NULL;
07261             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07262             if (res) {
07263                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
07264                   chan->name, strerror(errno));
07265             }
07266             len = 0;
07267             memset(exten, 0, sizeof(exten));
07268             timeout = firstdigittimeout;
07269          } else if (p->callreturn && !strcmp(exten, "*69")) {
07270             res = 0;
07271             if (!ast_strlen_zero(p->lastcid_num)) {
07272                res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
07273             }
07274             if (!res)
07275                res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07276             break;
07277          } else if (!strcmp(exten, "*78")) {
07278             /* Do not disturb */
07279             if (option_verbose > 2)
07280                ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
07281             manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07282                      "Channel: %s/%d\r\n"
07283                      "Status: enabled\r\n", dahdi_chan_name, p->channel);
07284             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07285             p->dnd = 1;
07286             getforward = 0;
07287             memset(exten, 0, sizeof(exten));
07288             len = 0;
07289          } else if (!strcmp(exten, "*79")) {
07290             /* Do not disturb */
07291             if (option_verbose > 2)
07292                ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
07293             manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07294                      "Channel: %s/%d\r\n"
07295                      "Status: disabled\r\n", dahdi_chan_name, p->channel);
07296             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07297             p->dnd = 0;
07298             getforward = 0;
07299             memset(exten, 0, sizeof(exten));
07300             len = 0;
07301          } else if (p->cancallforward && !strcmp(exten, "*72")) {
07302             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07303             getforward = 1;
07304             memset(exten, 0, sizeof(exten));
07305             len = 0;
07306          } else if (p->cancallforward && !strcmp(exten, "*73")) {
07307             if (option_verbose > 2)
07308                ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
07309             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07310             memset(p->call_forward, 0, sizeof(p->call_forward));
07311             getforward = 0;
07312             memset(exten, 0, sizeof(exten));
07313             len = 0;
07314          } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 
07315                   p->subs[SUB_THREEWAY].owner &&
07316                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07317             /* This is a three way call, the main call being a real channel, 
07318                and we're parking the first call. */
07319             ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
07320             if (option_verbose > 2)
07321                ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
07322             break;
07323          } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
07324             if (option_verbose > 2)
07325                ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
07326             res = ast_db_put("blacklist", p->lastcid_num, "1");
07327             if (!res) {
07328                res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07329                memset(exten, 0, sizeof(exten));
07330                len = 0;
07331             }
07332          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
07333             if (option_verbose > 2) 
07334                ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
07335             /* Enable Caller*ID if enabled */
07336             p->hidecallerid = 0;
07337             if (chan->cid.cid_num)
07338                free(chan->cid.cid_num);
07339             chan->cid.cid_num = NULL;
07340             if (chan->cid.cid_name)
07341                free(chan->cid.cid_name);
07342             chan->cid.cid_name = NULL;
07343             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
07344             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07345             if (res) {
07346                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
07347                   chan->name, strerror(errno));
07348             }
07349             len = 0;
07350             memset(exten, 0, sizeof(exten));
07351             timeout = firstdigittimeout;
07352          } else if (!strcmp(exten, "*0")) {
07353             struct ast_channel *nbridge = 
07354                p->subs[SUB_THREEWAY].owner;
07355             struct dahdi_pvt *pbridge = NULL;
07356               /* set up the private struct of the bridged one, if any */
07357             if (nbridge && ast_bridged_channel(nbridge)) 
07358                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
07359             if (nbridge && pbridge && 
07360                 (nbridge->tech == chan_tech) && 
07361                 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
07362                 ISTRUNK(pbridge)) {
07363                int func = DAHDI_FLASH;
07364                /* Clear out the dial buffer */
07365                p->dop.dialstr[0] = '\0';
07366                /* flash hookswitch */
07367                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07368                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
07369                      nbridge->name, strerror(errno));
07370                }
07371                swap_subs(p, SUB_REAL, SUB_THREEWAY);
07372                unalloc_sub(p, SUB_THREEWAY);
07373                p->owner = p->subs[SUB_REAL].owner;
07374                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
07375                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07376                ast_hangup(chan);
07377                goto quit;
07378             } else {
07379                tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07380                dahdi_wait_event(p->subs[index].dfd);
07381                tone_zone_play_tone(p->subs[index].dfd, -1);
07382                swap_subs(p, SUB_REAL, SUB_THREEWAY);
07383                unalloc_sub(p, SUB_THREEWAY);
07384                p->owner = p->subs[SUB_REAL].owner;
07385                ast_hangup(chan);
07386                goto quit;
07387             }              
07388          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
07389                      ((exten[0] != '*') || (strlen(exten) > 2))) {
07390             if (option_debug)
07391                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);
07392             break;
07393          }
07394          if (!timeout)
07395             timeout = gendigittimeout;
07396          if (len && !ast_ignore_pattern(chan->context, exten))
07397             tone_zone_play_tone(p->subs[index].dfd, -1);
07398       }
07399       break;
07400    case SIG_FXSLS:
07401    case SIG_FXSGS:
07402    case SIG_FXSKS:
07403 #ifdef HAVE_PRI
07404       if (p->pri) {
07405          /* This is a GR-303 trunk actually.  Wait for the first ring... */
07406          struct ast_frame *f;
07407          int res;
07408          time_t start;
07409 
07410          time(&start);
07411          ast_setstate(chan, AST_STATE_RING);
07412          while (time(NULL) < start + 3) {
07413             res = ast_waitfor(chan, 1000);
07414             if (res) {
07415                f = ast_read(chan);
07416                if (!f) {
07417                   ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
07418                   ast_hangup(chan);
07419                   goto quit;
07420                } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
07421                   res = 1;
07422                } else
07423                   res = 0;
07424                ast_frfree(f);
07425                if (res) {
07426                   ast_log(LOG_DEBUG, "Got ring!\n");
07427                   res = 0;
07428                   break;
07429                }
07430             }
07431          }
07432       }
07433 #endif
07434       /* check for SMDI messages */
07435       if (p->use_smdi && p->smdi_iface) {
07436          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
07437 
07438          if (smdi_msg != NULL) {
07439             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
07440 
07441             if (smdi_msg->type == 'B')
07442                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
07443             else if (smdi_msg->type == 'N')
07444                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
07445 
07446             ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
07447          } else {
07448             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
07449          }
07450       }
07451 
07452       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
07453             number = smdi_msg->calling_st;
07454 
07455       /* If we want caller id, we're in a prering state due to a polarity reversal
07456        * and we're set to use a polarity reversal to trigger the start of caller id,
07457        * grab the caller id and wait for ringing to start... */
07458       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
07459                    (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_DTMF_NOALERT))) {
07460          /* If set to use DTMF CID signalling, listen for DTMF */
07461          if (p->cid_signalling == CID_SIG_DTMF) {
07462             int i = 0;
07463             cs = NULL;
07464             ast_log(LOG_DEBUG, "Receiving DTMF cid on "
07465                "channel %s\n", chan->name);
07466             dahdi_setlinear(p->subs[index].dfd, 0);
07467             res = 2000;
07468             for (;;) {
07469                struct ast_frame *f;
07470                res = ast_waitfor(chan, res);
07471                if (res <= 0) {
07472                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07473                      "Exiting simple switch\n");
07474                   ast_hangup(chan);
07475                   goto quit;
07476                } 
07477                f = ast_read(chan);
07478                if (!f)
07479                   break;
07480                if (f->frametype == AST_FRAME_DTMF) {
07481                   dtmfbuf[i++] = f->subclass;
07482                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
07483                   res = 2000;
07484                }
07485                ast_frfree(f);
07486                if (chan->_state == AST_STATE_RING ||
07487                    chan->_state == AST_STATE_RINGING) 
07488                   break; /* Got ring */
07489             }
07490             dtmfbuf[i] = '\0';
07491             dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07492             /* Got cid and ring. */
07493             ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
07494             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07495             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 
07496                dtmfcid, flags);
07497             /* If first byte is NULL, we have no cid */
07498             if (!ast_strlen_zero(dtmfcid)) 
07499                number = dtmfcid;
07500             else
07501                number = NULL;
07502          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
07503          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
07504             cs = callerid_new(p->cid_signalling);
07505             if (cs) {
07506                samples = 0;
07507 #if 1
07508                bump_gains(p);
07509 #endif            
07510                /* Take out of linear mode for Caller*ID processing */
07511                dahdi_setlinear(p->subs[index].dfd, 0);
07512                
07513                /* First we wait and listen for the Caller*ID */
07514                for (;;) {  
07515                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07516                   if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
07517                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07518                      callerid_free(cs);
07519                      ast_hangup(chan);
07520                      goto quit;
07521                   }
07522                   if (i & DAHDI_IOMUX_SIGEVENT) {
07523                      res = dahdi_get_event(p->subs[index].dfd);
07524                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07525 
07526                      if (p->cid_signalling == CID_SIG_V23_JP) {
07527 #ifdef DAHDI_EVENT_RINGBEGIN
07528                         if (res == DAHDI_EVENT_RINGBEGIN) {
07529                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07530                            usleep(1);
07531                         }
07532 #endif
07533                      } else {
07534                         res = 0;
07535                         break;
07536                      }
07537                   } else if (i & DAHDI_IOMUX_READ) {
07538                      res = read(p->subs[index].dfd, buf, sizeof(buf));
07539                      if (res < 0) {
07540                         if (errno != ELAST) {
07541                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07542                            callerid_free(cs);
07543                            ast_hangup(chan);
07544                            goto quit;
07545                         }
07546                         break;
07547                      }
07548                      samples += res;
07549 
07550                      if  (p->cid_signalling == CID_SIG_V23_JP) {
07551                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
07552                      } else {
07553                         res = callerid_feed(cs, buf, res, AST_LAW(p));
07554                      }
07555 
07556                      if (res < 0) {
07557                         ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
07558                         break;
07559                      } else if (res)
07560                         break;
07561                      else if (samples > (8000 * 10))
07562                         break;
07563                   }
07564                }
07565                if (res == 1) {
07566                   callerid_get(cs, &name, &number, &flags);
07567                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07568                }
07569 
07570                if (p->cid_signalling == CID_SIG_V23_JP) {
07571                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07572                   usleep(1);
07573                   res = 4000;
07574                } else {
07575 
07576                   /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 
07577                   res = 2000;
07578                }
07579 
07580                for (;;) {
07581                   struct ast_frame *f;
07582                   res = ast_waitfor(chan, res);
07583                   if (res <= 0) {
07584                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
07585                         "Exiting simple switch\n");
07586                      ast_hangup(chan);
07587                      goto quit;
07588                   } 
07589                   if (!(f = ast_read(chan))) {
07590                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
07591                      ast_hangup(chan);
07592                      goto quit;
07593                   }
07594                   ast_frfree(f);
07595                   if (chan->_state == AST_STATE_RING ||
07596                       chan->_state == AST_STATE_RINGING) 
07597                      break; /* Got ring */
07598                }
07599    
07600                /* We must have a ring by now, so, if configured, lets try to listen for
07601                 * distinctive ringing */ 
07602                if (p->usedistinctiveringdetection) {
07603                   len = 0;
07604                   distMatches = 0;
07605                   /* Clear the current ring data array so we dont have old data in it. */
07606                   for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
07607                      curRingData[receivedRingT] = 0;
07608                   receivedRingT = 0;
07609                   counter = 0;
07610                   counter1 = 0;
07611                   /* Check to see if context is what it should be, if not set to be. */
07612                   if (strcmp(p->context,p->defcontext) != 0) {
07613                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07614                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07615                   }
07616       
07617                   for (;;) {  
07618                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07619                      if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
07620                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07621                         callerid_free(cs);
07622                         ast_hangup(chan);
07623                         goto quit;
07624                      }
07625                      if (i & DAHDI_IOMUX_SIGEVENT) {
07626                         res = dahdi_get_event(p->subs[index].dfd);
07627                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07628                         res = 0;
07629                         /* Let us detect distinctive ring */
07630       
07631                         curRingData[receivedRingT] = p->ringt;
07632       
07633                         if (p->ringt < p->ringt_base/2)
07634                            break;
07635                         /* Increment the ringT counter so we can match it against
07636                            values in chan_dahdi.conf for distinctive ring */
07637                         if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
07638                            break;
07639                      } else if (i & DAHDI_IOMUX_READ) {
07640                         res = read(p->subs[index].dfd, buf, sizeof(buf));
07641                         if (res < 0) {
07642                            if (errno != ELAST) {
07643                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07644                               callerid_free(cs);
07645                               ast_hangup(chan);
07646                               goto quit;
07647                            }
07648                            break;
07649                         }
07650                         if (p->ringt) 
07651                            p->ringt--;
07652                         if (p->ringt == 1) {
07653                            res = -1;
07654                            break;
07655                         }
07656                      }
07657                   }
07658                   if (option_verbose > 2)
07659                      /* this only shows up if you have n of the dring patterns filled in */
07660                      ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07661    
07662                   for (counter = 0; counter < 3; counter++) {
07663                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
07664                      channel */
07665                      distMatches = 0;
07666                      for (counter1 = 0; counter1 < 3; counter1++) {
07667                         if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
07668                         (p->drings.ringnum[counter].ring[counter1]-10)) {
07669                            distMatches++;
07670                         }
07671                      }
07672                      if (distMatches == 3) {
07673                         /* The ring matches, set the context to whatever is for distinctive ring.. */
07674                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07675                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07676                         if (option_verbose > 2)
07677                            ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
07678                         break;
07679                      }
07680                   }
07681                }
07682                /* Restore linear mode (if appropriate) for Caller*ID processing */
07683                dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07684 #if 1
07685                restore_gains(p);
07686 #endif            
07687             } else
07688                ast_log(LOG_WARNING, "Unable to get caller ID space\n");       
07689          } else {
07690             ast_log(LOG_WARNING, "Channel %s in prering "
07691                "state, but I have nothing to do. "
07692                "Terminating simple switch, should be "
07693                "restarted by the actual ring.\n", 
07694                chan->name);
07695             ast_hangup(chan);
07696             goto quit;
07697          }
07698       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
07699          /* FSK Bell202 callerID */
07700          cs = callerid_new(p->cid_signalling);
07701          if (cs) {
07702 #if 1
07703             bump_gains(p);
07704 #endif            
07705             samples = 0;
07706             len = 0;
07707             distMatches = 0;
07708             /* Clear the current ring data array so we dont have old data in it. */
07709             for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
07710                curRingData[receivedRingT] = 0;
07711             receivedRingT = 0;
07712             counter = 0;
07713             counter1 = 0;
07714             /* Check to see if context is what it should be, if not set to be. */
07715             if (strcmp(p->context,p->defcontext) != 0) {
07716                ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07717                ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07718             }
07719 
07720             /* Take out of linear mode for Caller*ID processing */
07721             dahdi_setlinear(p->subs[index].dfd, 0);
07722             for (;;) {  
07723                i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07724                if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
07725                   ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07726                   callerid_free(cs);
07727                   ast_hangup(chan);
07728                   goto quit;
07729                }
07730                if (i & DAHDI_IOMUX_SIGEVENT) {
07731                   res = dahdi_get_event(p->subs[index].dfd);
07732                   ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07733                   /* If we get a PR event, they hung up while processing calerid */
07734                   if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
07735                      ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
07736                      p->polarity = POLARITY_IDLE;
07737                      callerid_free(cs);
07738                      ast_hangup(chan);
07739                      goto quit;
07740                   }
07741                   res = 0;
07742                   /* Let us detect callerid when the telco uses distinctive ring */
07743 
07744                   curRingData[receivedRingT] = p->ringt;
07745 
07746                   if (p->ringt < p->ringt_base/2)
07747                      break;
07748                   /* Increment the ringT counter so we can match it against
07749                      values in chan_dahdi.conf for distinctive ring */
07750                   if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
07751                      break;
07752                } else if (i & DAHDI_IOMUX_READ) {
07753                   res = read(p->subs[index].dfd, buf, sizeof(buf));
07754                   if (res < 0) {
07755                      if (errno != ELAST) {
07756                         ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07757                         callerid_free(cs);
07758                         ast_hangup(chan);
07759                         goto quit;
07760                      }
07761                      break;
07762                   }
07763                   if (p->ringt) 
07764                      p->ringt--;
07765                   if (p->ringt == 1) {
07766                      res = -1;
07767                      break;
07768                   }
07769                   samples += res;
07770                   res = callerid_feed(cs, buf, res, AST_LAW(p));
07771                   if (res < 0) {
07772                      ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
07773                      break;
07774                   } else if (res)
07775                      break;
07776                   else if (samples > (8000 * 10))
07777                      break;
07778                }
07779             }
07780             if (res == 1) {
07781                callerid_get(cs, &name, &number, &flags);
07782                if (option_debug)
07783                   ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07784             }
07785             if (distinctiveringaftercid == 1) {
07786                /* Clear the current ring data array so we dont have old data in it. */
07787                for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
07788                   curRingData[receivedRingT] = 0;
07789                }
07790                receivedRingT = 0;
07791                if (option_verbose > 2)
07792                   ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
07793                for (;;) {
07794                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07795                   if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))    {
07796                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07797                      callerid_free(cs);
07798                      ast_hangup(chan);
07799                      goto quit;
07800                   }
07801                   if (i & DAHDI_IOMUX_SIGEVENT) {
07802                      res = dahdi_get_event(p->subs[index].dfd);
07803                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07804                      res = 0;
07805                      /* Let us detect callerid when the telco uses distinctive ring */
07806 
07807                      curRingData[receivedRingT] = p->ringt;
07808 
07809                      if (p->ringt < p->ringt_base/2)
07810                         break;
07811                      /* Increment the ringT counter so we can match it against
07812                         values in chan_dahdi.conf for distinctive ring */
07813                      if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
07814                         break;
07815                   } else if (i & DAHDI_IOMUX_READ) {
07816                      res = read(p->subs[index].dfd, buf, sizeof(buf));
07817                      if (res < 0) {
07818                         if (errno != ELAST) {
07819                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07820                            callerid_free(cs);
07821                            ast_hangup(chan);
07822                            goto quit;
07823                         }
07824                         break;
07825                      }
07826                   if (p->ringt)
07827                      p->ringt--;
07828                      if (p->ringt == 1) {
07829                         res = -1;
07830                         break;
07831                      }
07832                   }
07833                }
07834             }
07835             if (p->usedistinctiveringdetection) {
07836                if (option_verbose > 2)
07837                   /* this only shows up if you have n of the dring patterns filled in */
07838                   ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07839 
07840                for (counter = 0; counter < 3; counter++) {
07841                   /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
07842                   channel */
07843                   if (option_verbose > 2)
07844                      /* this only shows up if you have n of the dring patterns filled in */
07845                      ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
07846                         p->drings.ringnum[counter].ring[0],
07847                         p->drings.ringnum[counter].ring[1],
07848                         p->drings.ringnum[counter].ring[2]);
07849                   distMatches = 0;
07850                   for (counter1 = 0; counter1 < 3; counter1++) {
07851                      if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
07852                      (p->drings.ringnum[counter].ring[counter1]-10)) {
07853                         distMatches++;
07854                      }
07855                   }
07856                   if (distMatches == 3) {
07857                      /* The ring matches, set the context to whatever is for distinctive ring.. */
07858                      ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07859                      ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07860                      if (option_verbose > 2)
07861                         ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
07862                      break;
07863                   }
07864                }
07865             }
07866             /* Restore linear mode (if appropriate) for Caller*ID processing */
07867             dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07868 #if 1
07869             restore_gains(p);
07870 #endif            
07871             if (res < 0) {
07872                ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
07873             }
07874          } else
07875             ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07876       }
07877       else
07878          cs = NULL;
07879 
07880       if (number)
07881          ast_shrink_phone_number(number);
07882       ast_set_callerid(chan, number, name, number);
07883 
07884       if (smdi_msg)
07885          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
07886 
07887       if (cs)
07888          callerid_free(cs);
07889 
07890       ast_setstate(chan, AST_STATE_RING);
07891       chan->rings = 1;
07892       p->ringt = p->ringt_base;
07893       res = ast_pbx_run(chan);
07894       if (res) {
07895          ast_hangup(chan);
07896          ast_log(LOG_WARNING, "PBX exited non-zero\n");
07897       }
07898       goto quit;
07899    default:
07900       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
07901       res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07902       if (res < 0)
07903             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07904    }
07905    res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07906    if (res < 0)
07907          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07908    ast_hangup(chan);
07909 quit:
07910    ast_mutex_lock(&ss_thread_lock);
07911    ss_thread_count--;
07912    ast_cond_signal(&ss_thread_complete);
07913    ast_mutex_unlock(&ss_thread_lock);
07914    return NULL;
07915 }

static int start_pri ( struct dahdi_pri pri  )  [static]

Definition at line 11176 of file chan_dahdi.c.

References ast_log(), dahdi_close_pri_fd(), DAHDI_FILE_CHANNEL, DAHDI_OVERLAPDIAL_BOTH, DAHDI_OVERLAPDIAL_OUTGOING, DCHAN_NOTINALARM, dahdi_pri::dchanavail, dahdi_pri::dchannels, dahdi_pri::dchans, DEFAULT_PRI_DEBUG, errno, dahdi_pri::fds, dahdi_pri::inbanddisconnect, LOG_ERROR, dahdi_pri::nodetype, dahdi_pri::nsf, dahdi_pri::overlapdial, and dahdi_pri::switchtype.

Referenced by setup_dahdi().

11177 {
11178    int res, x;
11179    struct dahdi_params p;
11180    struct dahdi_bufferinfo bi;
11181    struct dahdi_spaninfo si;
11182    int i;
11183    
11184    for (i = 0; i < NUM_DCHANS; i++) {
11185       if (!pri->dchannels[i])
11186          break;
11187       pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600);
11188       x = pri->dchannels[i];
11189       if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
11190          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
11191          return -1;
11192       }
11193       memset(&p, 0, sizeof(p));
11194       res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
11195       if (res) {
11196          dahdi_close_pri_fd(pri, i);
11197          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
11198          return -1;
11199       }
11200       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
11201          dahdi_close_pri_fd(pri, i);
11202          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.  See /etc/dahdi/system.conf\n", x);
11203          return -1;
11204       }
11205       memset(&si, 0, sizeof(si));
11206       res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
11207       if (res) {
11208          dahdi_close_pri_fd(pri, i);
11209          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
11210       }
11211       if (!si.alarms)
11212          pri->dchanavail[i] |= DCHAN_NOTINALARM;
11213       else
11214          pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
11215       memset(&bi, 0, sizeof(bi));
11216       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
11217       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
11218       bi.numbufs = 32;
11219       bi.bufsize = 1024;
11220       if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
11221          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
11222          dahdi_close_pri_fd(pri, i);
11223          return -1;
11224       }
11225       pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
11226       /* Force overlap dial if we're doing GR-303! */
11227       if (pri->switchtype == PRI_SWITCH_GR303_TMC)
11228          pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
11229       pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
11230 #ifdef HAVE_PRI_INBANDDISCONNECT
11231       pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
11232 #endif
11233       /* Enslave to master if appropriate */
11234       if (i)
11235          pri_enslave(pri->dchans[0], pri->dchans[i]);
11236       if (!pri->dchans[i]) {
11237          dahdi_close_pri_fd(pri, i);
11238          ast_log(LOG_ERROR, "Unable to create PRI structure\n");
11239          return -1;
11240       }
11241       pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
11242       pri_set_nsf(pri->dchans[i], pri->nsf);
11243 #ifdef PRI_GETSET_TIMERS
11244       for (x = 0; x < PRI_MAX_TIMERS; x++) {
11245          if (pritimers[x] != 0)
11246             pri_set_timer(pri->dchans[i], x, pritimers[x]);
11247       }
11248 #endif
11249    }
11250    /* Assume primary is the one we use */
11251    pri->pri = pri->dchans[0];
11252    pri->resetpos = -1;
11253    if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
11254       for (i = 0; i < NUM_DCHANS; i++) {
11255          if (!pri->dchannels[i])
11256             break;
11257          dahdi_close_pri_fd(pri, i);
11258       }
11259       ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
11260       return -1;
11261    }
11262    return 0;
11263 }

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

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

01773 {
01774    int tchan;
01775    int tinthreeway;
01776    struct ast_channel *towner;
01777 
01778    ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
01779 
01780    tchan = p->subs[a].chan;
01781    towner = p->subs[a].owner;
01782    tinthreeway = p->subs[a].inthreeway;
01783 
01784    p->subs[a].chan = p->subs[b].chan;
01785    p->subs[a].owner = p->subs[b].owner;
01786    p->subs[a].inthreeway = p->subs[b].inthreeway;
01787 
01788    p->subs[b].chan = tchan;
01789    p->subs[b].owner = towner;
01790    p->subs[b].inthreeway = tinthreeway;
01791 
01792    if (p->subs[a].owner) 
01793       p->subs[a].owner->fds[0] = p->subs[a].dfd;
01794    if (p->subs[b].owner) 
01795       p->subs[b].owner->fds[0] = p->subs[b].dfd;
01796    wakeup_sub(p, a, NULL);
01797    wakeup_sub(p, b, NULL);
01798 }

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

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

01912 {
01913    if (!x) {
01914       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01915       return -1;
01916    }
01917    ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
01918    dahdi_close_sub(p, x);
01919    p->subs[x].linear = 0;
01920    p->subs[x].chan = 0;
01921    p->subs[x].owner = NULL;
01922    p->subs[x].inthreeway = 0;
01923    p->polarity = POLARITY_IDLE;
01924    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01925    return 0;
01926 }

static int unload_module ( void   )  [static]

Definition at line 12837 of file chan_dahdi.c.

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

12838 {
12839 #ifdef HAVE_PRI      
12840    int y;
12841    for (y = 0; y < NUM_SPANS; y++)
12842       ast_mutex_destroy(&pris[y].lock);
12843 #endif
12844    return __unload_module();
12845 }

static int update_conf ( struct dahdi_pvt p  )  [static]

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

02295 {
02296    int needconf = 0;
02297    int x;
02298    int useslavenative;
02299    struct dahdi_pvt *slave = NULL;
02300 
02301    useslavenative = isslavenative(p, &slave);
02302    /* Start with the obvious, general stuff */
02303    for (x = 0; x < 3; x++) {
02304       /* Look for three way calls */
02305       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
02306          conf_add(p, &p->subs[x], x, 0);
02307          needconf++;
02308       } else {
02309          conf_del(p, &p->subs[x], x);
02310       }
02311    }
02312    /* If we have a slave, add him to our conference now. or DAX
02313       if this is slave native */
02314    for (x = 0; x < MAX_SLAVES; x++) {
02315       if (p->slaves[x]) {
02316          if (useslavenative)
02317             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02318          else {
02319             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02320             needconf++;
02321          }
02322       }
02323    }
02324    /* If we're supposed to be in there, do so now */
02325    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02326       if (useslavenative)
02327          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02328       else {
02329          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02330          needconf++;
02331       }
02332    }
02333    /* If we have a master, add ourselves to his conference */
02334    if (p->master) {
02335       if (isslavenative(p->master, NULL)) {
02336          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02337       } else {
02338          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02339       }
02340    }
02341    if (!needconf) {
02342       /* Nobody is left (or should be left) in our conference.
02343          Kill it. */
02344       p->confno = -1;
02345    }
02346    if (option_debug)
02347       ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02348    return 0;
02349 }

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

Definition at line 1208 of file chan_dahdi.c.

References ast_mutex_trylock(), ast_mutex_unlock(), ast_null_frame, ast_queue_frame(), and DEADLOCK_AVOIDANCE.

Referenced by swap_subs().

01212 {
01213 #ifdef HAVE_PRI
01214    if (pri)
01215       ast_mutex_unlock(&pri->lock);
01216 #endif         
01217    for (;;) {
01218       if (p->subs[a].owner) {
01219          if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
01220             DEADLOCK_AVOIDANCE(&p->lock);
01221          } else {
01222             ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01223             ast_mutex_unlock(&p->subs[a].owner->lock);
01224             break;
01225          }
01226       } else
01227          break;
01228    }
01229 #ifdef HAVE_PRI
01230    if (pri)
01231       ast_mutex_lock(&pri->lock);
01232 #endif         
01233 }

static int zap_accept_r2_call_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 3546 of file chan_dahdi.c.

References dahdi_accept_r2_call_exec().

Referenced by load_module().

03547 {
03548    return dahdi_accept_r2_call_exec(chan, data);
03549 }

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

Definition at line 12661 of file chan_dahdi.c.

References __action_dialoffhook(), and s.

12662 {
12663    return __action_dialoffhook(s, m, 1);
12664 }

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

Definition at line 12561 of file chan_dahdi.c.

References __action_dnd(), and s.

12562 {
12563    return __action_dnd(s, m, 1, 0);
12564 }

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

Definition at line 12551 of file chan_dahdi.c.

References __action_dnd(), and s.

12552 {
12553    return __action_dnd(s, m, 1, 1);
12554 }

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

Definition at line 12740 of file chan_dahdi.c.

References __action_restart(), and s.

12741 {
12742    return __action_restart(s, m, 1);
12743 }

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

Definition at line 12716 of file chan_dahdi.c.

References __action_showchannels(), and s.

12717 {
12718    return __action_showchannels(s, m, 1);
12719 }

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

Definition at line 12590 of file chan_dahdi.c.

References __action_transfer(), and s.

12591 {
12592    return __action_transfer(s, m, 1);
12593 }

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

Definition at line 12618 of file chan_dahdi.c.

References __action_transferhangup(), and s.

12619 {
12620    return __action_transferhangup(s, m, 1);
12621 }

static int zap_send_keypad_facility_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 3345 of file chan_dahdi.c.

References ast_log(), LOG_WARNING, and send_keypad_facility_exec().

Referenced by load_module().

03346 {
03347    ast_log(LOG_WARNING, "Use of the command %s is deprecated, please use %s instead.\n", zap_send_keypad_facility_app, dahdi_send_keypad_facility_app);  
03348    return send_keypad_facility_exec(chan, data);
03349 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "DAHDI Telephony w/PRI" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 14129 of file chan_dahdi.c.

int alarm

Definition at line 2063 of file chan_dahdi.c.

Referenced by __action_showchannels().

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

Referenced by alarm2str(), and dahdi_show_status().

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 14129 of file chan_dahdi.c.

struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static]

Definition at line 1166 of file chan_dahdi.c.

struct ast_channel_tech* chan_tech [static]

Definition at line 1134 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 1177 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 12457 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 12462 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 12442 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 12452 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 12447 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 12467 of file chan_dahdi.c.

char* dahdi_accept_r2_call_app = "DAHDIAcceptR2Call" [static]

Definition at line 3431 of file chan_dahdi.c.

char* dahdi_accept_r2_call_descrip [static]

Initial value:

 
"  DAHDIAcceptR2Call(): This application will accept the current MFC/R2 call\n"
"  You can specify yes or no as argument to accept with or without charge.\n"

Definition at line 3437 of file chan_dahdi.c.

char* dahdi_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)" [static]

Definition at line 3434 of file chan_dahdi.c.

struct ast_cli_entry dahdi_cli[] [static]

Definition at line 12472 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct ast_cli_entry dahdi_mfcr2_cli[] [static]

Definition at line 11888 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct ast_cli_entry dahdi_pri_cli[] [static]

Definition at line 11548 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

const char dahdi_r2_callfiles_help[] [static]

Initial value:

         "Usage: mfcr2 call files [on|off] <channel>\n"
         "       Enable call files creation on the specified channel.\n"
         "       If no channel is specified call files creation policy will be applied to all channels.\n"

Definition at line 11873 of file chan_dahdi.c.

openr2_event_interface_t dahdi_r2_event_iface [static]

Definition at line 1732 of file chan_dahdi.c.

const char dahdi_r2_setblocked_help[] [static]

Initial value:

         "Usage: mfcr2 set blocked <channel>\n"
         "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
         "       Force the given channel into BLOCKED state.\n"
         "       If no channel is specified, all channels will be set to BLOCKED.\n"

Definition at line 11882 of file chan_dahdi.c.

const char dahdi_r2_setdebug_help[] [static]

Initial value:

         "Usage: mfcr2 set debug <loglevel> <channel>\n"
         "       Set a new logging level for the specified channel.\n"
         "       If no channel is specified the logging level will be applied to all channels.\n"

Definition at line 11869 of file chan_dahdi.c.

const char dahdi_r2_setidle_help[] [static]

Initial value:

         "Usage: mfcr2 set idle <channel>\n"
         "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
         "       Force the given channel into IDLE state.\n"
         "       If no channel is specified, all channels will be set to IDLE.\n"

Definition at line 11877 of file chan_dahdi.c.

const char dahdi_r2_showchannels_help[] [static]

Initial value:

         "Usage: mfcr2 show channels [group <group> | context <context>]\n"
         "       Shows the zap channels configured with MFC/R2 signaling.\n"

Definition at line 11866 of file chan_dahdi.c.

openr2_transcoder_interface_t dahdi_r2_transcode_iface [static]

Initial value:

Definition at line 1763 of file chan_dahdi.c.

const char dahdi_r2_variants_help[] [static]

Initial value:

 
         "Usage: mfcr2 show variants\n"
         "       Show supported MFC/R2 variants.\n"

Definition at line 11863 of file chan_dahdi.c.

const char dahdi_r2_version_help[] [static]

Initial value:

 
         "Usage: mfcr2 show version\n"
         "       Shows the version of the OpenR2 library being used.\n"

Definition at line 11860 of file chan_dahdi.c.

char dahdi_restart_usage[] [static]

Definition at line 12435 of file chan_dahdi.c.

char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static]

Definition at line 3287 of file chan_dahdi.c.

char* dahdi_send_keypad_facility_descrip [static]

Initial value:

 
"  DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
"  IE over the current channel.\n"

Definition at line 3293 of file chan_dahdi.c.

char* dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static]

Definition at line 3290 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 12328 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 12427 of file chan_dahdi.c.

struct ast_channel_tech dahdi_tech [static]

Definition at line 1092 of file chan_dahdi.c.

Referenced by dahdi_accept_r2_call_exec(), and load_module().

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 115 of file chan_dahdi.c.

char defaultcic[64] = "" [static]

Definition at line 214 of file chan_dahdi.c.

char defaultozz[64] = "" [static]

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

int distinctiveringaftercid = 0 [static]

Definition at line 219 of file chan_dahdi.c.

struct dahdi_distRings drings [static]

Definition at line 435 of file chan_dahdi.c.

Referenced by process_dahdi().

int dtmfcid_level = 256 [static]

Definition at line 222 of file chan_dahdi.c.

char* events[] [static]

Definition at line 2040 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 234 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 237 of file chan_dahdi.c.

Referenced by mgcp_ss(), and skinny_ss().

struct ast_jb_conf global_jbconf [static]

Definition at line 122 of file chan_dahdi.c.

int ifcount = 0 [static]

Definition at line 246 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_mfcr2_call_files(), handle_mfcr2_set_blocked(), handle_mfcr2_set_debug(), handle_mfcr2_set_idle(), handle_mfcr2_show_channels(), handle_request_subscribe(), load_module(), mkintf(), oh323_alloc(), phone_request(), sip_alloc(), sip_show_channel(), sip_show_history(), and unload_module().

ast_mutex_t iflock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Protect the interface list (of dahdi_pvt's).

Definition at line 243 of file chan_dahdi.c.

Referenced by __action_showchannels(), __sip_show_channels(), __unload_module(), complete_sipch(), dahdi_destroy_channel_bynum(), dahdi_hangup(), dahdi_request(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), do_monitor(), find_call(), find_call_locked(), get_sip_pvt_byid_locked(), handle_mfcr2_call_files(), handle_mfcr2_set_blocked(), handle_mfcr2_set_debug(), handle_mfcr2_set_idle(), handle_mfcr2_show_channels(), handle_request_subscribe(), load_module(), oh323_alloc(), oh323_destroy(), phone_request(), restart_monitor(), setup_dahdi(), sip_alloc(), sip_destroy(), sip_show_channel(), sip_show_history(), and unload_module().

struct ast_channel inuse [static]

Definition at line 225 of file chan_dahdi.c.

Referenced by ast_jb_do_usecheck(), chanavail_exec(), load_module(), pri_assign_bearer(), and update_call_counter().

int matchdigittimeout = 3000 [static]

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

Definition at line 240 of file chan_dahdi.c.

Referenced by mgcp_ss(), and skinny_ss().

int mfcr2_cur_accept_on_offer = 1 [static]

Definition at line 332 of file chan_dahdi.c.

int mfcr2_cur_allow_collect_calls = 0 [static]

Definition at line 331 of file chan_dahdi.c.

int mfcr2_cur_call_files = 0 [static]

Definition at line 330 of file chan_dahdi.c.

openr2_calling_party_category_t mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER [static]

Definition at line 347 of file chan_dahdi.c.

int mfcr2_cur_charge_calls = 1 [static]

Definition at line 333 of file chan_dahdi.c.

int mfcr2_cur_context_index = 0 [static]

Definition at line 329 of file chan_dahdi.c.

int mfcr2_cur_double_answer = 0 [static]

Definition at line 335 of file chan_dahdi.c.

int mfcr2_cur_forced_release = 0 [static]

Definition at line 334 of file chan_dahdi.c.

int mfcr2_cur_get_ani_first = -1 [static]

Definition at line 327 of file chan_dahdi.c.

int mfcr2_cur_immediate_accept = -1 [static]

Definition at line 336 of file chan_dahdi.c.

char mfcr2_cur_logdir[OR2_MAX_PATH] [static]

Definition at line 344 of file chan_dahdi.c.

openr2_log_level_t mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING [static]

Definition at line 346 of file chan_dahdi.c.

int mfcr2_cur_max_ani = 10 [static]

Definition at line 325 of file chan_dahdi.c.

int mfcr2_cur_max_dnis = 4 [static]

Definition at line 326 of file chan_dahdi.c.

int mfcr2_cur_metering_pulse_timeout = -1 [static]

Definition at line 324 of file chan_dahdi.c.

int mfcr2_cur_mfback_timeout = -1 [static]

Definition at line 323 of file chan_dahdi.c.

char mfcr2_cur_r2proto_file[OR2_MAX_PATH] [static]

Definition at line 345 of file chan_dahdi.c.

int mfcr2_cur_skip_category = -1 [static]

Definition at line 328 of file chan_dahdi.c.

openr2_variant_t mfcr2_cur_variant = OR2_VAR_UNKNOWN [static]

Definition at line 322 of file chan_dahdi.c.

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

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

ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

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

Definition at line 254 of file chan_dahdi.c.

Referenced by __unload_module(), dahdi_restart(), do_monitor(), restart_monitor(), and unload_module().

char* name

Definition at line 2064 of file chan_dahdi.c.

int num_cadence = 4 [static]

Definition at line 1163 of file chan_dahdi.c.

int num_restart_pending = 0 [static]

Definition at line 263 of file chan_dahdi.c.

int numbufs = 4 [static]

Definition at line 221 of file chan_dahdi.c.

const char pri_debug_help[] [static]

Initial value:

 
   "Usage: pri debug span <span>\n"
   "       Enables debugging on a given PRI span\n"

Definition at line 11528 of file chan_dahdi.c.

const char pri_no_debug_help[] [static]

Initial value:

 
   "Usage: pri no debug span <span>\n"
   "       Disables debugging on a given PRI span\n"

Definition at line 11532 of file chan_dahdi.c.

const char pri_really_debug_help[] [static]

Initial value:

 
   "Usage: pri intensive debug span <span>\n"
   "       Enables debugging down to the Q.921 level\n"

Definition at line 11536 of file chan_dahdi.c.

const char pri_show_span_help[] [static]

Initial value:

 
   "Usage: pri show span <span>\n"
   "       Displays PRI Information on a given PRI span\n"

Definition at line 11540 of file chan_dahdi.c.

const char pri_show_spans_help[] [static]

Initial value:

 
   "Usage: pri show spans\n"
   "       Displays PRI Information\n"

Definition at line 11544 of file chan_dahdi.c.

int pridebugfd = -1 [static]

Definition at line 229 of file chan_dahdi.c.

ast_mutex_t pridebugfdlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Definition at line 249 of file chan_dahdi.c.

Referenced by dahdi_pri_error(), dahdi_pri_message(), handle_pri_set_debug_file(), and handle_pri_show_debug().

char pridebugfilename[1024] = "" [static]

Definition at line 230 of file chan_dahdi.c.

struct dahdi_pri pris[NUM_SPANS] [static]

Definition at line 408 of file chan_dahdi.c.

Referenced by __unload_module(), build_channels(), complete_span_helper(), dahdi_pri_error(), dahdi_pri_message(), dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), handle_pri_debug(), handle_pri_no_debug(), handle_pri_really_debug(), handle_pri_show_debug(), handle_pri_show_span(), handle_pri_show_spans(), load_module(), mkintf(), pri_create_spanmap(), pri_create_trunkgroup(), pri_find_principle(), pri_resolve_span(), setup_dahdi(), and unload_module().

char progzone[10] = "" [static]

Definition at line 217 of file chan_dahdi.c.

struct dahdi_mfcr2 r2links[NUM_SPANS] [static]

Definition at line 321 of file chan_dahdi.c.

Referenced by __unload_module(), build_channels(), dahdi_restart(), init_mfcr2_globals(), mfcr2_get_context(), and setup_dahdi().

ast_mutex_t restart_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Definition at line 261 of file chan_dahdi.c.

Referenced by dahdi_restart().

int ringt_base = DEFAULT_RINGT [static]

Configured ring timeout base.

Note:
Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.

Definition at line 310 of file chan_dahdi.c.

struct dahdi_pvt* round_robin[32]

Definition at line 1142 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 12423 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 12419 of file chan_dahdi.c.

ast_cond_t ss_thread_complete [static]

Definition at line 259 of file chan_dahdi.c.

int ss_thread_count = 0 [static]

Definition at line 262 of file chan_dahdi.c.

ast_mutex_t ss_thread_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Definition at line 260 of file chan_dahdi.c.

Referenced by dahdi_restart(), and ss_thread().

char* subnames[] [static]

Initial value:

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

Definition at line 448 of file chan_dahdi.c.

const char tdesc[] [static]

Definition at line 161 of file chan_dahdi.c.

int user_has_defined_cadences = 0 [static]

Definition at line 1164 of file chan_dahdi.c.

char* zap_accept_r2_call_app = "ZapAcceptR2Call" [static]

Definition at line 3432 of file chan_dahdi.c.

char* zap_accept_r2_call_descrip [static]

Initial value:

 
"  ZapAcceptR2Call(): This application will accept the current MFC/R2 call\n"
"  You can specify yes or no as argument to accept with or without charge.\n"

Definition at line 3441 of file chan_dahdi.c.

char* zap_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)" [static]

Definition at line 3435 of file chan_dahdi.c.

char* zap_send_keypad_facility_app = "ZapSendKeypadFacility" [static]

Definition at line 3288 of file chan_dahdi.c.

char* zap_send_keypad_facility_descrip [static]

Initial value:

 
"  ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
"  IE over the current channel.\n"

Definition at line 3296 of file chan_dahdi.c.

char* zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static]

Definition at line 3291 of file chan_dahdi.c.

struct ast_channel_tech zap_tech [static]

Definition at line 1113 of file chan_dahdi.c.

Referenced by load_module().


Generated on Tue Apr 6 15:45:45 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7