Fri Aug 13 18:21:12 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(), 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 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 12542 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 12572 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 12573 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 13969 of file chan_dahdi.c.

Referenced by load_module().

#define local_astman_unregister (  ) 

Definition at line 12793 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 12987 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_setoption(), 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_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_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(), mfcr2_monitor(), 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 14163 of file chan_dahdi.c.

#define TRAILER_MS   5

Referenced by dahdi_sendtext().

#define TRANSFER   0

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

12672 {
12673    struct dahdi_pvt *p = NULL;
12674    const char *channel = local_astman_header(m, "Channel", zap_mode);
12675    const char *number = astman_get_header(m, "Number");
12676    int i;
12677 
12678    if (ast_strlen_zero(channel)) {
12679       astman_send_error(s, m, "No channel specified");
12680       return 0;
12681    }
12682    if (ast_strlen_zero(number)) {
12683       astman_send_error(s, m, "No number specified");
12684       return 0;
12685    }
12686    if (!(p = find_channel(atoi(channel)))) {
12687       astman_send_error(s, m, "No such channel");
12688       return 0;
12689    }
12690    if (!p->owner) {
12691       astman_send_error(s, m, "Channel does not have an owner");
12692       return 0;
12693    }
12694    for (i = 0; i < strlen(number); i++) {
12695       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
12696 
12697       dahdi_queue_frame(p, &f, NULL); 
12698    }
12699    local_astman_ack(s, m, "DialOffHook", zap_mode);
12700 
12701    return 0;
12702 }

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

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

12576 {
12577    struct dahdi_pvt *p = NULL;
12578    const char *channel = local_astman_header(m, "Channel", zap_mode);
12579 
12580    if (ast_strlen_zero(channel)) {
12581       astman_send_error(s, m, "No channel specified");
12582       return 0;
12583    }
12584    if (!(p = find_channel(atoi(channel)))) {
12585       astman_send_error(s, m, "No such channel");
12586       return 0;
12587    }
12588    p->dnd = dnd;
12589    local_astman_ack(s, m, "DND", zap_mode);
12590 
12591    return 0;
12592 }

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

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

12770 {
12771    if (dahdi_restart() != 0) {
12772       if (zap_mode) {
12773          astman_send_error(s, m, "Failed to restart Zap");
12774       } else {
12775          astman_send_error(s, m, "Failed to restart DAHDI");
12776       }
12777       return 1;
12778    }
12779    local_astman_ack(s, m, "Restart: Success", zap_mode);
12780    return 0;
12781 }

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

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

12715 {
12716    struct dahdi_pvt *tmp = NULL;
12717    const char *id = astman_get_header(m, "ActionID");
12718    char idText[256] = "";
12719 
12720    local_astman_ack(s, m, " channel status will follow", zap_mode);
12721    if (!ast_strlen_zero(id))
12722       snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
12723 
12724    ast_mutex_lock(&iflock);
12725    
12726    tmp = iflist;
12727    while (tmp) {
12728       if (tmp->channel > 0) {
12729          int alarm = get_alarms(tmp);
12730          astman_append(s,
12731                   "Event: %sShowChannels\r\n"
12732                   "Channel: %d\r\n"
12733                   "Signalling: %s\r\n"
12734                   "Context: %s\r\n"
12735                   "DND: %s\r\n"
12736                   "Alarm: %s\r\n"
12737                   "%s"
12738                   "\r\n",
12739                   dahdi_chan_name,
12740                   tmp->channel, sig2str(tmp->sig), tmp->context, 
12741                   tmp->dnd ? "Enabled" : "Disabled",
12742                   alarm2str(alarm), idText);
12743       } 
12744 
12745       tmp = tmp->next;
12746    }
12747 
12748    ast_mutex_unlock(&iflock);
12749    
12750    astman_append(s, 
12751             "Event: %sShowChannelsComplete\r\n"
12752             "%s"
12753             "\r\n",
12754             dahdi_chan_name,
12755             idText);
12756    return 0;
12757 }

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

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

12615 {
12616    struct dahdi_pvt *p = NULL;
12617    const char *channel = local_astman_header(m, "Channel", zap_mode);
12618 
12619    if (ast_strlen_zero(channel)) {
12620       astman_send_error(s, m, "No channel specified");
12621       return 0;
12622    }
12623    if (!(p = find_channel(atoi(channel)))) {
12624       astman_send_error(s, m, "No such channel");
12625       return 0;
12626    }
12627    dahdi_fake_event(p,TRANSFER);
12628    local_astman_ack(s, m, "Transfer", zap_mode);
12629 
12630    return 0;
12631 }

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

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

12644 {
12645    struct dahdi_pvt *p = NULL;
12646    const char *channel = local_astman_header(m, "Channel", zap_mode);
12647 
12648    if (ast_strlen_zero(channel)) {
12649       astman_send_error(s, m, "No channel specified");
12650       return 0;
12651    }
12652    if (!(p = find_channel(atoi(channel)))) {
12653       astman_send_error(s, m, "No such channel");
12654       return 0;
12655    }
12656    dahdi_fake_event(p, HANGUP);
12657    local_astman_ack(s, m, "Hangup", zap_mode);
12658    return 0;
12659 }

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

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

static int __unload_module ( void   )  [static]

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

12801 {
12802    struct dahdi_pvt *p;
12803 #ifdef HAVE_OPENR2
12804    int r;
12805 #endif
12806 #ifdef HAVE_PRI
12807    int i, j;
12808    for (i = 0; i < NUM_SPANS; i++) {
12809       if (pris[i].master != AST_PTHREADT_NULL) 
12810          pthread_cancel(pris[i].master);
12811    }
12812    ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
12813 
12814    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12815       ast_unregister_application(dahdi_send_keypad_facility_app);
12816    }
12817    ast_unregister_application(zap_send_keypad_facility_app);
12818 #endif
12819 #ifdef HAVE_OPENR2
12820    for (r = 0; r < NUM_SPANS; r++) {
12821       if (r2links[r].master != AST_PTHREADT_NULL) {
12822          pthread_cancel(r2links[r].master);
12823          pthread_join(r2links[r].master, NULL);
12824       }
12825    }
12826    ast_cli_unregister_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli) / sizeof(dahdi_mfcr2_cli[0]));
12827    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12828       ast_unregister_application(dahdi_accept_r2_call_app);
12829    }
12830    ast_unregister_application(zap_accept_r2_call_app);
12831 #endif
12832    ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
12833    local_astman_unregister("DialOffHook");
12834    local_astman_unregister("Hangup");
12835    local_astman_unregister("Transfer");
12836    local_astman_unregister("DNDoff");
12837    local_astman_unregister("DNDon");
12838    local_astman_unregister("ShowChannels");
12839    local_astman_unregister("Restart");
12840    ast_channel_unregister(chan_tech);
12841    ast_mutex_lock(&iflock);
12842    /* Hangup all interfaces if they have an owner */
12843    p = iflist;
12844    while (p) {
12845       if (p->owner)
12846          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
12847       p = p->next;
12848    }
12849    ast_mutex_unlock(&iflock);
12850    ast_mutex_lock(&monlock);
12851    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12852       pthread_cancel(monitor_thread);
12853       pthread_kill(monitor_thread, SIGURG);
12854       pthread_join(monitor_thread, NULL);
12855    }
12856    monitor_thread = AST_PTHREADT_STOP;
12857    ast_mutex_unlock(&monlock);
12858 
12859    destroy_all_channels();
12860 #ifdef HAVE_PRI      
12861    for (i = 0; i < NUM_SPANS; i++) {
12862       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
12863          pthread_join(pris[i].master, NULL);
12864       for (j = 0; j < NUM_DCHANS; j++) {
12865          dahdi_close_pri_fd(&(pris[i]), j);
12866       }
12867    }
12868 #endif
12869 #ifdef HAVE_OPENR2
12870    for (r = 0; r < NUM_SPANS; r++) {
12871       if (r2links[r].protocol_context) {
12872          openr2_context_delete(r2links[r].protocol_context);
12873       }
12874    }
12875 #endif
12876    ast_cond_destroy(&ss_thread_complete);
12877    return 0;
12878 }

static void __unreg_module ( void   )  [static]

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

10046 {
10047    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
10048       if (size) {
10049          *buf = '\0';
10050       }
10051       return;
10052    }
10053 
10054    switch (plan) {
10055    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
10056       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
10057       break;
10058    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
10059       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
10060       break;
10061    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
10062       snprintf(buf, size, "%s%s", pri->localprefix, number);
10063       break;
10064    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
10065       snprintf(buf, size, "%s%s", pri->privateprefix, number);
10066       break;
10067    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
10068       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
10069       break;
10070    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
10071       snprintf(buf, size, "%s", number);
10072       break;
10073    }
10074 }

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

09195 {
09196    int res;
09197    struct dahdi_params par;
09198 
09199    /* First, check group matching */
09200    if (groupmatch) {
09201       if ((p->group & groupmatch) != groupmatch)
09202          return 0;
09203       *groupmatched = 1;
09204    }
09205    /* Check to see if we have a channel match */
09206    if (channelmatch != -1) {
09207       if (p->channel != channelmatch)
09208          return 0;
09209       *channelmatched = 1;
09210    }
09211    /* We're at least busy at this point */
09212    if (busy) {
09213       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
09214          *busy = 1;
09215    }
09216    /* If do not disturb, definitely not */
09217    if (p->dnd)
09218       return 0;
09219    /* If guard time, definitely not */
09220    if (p->guardtime && (time(NULL) < p->guardtime)) 
09221       return 0;
09222       
09223    /* If no owner definitely available */
09224    if (!p->owner) {
09225 #ifdef HAVE_PRI
09226       /* Trust PRI */
09227       if (p->pri) {
09228          if (p->resetting || p->call)
09229             return 0;
09230          else
09231             return 1;
09232       }
09233 #endif
09234 #ifdef HAVE_OPENR2
09235       /* Trust MFC/R2 */
09236       if (p->mfcr2) {
09237          if (p->mfcr2call || p->mfcr2block)
09238             return 0;
09239          else
09240             return 1;
09241       }
09242 #endif
09243       if (!(p->radio || (p->oprmode < 0)))
09244       {
09245          if (!p->sig || (p->sig == SIG_FXSLS))
09246             return 1;
09247          /* Check hook state */
09248          if (p->subs[SUB_REAL].dfd > -1) {
09249             memset(&par, 0, sizeof(par));
09250             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
09251          } else {
09252             /* Assume not off hook on CVRS */
09253             res = 0;
09254             par.rxisoffhook = 0;
09255          }
09256          if (res) {
09257             ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
09258          } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
09259             /* When "onhook" that means no battery on the line, and thus
09260               it is out of service..., if it's on a TDM card... If it's a channel
09261               bank, there is no telling... */
09262             if (par.rxbits > -1)
09263                return 1;
09264             if (par.rxisoffhook)
09265                return 1;
09266             else
09267 #ifdef DAHDI_CHECK_HOOKSTATE
09268                return 0;
09269 #else
09270                return 1;
09271 #endif
09272          } else if (par.rxisoffhook) {
09273             ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
09274             /* Not available when the other end is off hook */
09275             return 0;
09276          }
09277       }
09278       return 1;
09279    }
09280 
09281    /* If it's not an FXO, forget about call wait */
09282    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 
09283       return 0;
09284 
09285    if (!p->callwaiting) {
09286       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
09287       return 0;
09288    }
09289 
09290    if (p->subs[SUB_CALLWAIT].dfd > -1) {
09291       /* If there is already a call waiting call, then we can't take a second one */
09292       return 0;
09293    }
09294    
09295    if ((p->owner->_state != AST_STATE_UP) &&
09296        ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
09297       /* If the current call is not up, then don't allow the call */
09298       return 0;
09299    }
09300    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
09301       /* Can't take a call wait when the three way calling hasn't been merged yet. */
09302       return 0;
09303    }
09304    /* We're cool */
09305    return 1;
09306 }

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

12891 {
12892    char *c, *chan;
12893    int x, start, finish;
12894    struct dahdi_pvt *tmp;
12895 #ifdef HAVE_PRI
12896    struct dahdi_pri *pri;
12897    int trunkgroup, y;
12898 #endif
12899    
12900    if ((reload == 0) && (conf->chan.sig < 0)) {
12901       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
12902       return -1;
12903    }
12904 
12905    c = ast_strdupa(value);
12906 
12907 #ifdef HAVE_PRI
12908    pri = NULL;
12909    if (iscrv) {
12910       if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
12911          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
12912          return -1;
12913       }
12914       if (trunkgroup < 1) {
12915          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
12916          return -1;
12917       }
12918       c += y;
12919       for (y = 0; y < NUM_SPANS; y++) {
12920          if (pris[y].trunkgroup == trunkgroup) {
12921             pri = pris + y;
12922             break;
12923          }
12924       }
12925       if (!pri) {
12926          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
12927          return -1;
12928       }
12929    }
12930 #endif         
12931 
12932    while ((chan = strsep(&c, ","))) {
12933       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
12934          /* Range */
12935       } else if (sscanf(chan, "%30d", &start)) {
12936          /* Just one */
12937          finish = start;
12938       } else if (!strcasecmp(chan, "pseudo")) {
12939          finish = start = CHAN_PSEUDO;
12940          if (found_pseudo)
12941             *found_pseudo = 1;
12942       } else {
12943          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
12944          return -1;
12945       }
12946       if (finish < start) {
12947          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
12948          x = finish;
12949          finish = start;
12950          start = x;
12951       }
12952 
12953       for (x = start; x <= finish; x++) {
12954 #ifdef HAVE_PRI
12955          tmp = mkintf(x, conf, pri, reload);
12956 #else       
12957          tmp = mkintf(x, conf, NULL, reload);
12958 #endif         
12959 
12960          if (tmp) {
12961             if (option_verbose > 2) {
12962 #ifdef HAVE_PRI
12963                if (pri)
12964                   ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
12965                else
12966 #endif
12967                   ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
12968             }
12969          } else {
12970             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
12971                (reload == 1) ? "reconfigure" : "register", value);
12972             return -1;
12973          }
12974       }
12975 #ifdef HAVE_OPENR2
12976       if (reload != 1 && r2links[mfcr2_cur_context_index].protocol_context) {
12977          mfcr2_cur_context_index++;
12978       }  
12979 #endif
12980    }
12981 
12982    return 0;
12983 }

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

Definition at line 11460 of file chan_dahdi.c.

References DCHAN_NOTINALARM, and DCHAN_PROVISIONED.

Referenced by handle_pri_show_span(), and handle_pri_show_spans().

11461 {
11462    if (!s || len < 1) {
11463       return;
11464    }
11465    s[0] = '\0';
11466    if (status & DCHAN_PROVISIONED)
11467       strncat(s, "Provisioned, ", len - strlen(s) - 1);
11468    if (!(status & DCHAN_NOTINALARM))
11469       strncat(s, "In Alarm, ", len - strlen(s) - 1);
11470    if (status & DCHAN_UP)
11471       strncat(s, "Up", len - strlen(s) - 1);
11472    else
11473       strncat(s, "Down", len - strlen(s) - 1);
11474    if (active)
11475       strncat(s, ", Active", len - strlen(s) - 1);
11476    else
11477       strncat(s, ", Standby", len - strlen(s) - 1);
11478    s[len - 1] = '\0';
11479 }

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

References AST_ALAW, AST_FORMAT_ULAW, ast_log(), AST_MULAW, and option_verbose.

07948 {
07949    int x;
07950    int sum = 0;
07951    int ssum = 0, mean = 0;
07952 
07953    if (!len)
07954       return 0;
07955 
07956    /* First calc mean signal (DC offset) */
07957    for (x = 0; x < len; x++)
07958          ssum += (law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
07959 
07960    mean = ssum / len;   
07961 
07962    for (x = 0; x < len; x++) {
07963          sum += abs((law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x])) - mean);
07964       if (option_verbose > 7)
07965             ast_log(LOG_WARNING, "x %i, bufx: %i sum %i, ssum %i\n", x, buf[x], sum, ssum);
07966    }
07967 
07968    if (option_verbose > 5)
07969          ast_log(LOG_WARNING, "mean %i, energy %i\n", mean, sum/len);
07970 
07971    return sum / len;
07972 }

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

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

09309 {
09310    struct dahdi_pvt *p;
09311    struct dahdi_bufferinfo bi;
09312    int res;
09313    
09314    if ((p = ast_malloc(sizeof(*p)))) {
09315       memcpy(p, src, sizeof(struct dahdi_pvt));
09316       ast_mutex_init(&p->lock);
09317       p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
09318       /* Allocate a DAHDI structure */
09319       if (p->subs[SUB_REAL].dfd < 0) {
09320          ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
09321          destroy_dahdi_pvt(&p);
09322          return NULL;
09323       }
09324       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09325       if (!res) {
09326          bi.txbufpolicy = p->buf_policy;
09327          bi.rxbufpolicy = p->buf_policy;
09328          bi.numbufs = p->buf_no;
09329          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09330          if (res < 0) {
09331             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09332          }
09333       } else
09334          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09335    }
09336    p->destroy = 1;
09337    p->next = iflist;
09338    p->prev = NULL;
09339    iflist = p;
09340    if (iflist->next)
09341       iflist->next->prev = p;
09342    return p;
09343 }

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

References complete_span_helper().

11328 {
11329    return complete_span_helper(line,word,pos,state,3);
11330 }

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

Definition at line 11332 of file chan_dahdi.c.

References complete_span_helper().

11333 {
11334    return complete_span_helper(line,word,pos,state,4);
11335 }

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

Definition at line 11308 of file chan_dahdi.c.

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

Referenced by complete_span_4(), and complete_span_5().

11309 {
11310    int which, span;
11311    char *ret = NULL;
11312 
11313    if (pos != rpos)
11314       return ret;
11315 
11316    for (which = span = 0; span < NUM_SPANS; span++) {
11317       if (pris[span].pri && ++which > state) {
11318          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
11319             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
11320          }
11321          break;
11322       }
11323    }
11324    return ret;
11325 }

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

References __action_dialoffhook(), and s.

12710 {
12711    return __action_dialoffhook(s, m, 0);
12712 }

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

Definition at line 12609 of file chan_dahdi.c.

References __action_dnd(), and s.

12610 {
12611    return __action_dnd(s, m, 0, 0);
12612 }

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

Definition at line 12599 of file chan_dahdi.c.

References __action_dnd(), and s.

12600 {
12601    return __action_dnd(s, m, 0, 1);
12602 }

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

Definition at line 12788 of file chan_dahdi.c.

References __action_restart(), and s.

12789 {
12790    return __action_restart(s, m, 0);
12791 }

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

Definition at line 12764 of file chan_dahdi.c.

References __action_showchannels(), and s.

12765 {
12766    return __action_showchannels(s, m, 0);
12767 }

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

Definition at line 12638 of file chan_dahdi.c.

References __action_transfer(), and s.

12639 {
12640    return __action_transfer(s, m, 0);
12641 }

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

Definition at line 12666 of file chan_dahdi.c.

References __action_transferhangup(), and s.

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

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

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

References dahdi_destroy_channel_bynum(), and RESULT_SHOWUSAGE.

11965 {
11966    int channel;
11967    
11968    if (argc != 4)
11969       return RESULT_SHOWUSAGE;
11970    
11971    channel = atoi(argv[3]);
11972 
11973    return dahdi_destroy_channel_bynum(channel);
11974 }

static int dahdi_destroy_channel_bynum ( int  channel  )  [static]

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

07976 {
07977    struct dahdi_pvt *tmp = NULL;
07978    struct dahdi_pvt *prev = NULL;
07979 
07980    ast_mutex_lock(&iflock);
07981    tmp = iflist;
07982    while (tmp) {
07983       if (tmp->channel == channel) {
07984          int x = DAHDI_FLASH;
07985          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 */
07986          destroy_channel(prev, tmp, 1);
07987          ast_mutex_unlock(&iflock);
07988          ast_module_unref(ast_module_info->self);
07989          return RESULT_SUCCESS;
07990       }
07991       prev = tmp;
07992       tmp = tmp->next;
07993    }
07994    ast_mutex_unlock(&iflock);
07995    return RESULT_FAILURE;
07996 }

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

12545 {
12546    if (p) {
12547       switch (mode) {
12548          case TRANSFER:
12549             p->fake_event = DAHDI_EVENT_WINKFLASH;
12550             break;
12551          case HANGUP:
12552             p->fake_event = DAHDI_EVENT_ONHOOK;
12553             break;
12554          default:
12555             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
12556       }
12557    }
12558    return 0;
12559 }

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

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 6365 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.

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

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

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

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

09945 {
09946    int x, y;
09947    int dchan = -1, span = -1;
09948    int dchancount = 0;
09949 
09950    if (pri) {
09951       for (x = 0; x < NUM_SPANS; x++) {
09952          for (y = 0; y < NUM_DCHANS; y++) {
09953             if (pris[x].dchans[y])
09954                dchancount++;
09955 
09956             if (pris[x].dchans[y] == pri)
09957                dchan = y;
09958          }
09959          if (dchan >= 0) {
09960             span = x;
09961             break;
09962          }
09963          dchancount = 0;
09964       }
09965       if ((dchan >= 0) && (span >= 0)) {
09966          if (dchancount > 1)
09967             ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
09968          else
09969             ast_log(LOG_ERROR, "%s", s);
09970       } else
09971          ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
09972    } else
09973       ast_log(LOG_ERROR, "%s", s);
09974 
09975    ast_mutex_lock(&pridebugfdlock);
09976 
09977    if (pridebugfd >= 0) {
09978       if (write(pridebugfd, s, strlen(s)) < 0) {
09979          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
09980       }
09981    }
09982 
09983    ast_mutex_unlock(&pridebugfdlock);
09984 }

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

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

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

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 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_FLAG_BLOCKING, AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_NULL, AST_FRIENDLY_OFFSET, ast_getformatname(), AST_LIN2MU, ast_log(), AST_MULAW, ast_mutex_trylock(), ast_mutex_unlock(), ast_set_callerid(), ast_setstate(), AST_STATE_PRERING, AST_STATE_RINGING, ast_tv(), dahdi_subchannel::buffer, dahdi_pvt::channel, CHECK_BLOCKING, dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, CID_START_POLARITY, dahdi_get_index(), dahdi_setlinear(), ast_frame::data, ast_frame::datalen, DEADLOCK_AVOIDANCE, ast_frame::delivery, dahdi_subchannel::dfd, dahdi_subchannel::f, f, dahdi_pvt::firstradio, ast_frame::frametype, dahdi_pvt::inalarm, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_subchannel::linear, ast_channel::lock, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, 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::r2chan, dahdi_pvt::radio, ast_channel::rawreadformat, READ_SIZE, dahdi_pvt::ringt, S_OR, ast_frame::samples, ast_frame::src, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, and dahdi_pvt::use_callerid.

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 
06099       if (p->use_callerid && (ast->_state == AST_STATE_PRERING &&
06100                    (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_DTMF_NOALERT))) {
06101          //ast_log(LOG_NOTICE, "use_callerid %u, cid_start %i\n", p->use_callerid, p->cid_start);
06102          if (!p->subs[index].linear) {
06103                int x, samplin;
06104                int mean, ssum;
06105                
06106                /* First calc mean signal (DC offset) */
06107                for (x = 0, ssum = 0; x < READ_SIZE; x++) {
06108                      //ssum += (ast->rawreadformat == AST_FORMAT_ULAW ? AST_MULAW((u_char *)readbuf) : AST_ALAW((u_char *)readbuf[x]));
06109                      ssum += AST_MULAW(((u_char *)readbuf)[x]);
06110                      if (option_verbose > 5 && (x % 10 == 0))
06111                            ast_log(LOG_NOTICE, "dahdi_read ssum %i, mean %i \n", ssum, ssum / READ_SIZE);
06112                }
06113                mean = ssum / READ_SIZE;
06114 
06115                if (option_verbose > 5)
06116                      ast_log(LOG_WARNING, "dahdi_read channel %s, mean %i \n", ast->name, mean);
06117                if (ast->rawreadformat == AST_FORMAT_ULAW) {
06118                      for (x = 0; x < READ_SIZE; x++) {
06119                            samplin = AST_MULAW(((u_char *)readbuf)[x]);
06120                            if (option_verbose > 6 && (x % 10 == 0))
06121                                  ast_log(LOG_NOTICE, "dahdi_read,x %i, samporig %i samplin %i, samplinconv %i, xconv %i\n", x, ((u_char *)readbuf)[x], samplin, samplin - mean, AST_LIN2MU(samplin - mean));
06122                            ((u_char *)readbuf)[x] = AST_LIN2MU(samplin - mean);
06123                      }
06124                }
06125          }
06126       }
06127 
06128    /* Check for hangup */
06129    if (res < 0) {
06130       f = NULL;
06131       if (res == -1)  {
06132          if (errno == EAGAIN) {
06133             /* Return "NULL" frame if there is nobody there */
06134             ast_mutex_unlock(&p->lock);
06135             return &p->subs[index].f;
06136          } else if (errno == ELAST) {
06137             f = __dahdi_exception(ast);
06138          } else
06139             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
06140       }
06141       ast_mutex_unlock(&p->lock);
06142       return f;
06143    }
06144    if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
06145       ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
06146       f = __dahdi_exception(ast);
06147       ast_mutex_unlock(&p->lock);
06148       return f;
06149    }
06150    if (p->tdd) { /* if in TDD mode, see if we receive that */
06151       int c;
06152 
06153       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
06154       if (c < 0) {
06155          ast_log(LOG_DEBUG,"tdd_feed failed\n");
06156          ast_mutex_unlock(&p->lock);
06157          return NULL;
06158       }
06159       if (c) { /* if a char to return */
06160          p->subs[index].f.subclass = 0;
06161          p->subs[index].f.frametype = AST_FRAME_TEXT;
06162          p->subs[index].f.mallocd = 0;
06163          p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
06164          p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
06165          p->subs[index].f.datalen = 1;
06166          *((char *) p->subs[index].f.data) = c;
06167          ast_mutex_unlock(&p->lock);
06168          return &p->subs[index].f;
06169       }
06170    }
06171    /* Ensure the CW timer decrements only on a single subchannel */
06172    if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
06173       p->callwaitingrepeat--;
06174    }
06175    if (p->cidcwexpire)
06176       p->cidcwexpire--;
06177    /* Repeat callwaiting */
06178    if (p->callwaitingrepeat == 1) {
06179       p->callwaitrings++;
06180       dahdi_callwait(ast);
06181    }
06182    /* Expire CID/CW */
06183    if (p->cidcwexpire == 1) {
06184       if (option_verbose > 2)
06185          ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
06186       restore_conference(p);
06187    }
06188    if (p->subs[index].linear) {
06189       p->subs[index].f.datalen = READ_SIZE * 2;
06190    } else 
06191       p->subs[index].f.datalen = READ_SIZE;
06192 
06193    /* Handle CallerID Transmission */
06194    if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
06195       send_callerid(p);
06196    }
06197 
06198    p->subs[index].f.frametype = AST_FRAME_VOICE;
06199    p->subs[index].f.subclass = ast->rawreadformat;
06200    p->subs[index].f.samples = READ_SIZE;
06201    p->subs[index].f.mallocd = 0;
06202    p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
06203    p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
06204 #if 0
06205    ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
06206 #endif   
06207    if (p->dialing || /* Transmitting something */
06208       (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
06209       ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
06210       ) {
06211       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
06212          don't send anything */
06213       p->subs[index].f.frametype = AST_FRAME_NULL;
06214       p->subs[index].f.subclass = 0;
06215       p->subs[index].f.samples = 0;
06216       p->subs[index].f.mallocd = 0;
06217       p->subs[index].f.offset = 0;
06218       p->subs[index].f.data = NULL;
06219       p->subs[index].f.datalen= 0;
06220    }
06221    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect  || p->callprogress) && !index) {
06222       /* Perform busy detection. etc on the dahdi line */
06223       f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
06224       if (f) {
06225          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
06226             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
06227                /* Treat this as a "hangup" instead of a "busy" on the assumption that
06228                   a busy  */
06229                f = NULL;
06230             }
06231          } else if (f->frametype == AST_FRAME_DTMF) {
06232 #ifdef HAVE_PRI
06233             if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial &&
06234                ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
06235                (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
06236                /* Don't accept in-band DTMF when in overlap dial mode */
06237                f->frametype = AST_FRAME_NULL;
06238                f->subclass = 0;
06239             }
06240 #endif            
06241             /* DSP clears us of being pulse */
06242             p->pulsedial = 0;
06243          }
06244       }
06245    } else 
06246       f = &p->subs[index].f; 
06247 
06248    if (f && (f->frametype == AST_FRAME_DTMF))
06249       dahdi_handle_dtmfup(ast, index, &f);
06250 
06251    /* If we have a fake_event, trigger exception to handle it */
06252    if (p->fake_event)
06253       ast_set_flag(ast, AST_FLAG_EXCEPTION);
06254 
06255    ast_mutex_unlock(&p->lock);
06256    return f;
06257 }

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

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

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

static int dahdi_restart ( void   )  [static]

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

12006 {
12007 #ifdef HAVE_OPENR2
12008    int r;
12009 #endif
12010 #if defined(HAVE_PRI)
12011    int i, j;
12012 #endif
12013    int cancel_code;
12014    struct dahdi_pvt *p;
12015 
12016    ast_mutex_lock(&restart_lock);
12017  
12018    if (option_verbose)
12019       ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
12020    dahdi_softhangup_all();
12021    if (option_verbose > 3)
12022       ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
12023 
12024 #ifdef HAVE_OPENR2
12025    for (r = 0; r < NUM_SPANS; r++) {
12026       if (r2links[r].master != AST_PTHREADT_NULL) {
12027          ast_log(LOG_DEBUG, "Killing MFC/R2 monitor thread %p\n", &r2links[r].master);
12028          pthread_cancel(r2links[r].master);
12029          pthread_join(r2links[r].master, NULL);
12030          openr2_context_delete(r2links[r].protocol_context);
12031       }
12032    }
12033    init_mfcr2_globals();
12034 #endif
12035 
12036    #if defined(HAVE_PRI)
12037    for (i = 0; i < NUM_SPANS; i++) {
12038       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
12039          cancel_code = pthread_cancel(pris[i].master);
12040          pthread_kill(pris[i].master, SIGURG);
12041          if (option_debug > 3)
12042             ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
12043             pthread_join(pris[i].master, NULL);
12044          if (option_debug > 3)
12045             ast_verbose("Joined thread of span %d\n", i);
12046       }
12047     }
12048    #endif
12049 
12050     ast_mutex_lock(&monlock);
12051     if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12052       cancel_code = pthread_cancel(monitor_thread);
12053       pthread_kill(monitor_thread, SIGURG);
12054       if (option_debug > 3)
12055          ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
12056         pthread_join(monitor_thread, NULL);
12057       if (option_debug > 3)
12058          ast_verbose("Joined monitor thread\n");
12059     }
12060    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
12061 
12062    ast_mutex_lock(&ss_thread_lock);
12063    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
12064       int x = DAHDI_FLASH;
12065       if (option_debug > 2)
12066          ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
12067 
12068       for (p = iflist; p; p = p->next) {
12069          if (p->owner)
12070             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 */    
12071       }
12072       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
12073    }
12074 
12075    /* ensure any created channels before monitor threads were stopped are hungup */
12076    dahdi_softhangup_all();
12077    if (option_verbose > 3)
12078       ast_verbose("Final softhangup of all DAHDI channels complete.\n");
12079    destroy_all_channels();
12080    if (option_debug)
12081       ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
12082 
12083     ast_mutex_unlock(&monlock);
12084 
12085    #ifdef HAVE_PRI
12086    for (i = 0; i < NUM_SPANS; i++) {
12087       for (j = 0; j < NUM_DCHANS; j++)
12088             dahdi_close_pri_fd(&(pris[i]), j);
12089    }
12090 
12091    memset(pris, 0, sizeof(pris));
12092    for (i = 0; i < NUM_SPANS; i++) {
12093       ast_mutex_init(&pris[i].lock);
12094       pris[i].offset = -1;
12095       pris[i].master = AST_PTHREADT_NULL;
12096       for (j = 0; j < NUM_DCHANS; j++)
12097          pris[i].fds[j] = -1;
12098    }
12099    pri_set_error(dahdi_pri_error);
12100    pri_set_message(dahdi_pri_message);
12101    #endif
12102 
12103    if (setup_dahdi(2) != 0) {
12104       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
12105       ast_mutex_unlock(&ss_thread_lock);
12106       return 1;
12107    }
12108    ast_mutex_unlock(&ss_thread_lock);
12109    ast_mutex_unlock(&restart_lock);
12110    return 0;
12111 }

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

Definition at line 12113 of file chan_dahdi.c.

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

12114 {
12115    if (argc != 2) {
12116       return RESULT_SHOWUSAGE;
12117    }
12118 
12119    if (dahdi_restart() != 0)
12120       return RESULT_FAILURE;
12121    return RESULT_SUCCESS;
12122 }

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 14045 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, dahdi_pvt::subs, dahdi_pvt::tdd, TDD_BYTES_PER_CHAR, tdd_generate(), ast_channel::tech_pvt, and TRAILER_MS.

14046 {
14047 #define  END_SILENCE_LEN 400
14048 #define  HEADER_MS 50
14049 #define  TRAILER_MS 5
14050 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
14051 #define  ASCII_BYTES_PER_CHAR 80
14052 
14053    unsigned char *buf,*mybuf;
14054    struct dahdi_pvt *p = c->tech_pvt;
14055    struct pollfd fds[1];
14056    int size,res,fd,len,x;
14057    int bytes=0;
14058    /* Initial carrier (imaginary) */
14059    float cr = 1.0;
14060    float ci = 0.0;
14061    float scont = 0.0;
14062    int index;
14063 
14064    index = dahdi_get_index(c, p, 0);
14065    if (index < 0) {
14066       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
14067       return -1;
14068    }
14069    if (!text[0]) return(0); /* if nothing to send, dont */
14070    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
14071    if (p->mate) 
14072       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
14073    else
14074       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
14075    if (!buf)
14076       return -1;
14077    mybuf = buf;
14078    if (p->mate) {
14079       int codec = AST_LAW(p);
14080       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
14081          PUT_CLID_MARKMS;
14082       }
14083       /* Put actual message */
14084       for (x = 0; text[x]; x++) {
14085          PUT_CLID(text[x]);
14086       }
14087       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
14088          PUT_CLID_MARKMS;
14089       }
14090       len = bytes;
14091       buf = mybuf;
14092    } else {
14093       len = tdd_generate(p->tdd, buf, text);
14094       if (len < 1) {
14095          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
14096          free(mybuf);
14097          return -1;
14098       }
14099    }
14100    memset(buf + len, 0x7f, END_SILENCE_LEN);
14101    len += END_SILENCE_LEN;
14102    fd = p->subs[index].dfd;
14103    while (len) {
14104       if (ast_check_hangup(c)) {
14105          free(mybuf);
14106          return -1;
14107       }
14108       size = len;
14109       if (size > READ_SIZE)
14110          size = READ_SIZE;
14111       fds[0].fd = fd;
14112       fds[0].events = POLLOUT | POLLPRI;
14113       fds[0].revents = 0;
14114       res = poll(fds, 1, -1);
14115       if (!res) {
14116          ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
14117          continue;
14118       }
14119         /* if got exception */
14120       if (fds[0].revents & POLLPRI) {
14121          ast_free(mybuf);
14122          return -1;
14123       }
14124       if (!(fds[0].revents & POLLOUT)) {
14125          ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
14126          continue;
14127       }
14128       res = write(fd, buf, size);
14129       if (res != size) {
14130          if (res == -1) {
14131             free(mybuf);
14132             return -1;
14133          }
14134          if (option_debug)
14135             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
14136          break;
14137       }
14138       len -= size;
14139       buf += size;
14140    }
14141    free(mybuf);
14142    return(0);
14143 }

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

10077 {
10078    int res;
10079    res = ioctl(dfd, DAHDI_SETLAW, &law);
10080    if (res)
10081       return res;
10082    return 0;
10083 }

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 12185 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.

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

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

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

12125 {
12126 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
12127 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
12128    struct dahdi_pvt *tmp = NULL;
12129    char tmps[20] = "";
12130    ast_mutex_t *lock;
12131    struct dahdi_pvt *start;
12132 #ifdef HAVE_PRI
12133    int trunkgroup;
12134    struct dahdi_pri *pri = NULL;
12135    int x;
12136 #endif
12137 
12138    lock = &iflock;
12139    start = iflist;
12140 
12141 #ifdef HAVE_PRI
12142    if (argc == 4) {
12143       if ((trunkgroup = atoi(argv[3])) < 1)
12144          return RESULT_SHOWUSAGE;
12145       for (x = 0; x < NUM_SPANS; x++) {
12146          if (pris[x].trunkgroup == trunkgroup) {
12147             pri = pris + x;
12148             break;
12149          }
12150       }
12151       if (pri) {
12152          start = pri->crvs;
12153          lock = &pri->lock;
12154       } else {
12155          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
12156          return RESULT_FAILURE;
12157       }
12158    } else
12159 #endif
12160    if (argc != 3)
12161       return RESULT_SHOWUSAGE;
12162 
12163    ast_mutex_lock(lock);
12164 #ifdef HAVE_PRI
12165    ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
12166 #else
12167    ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
12168 #endif   
12169    
12170    tmp = start;
12171    while (tmp) {
12172       if (tmp->channel > 0) {
12173          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
12174       } else
12175          ast_copy_string(tmps, "pseudo", sizeof(tmps));
12176       ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
12177       tmp = tmp->next;
12178    }
12179    ast_mutex_unlock(lock);
12180    return RESULT_SUCCESS;
12181 #undef FORMAT
12182 #undef FORMAT2
12183 }

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

Definition at line 12402 of file chan_dahdi.c.

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

12402                                                              {
12403    #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
12404    #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
12405 
12406    int span;
12407    int res;
12408    char alarms[50];
12409 
12410    int ctl;
12411    struct dahdi_spaninfo s;
12412 
12413    if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) {
12414       ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno));
12415       ast_cli(fd, "No " DAHDI_NAME " interface found.\n");
12416       return RESULT_FAILURE;
12417    }
12418    ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
12419 
12420    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
12421       s.spanno = span;
12422       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
12423       if (res) {
12424          continue;
12425       }
12426       alarms[0] = '\0';
12427       if (s.alarms > 0) {
12428          if (s.alarms & DAHDI_ALARM_BLUE)
12429             strcat(alarms, "BLU/");
12430          if (s.alarms & DAHDI_ALARM_YELLOW)
12431             strcat(alarms, "YEL/");
12432          if (s.alarms & DAHDI_ALARM_RED)
12433             strcat(alarms, "RED/");
12434          if (s.alarms & DAHDI_ALARM_LOOPBACK)
12435             strcat(alarms, "LB/");
12436          if (s.alarms & DAHDI_ALARM_RECOVER)
12437             strcat(alarms, "REC/");
12438          if (s.alarms & DAHDI_ALARM_NOTOPEN)
12439             strcat(alarms, "NOP/");
12440          if (!strlen(alarms))
12441             strcat(alarms, "UUU/");
12442          if (strlen(alarms)) {
12443             /* Strip trailing / */
12444             alarms[strlen(alarms) - 1] = '\0';
12445          }
12446       } else {
12447          if (s.numchans)
12448             strcpy(alarms, "OK");
12449          else
12450             strcpy(alarms, "UNCONFIGURED");
12451       }
12452 
12453       ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
12454    }
12455    close(ctl);
12456 
12457    return RESULT_SUCCESS;
12458 #undef FORMAT
12459 #undef FORMAT2
12460 }

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

11977 {
11978    struct dahdi_pvt *p;
11979 retry:
11980    ast_mutex_lock(&iflock);
11981     for (p = iflist; p; p = p->next) {
11982       ast_mutex_lock(&p->lock);
11983         if (p->owner && !p->restartpending) {
11984          if (ast_channel_trylock(p->owner)) {
11985             if (option_debug > 2)
11986                ast_verbose("Avoiding deadlock\n");
11987             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
11988             ast_mutex_unlock(&p->lock);
11989             ast_mutex_unlock(&iflock);
11990             goto retry;
11991          }
11992          if (option_debug > 2)
11993             ast_verbose("Softhanging up on %s\n", p->owner->name);
11994          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
11995          p->restartpending = 1;
11996          num_restart_pending++;
11997          ast_channel_unlock(p->owner);
11998       }
11999       ast_mutex_unlock(&p->lock);
12000     }
12001    ast_mutex_unlock(&iflock);
12002 }

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

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

Referenced by ss_thread().

06770 {
06771    int j;
06772    dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
06773    for (;;)
06774    {
06775          /* set bits of interest */
06776       j = DAHDI_IOMUX_SIGEVENT;
06777           /* wait for some happening */
06778       if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
06779          /* exit loop if we have it */
06780       if (j & DAHDI_IOMUX_SIGEVENT) break;
06781    }
06782      /* get the event info */
06783    if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
06784    return 0;
06785 }

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

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

06283 {
06284    struct dahdi_pvt *p = ast->tech_pvt;
06285    int res;
06286    int index;
06287    index = dahdi_get_index(ast, p, 0);
06288    if (index < 0) {
06289       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
06290       return -1;
06291    }
06292 
06293 #if 0
06294 #ifdef HAVE_PRI
06295    ast_mutex_lock(&p->lock);
06296    if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06297       if (p->pri->pri) {      
06298          if (!pri_grab(p, p->pri)) {
06299                pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06300                pri_rel(p->pri);
06301          } else
06302                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06303       }
06304       p->proceeding=1;
06305    }
06306    ast_mutex_unlock(&p->lock);
06307 #endif
06308 #endif
06309    /* Write a frame of (presumably voice) data */
06310    if (frame->frametype != AST_FRAME_VOICE) {
06311       if (frame->frametype != AST_FRAME_IMAGE)
06312          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
06313       return 0;
06314    }
06315    if ((frame->subclass != AST_FORMAT_SLINEAR) && 
06316        (frame->subclass != AST_FORMAT_ULAW) &&
06317        (frame->subclass != AST_FORMAT_ALAW)) {
06318       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
06319       return -1;
06320    }
06321    if (p->dialing) {
06322       if (option_debug)
06323          ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
06324       return 0;
06325    }
06326    if (!p->owner) {
06327       if (option_debug)
06328          ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
06329       return 0;
06330    }
06331    if (p->cidspill) {
06332       if (option_debug)
06333          ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
06334       return 0;
06335    }
06336    /* Return if it's not valid data */
06337    if (!frame->data || !frame->datalen)
06338       return 0;
06339 
06340    if (frame->subclass == AST_FORMAT_SLINEAR) {
06341       if (!p->subs[index].linear) {
06342          p->subs[index].linear = 1;
06343          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06344          if (res)
06345             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
06346       }
06347       res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
06348    } else {
06349       /* x-law already */
06350       if (p->subs[index].linear) {
06351          p->subs[index].linear = 0;
06352          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06353          if (res)
06354             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
06355       }
06356       res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
06357    }
06358    if (res < 0) {
06359       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
06360       return -1;
06361    } 
06362    return 0;
06363 }

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

09848 {
09849    struct ast_channel *chan = vchan;
09850    struct dahdi_pvt *pvt = chan->tech_pvt;
09851    struct ast_frame *f;
09852    char ex[80];
09853    /* Wait up to 30 seconds for an answer */
09854    int newms, ms = 30000;
09855    if (option_verbose > 2) 
09856       ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
09857    snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
09858    if (ast_call(chan, ex, 0)) {
09859       ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
09860       ast_hangup(chan);
09861       return NULL;
09862    }
09863    while ((newms = ast_waitfor(chan, ms)) > 0) {
09864       f = ast_read(chan);
09865       if (!f) {
09866          /* Got hangup */
09867          break;
09868       }
09869       if (f->frametype == AST_FRAME_CONTROL) {
09870          switch (f->subclass) {
09871          case AST_CONTROL_ANSWER:
09872             /* Launch the PBX */
09873             ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
09874             ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
09875             chan->priority = 1;
09876             if (option_verbose > 3) 
09877                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
09878             ast_pbx_run(chan);
09879             /* It's already hungup, return immediately */
09880             return NULL;
09881          case AST_CONTROL_BUSY:
09882             if (option_verbose > 3) 
09883                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
09884             break;
09885          case AST_CONTROL_CONGESTION:
09886             if (option_verbose > 3) 
09887                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
09888             break;
09889          };
09890       }
09891       ast_frfree(f);
09892       ms = newms;
09893    }
09894    /* Hangup the channel since nothing happend */
09895    ast_hangup(chan);
09896    return NULL;
09897 }

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

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

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

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

12561 {
12562    struct dahdi_pvt *p = iflist;
12563    while (p) {
12564       if (p->channel == channel) {
12565          break;
12566       }
12567       p = p->next;
12568    }
12569    return p;
12570 }

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

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

12376 {
12377    int i, j;
12378    for (i = 0; i < num_cadence; i++) {
12379       char output[1024];
12380       char tmp[16], tmp2[64];
12381       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
12382       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
12383 
12384       for (j = 0; j < 16; j++) {
12385          if (cadences[i].ringcadence[j] == 0)
12386             break;
12387          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
12388          if (cidrings[i] * 2 - 1 == j)
12389             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
12390          else
12391             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
12392          if (j != 0)
12393             strncat(output, ",", sizeof(output) - strlen(output) - 1);
12394          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
12395       }
12396       ast_cli(fd,"%s\n",output);
12397    }
12398    return 0;
12399 }

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

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

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

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

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

11784 {
11785    struct dahdi_pvt *p = NULL;
11786    int channo = 0;
11787    if (argc < 4) {
11788       return RESULT_SHOWUSAGE;
11789    }
11790    channo = (argc == 5) ? atoi(argv[4]) : -1;
11791    ast_mutex_lock(&iflock);
11792    p = iflist;
11793    while (p) {
11794       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11795          p = p->next;
11796          continue;
11797       }
11798       if ((channo != -1) && (p->channel != channo )) {
11799          p = p->next;
11800          continue;
11801       }
11802       if (ast_true(argv[3])) {
11803          openr2_chan_enable_call_files(p->r2chan);
11804       } else {
11805          openr2_chan_disable_call_files(p->r2chan);
11806       }
11807       if (channo != -1) {
11808          if (ast_true(argv[3])) {
11809             ast_cli(fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
11810          } else {
11811             ast_cli(fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
11812          }
11813          break;
11814       } else {
11815          p = p->next;
11816       }
11817    }
11818    if ((channo != -1) && !p) {
11819       ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11820    }
11821    if (channo == -1) {
11822       if (ast_true(argv[3])) {
11823          ast_cli(fd, "MFC/R2 Call files enabled for all channels.\n");
11824       } else {
11825          ast_cli(fd, "MFC/R2 Call files disabled for all channels.\n");
11826       }  
11827    }
11828    ast_mutex_unlock(&iflock);
11829    return RESULT_SUCCESS;
11830 }  

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

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

11868 {
11869    struct dahdi_pvt *p = NULL;
11870    int channo = 0;
11871    channo = (argc == 4) ? atoi(argv[3]) : -1;
11872    ast_mutex_lock(&iflock);
11873    p = iflist;
11874    while (p) {
11875       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11876          p = p->next;
11877          continue;
11878       }
11879       if ((channo != -1) && (p->channel != channo )) {
11880          p = p->next;
11881          continue;
11882       }
11883       if (!openr2_chan_set_blocked(p->r2chan)) {
11884          ast_mutex_lock(&p->lock);
11885          p->mfcr2block |= DAHDI_R2_LOCAL_BLOCK;
11886          ast_mutex_unlock(&p->lock);
11887       } else {
11888          ast_cli(fd, "MFC/R2 channel %d could not be blocked.\n", p->channel);
11889       }
11890       if (channo != -1) {
11891          break;
11892       } else {
11893          p = p->next;
11894       }
11895    }
11896    if ((channo != -1) && !p) {
11897       ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11898    }
11899    ast_mutex_unlock(&iflock);
11900    return RESULT_SUCCESS;
11901 }

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

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

11725 {
11726    struct dahdi_pvt *p = NULL;
11727    int channo = 0;
11728    char *toklevel = NULL;
11729    char *saveptr = NULL;
11730    char *logval = NULL;
11731    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
11732    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
11733    if (argc < 4) {
11734       return RESULT_SHOWUSAGE;
11735    }
11736    channo = (argc == 5) ? atoi(argv[4]) : -1;
11737    logval = ast_strdupa(argv[3]);
11738    toklevel = strtok_r(logval, ",", &saveptr);
11739    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
11740       ast_cli(fd, "Invalid MFC/R2 logging level '%s'.\n", argv[3]);
11741       return RESULT_FAILURE;
11742    } else if (OR2_LOG_NOTHING == tmplevel) {
11743       loglevel = tmplevel;
11744    } else {
11745       loglevel |= tmplevel;
11746       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
11747          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
11748             ast_cli(fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
11749             continue;
11750          }
11751          loglevel |= tmplevel;
11752       }
11753    }
11754    ast_mutex_lock(&iflock);
11755    p = iflist;
11756    while (p) {
11757       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11758          p = p->next;
11759          continue;
11760       }
11761       if ((channo != -1) && (p->channel != channo )) {
11762          p = p->next;
11763          continue;
11764       }
11765       openr2_chan_set_log_level(p->r2chan, loglevel);
11766       if (channo != -1) {
11767          ast_cli(fd, "MFC/R2 debugging set to '%s' for channel %d.\n", argv[3], p->channel);
11768          break;
11769       } else {
11770          p = p->next;
11771       }
11772    }
11773    if ((channo != -1) && !p) {
11774       ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11775    }
11776    if (channo == -1) {
11777       ast_cli(fd, "MFC/R2 debugging set to '%s' for all channels.\n", argv[3]);
11778    }
11779    ast_mutex_unlock(&iflock);
11780    return RESULT_SUCCESS;
11781 }

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

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

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

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

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

11656 {
11657 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
11658    int filtertype = 0;
11659    int targetnum = 0;
11660    char channo[5];
11661    char anino[5];
11662    char dnisno[5];
11663    struct dahdi_pvt *p;
11664    openr2_context_t *r2context;
11665    openr2_variant_t r2variant;
11666    if (!((argc == 3) || (argc == 5))) {
11667       return RESULT_SHOWUSAGE;
11668    }
11669    if (argc == 5) {
11670       if (!strcasecmp(argv[3], "group")) {
11671          targetnum = atoi(argv[4]);
11672          if ((targetnum < 0) || (targetnum > 63))
11673             return RESULT_SHOWUSAGE;
11674          targetnum = 1 << targetnum;
11675          filtertype = 1;
11676       } else if (!strcasecmp(argv[3], "context")) {
11677          filtertype = 2;
11678       } else {
11679          return RESULT_SHOWUSAGE;
11680       }
11681    }
11682    ast_cli(fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
11683    ast_mutex_lock(&iflock);
11684    p = iflist;
11685    while (p) {
11686       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11687          p = p->next;
11688          continue;
11689       }
11690       if (filtertype) {
11691          switch(filtertype) {
11692          case 1: /* mfcr2 show channels group <group> */
11693             if (p->group != targetnum) {
11694                p = p->next;
11695                continue;
11696             }
11697             break;
11698          case 2: /* mfcr2 show channels context <context> */
11699             if (strcasecmp(p->context, argv[4])) {
11700                p= p->next;
11701                continue;
11702             }
11703             break;
11704          default:
11705             ;
11706          }
11707       }
11708       r2context = openr2_chan_get_context(p->r2chan);
11709       r2variant = openr2_context_get_variant(r2context);
11710       snprintf(channo, sizeof(channo), "%d", p->channel);
11711       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
11712       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
11713       ast_cli(fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant), 
11714             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",  
11715             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
11716             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
11717       p = p->next;
11718    }
11719    ast_mutex_unlock(&iflock);
11720    return RESULT_SUCCESS;
11721 #undef FORMAT
11722 }

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

Definition at line 11637 of file chan_dahdi.c.

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

11638 {
11639 #define FORMAT "%4s %40s\n"
11640    int numvariants = 0;
11641    int i;
11642    const openr2_variant_entry_t *variants;
11643    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
11644       ast_cli(fd, "Failed to get list of variants.\n");
11645       return RESULT_FAILURE;
11646    }
11647    ast_cli(fd, FORMAT, "Variant Code", "Country");
11648    for (i = 0; i < numvariants; i++) {
11649       ast_cli(fd, FORMAT, variants[i].name, variants[i].country);
11650    }
11651    return RESULT_SUCCESS;
11652 #undef FORMAT
11653 }  

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

Definition at line 11631 of file chan_dahdi.c.

References ast_cli(), and RESULT_SUCCESS.

11632 {
11633    ast_cli(fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
11634    return RESULT_SUCCESS;
11635 }

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

Definition at line 11384 of file chan_dahdi.c.

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

11385 {
11386    int span;
11387    int x;
11388    if (argc < 4) {
11389       return RESULT_SHOWUSAGE;
11390    }
11391    span = atoi(argv[3]);
11392    if ((span < 1) || (span > NUM_SPANS)) {
11393       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
11394       return RESULT_SUCCESS;
11395    }
11396    if (!pris[span-1].pri) {
11397       ast_cli(fd, "No PRI running on span %d\n", span);
11398       return RESULT_SUCCESS;
11399    }
11400    for (x = 0; x < NUM_DCHANS; x++) {
11401       if (pris[span-1].dchans[x])
11402          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11403                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11404                                                PRI_DEBUG_Q921_STATE);
11405    }
11406    ast_cli(fd, "Enabled debugging on span %d\n", span);
11407    return RESULT_SUCCESS;
11408 }

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

Definition at line 11412 of file chan_dahdi.c.

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

11413 {
11414    int span;
11415    int x;
11416    if (argc < 5)
11417       return RESULT_SHOWUSAGE;
11418    span = atoi(argv[4]);
11419    if ((span < 1) || (span > NUM_SPANS)) {
11420       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
11421       return RESULT_SUCCESS;
11422    }
11423    if (!pris[span-1].pri) {
11424       ast_cli(fd, "No PRI running on span %d\n", span);
11425       return RESULT_SUCCESS;
11426    }
11427    for (x = 0; x < NUM_DCHANS; x++) {
11428       if (pris[span-1].dchans[x])
11429          pri_set_debug(pris[span-1].dchans[x], 0);
11430    }
11431    ast_cli(fd, "Disabled debugging on span %d\n", span);
11432    return RESULT_SUCCESS;
11433 }

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

Definition at line 11435 of file chan_dahdi.c.

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

11436 {
11437    int span;
11438    int x;
11439    if (argc < 5)
11440       return RESULT_SHOWUSAGE;
11441    span = atoi(argv[4]);
11442    if ((span < 1) || (span > NUM_SPANS)) {
11443       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
11444       return RESULT_SUCCESS;
11445    }
11446    if (!pris[span-1].pri) {
11447       ast_cli(fd, "No PRI running on span %d\n", span);
11448       return RESULT_SUCCESS;
11449    }
11450    for (x = 0; x < NUM_DCHANS; x++) {
11451       if (pris[span-1].dchans[x])
11452          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11453                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11454                                                PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
11455    }
11456    ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
11457    return RESULT_SUCCESS;
11458 }

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

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

11338 {
11339    int myfd;
11340 
11341    if (!strncasecmp(argv[1], "set", 3)) {
11342       if (argc < 5) 
11343          return RESULT_SHOWUSAGE;
11344 
11345       if (ast_strlen_zero(argv[4]))
11346          return RESULT_SHOWUSAGE;
11347 
11348       myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
11349       if (myfd < 0) {
11350          ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
11351          return RESULT_SUCCESS;
11352       }
11353 
11354       ast_mutex_lock(&pridebugfdlock);
11355 
11356       if (pridebugfd >= 0)
11357          close(pridebugfd);
11358 
11359       pridebugfd = myfd;
11360       ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
11361       
11362       ast_mutex_unlock(&pridebugfdlock);
11363 
11364       ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
11365    } else {
11366       /* Assume it is unset */
11367       ast_mutex_lock(&pridebugfdlock);
11368       close(pridebugfd);
11369       pridebugfd = -1;
11370       ast_cli(fd, "PRI debug output to file disabled\n");
11371       ast_mutex_unlock(&pridebugfdlock);
11372    }
11373 
11374    return RESULT_SUCCESS;
11375 }

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

Definition at line 11541 of file chan_dahdi.c.

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

11542 {
11543    int x;
11544    int span;
11545    int count=0;
11546    int debug=0;
11547 
11548    for (span = 0; span < NUM_SPANS; span++) {
11549            if (pris[span].pri) {
11550          for (x = 0; x < NUM_DCHANS; x++) {
11551             debug = 0;
11552                if (pris[span].dchans[x]) {
11553                   debug = pri_get_debug(pris[span].dchans[x]);
11554                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" );
11555                count++;
11556             }
11557          }
11558       }
11559 
11560    }
11561    ast_mutex_lock(&pridebugfdlock);
11562    if (pridebugfd >= 0) 
11563       ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
11564    ast_mutex_unlock(&pridebugfdlock);
11565        
11566    if (!count) 
11567       ast_cli(fd, "No debug set or no PRI running\n");
11568    return RESULT_SUCCESS;
11569 }

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

Definition at line 11502 of file chan_dahdi.c.

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

11503 {
11504    int span;
11505    int x;
11506    char status[256];
11507    if (argc < 4)
11508       return RESULT_SHOWUSAGE;
11509    span = atoi(argv[3]);
11510    if ((span < 1) || (span > NUM_SPANS)) {
11511       ast_cli(fd, "Invalid span '%s'.  Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
11512       return RESULT_SUCCESS;
11513    }
11514    if (!pris[span-1].pri) {
11515       ast_cli(fd, "No PRI running on span %d\n", span);
11516       return RESULT_SUCCESS;
11517    }
11518    for (x = 0; x < NUM_DCHANS; x++) {
11519       if (pris[span-1].dchannels[x]) {
11520 #ifdef PRI_DUMP_INFO_STR
11521          char *info_str = NULL;
11522 #endif
11523          ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
11524          build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
11525          ast_cli(fd, "Status: %s\n", status);
11526 #ifdef PRI_DUMP_INFO_STR
11527          info_str = pri_dump_info_str(pris[span-1].pri);
11528          if (info_str) {
11529             ast_cli(fd, "%s", info_str);
11530             free(info_str);
11531          }
11532 #else
11533          pri_dump_info(pris[span-1].pri);
11534 #endif
11535          ast_cli(fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
11536       }
11537    }
11538    return RESULT_SUCCESS;
11539 }

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

Definition at line 11481 of file chan_dahdi.c.

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

11482 {
11483    int span;
11484    int x;
11485    char status[256];
11486    if (argc != 3)
11487       return RESULT_SHOWUSAGE;
11488 
11489    for (span = 0; span < NUM_SPANS; span++) {
11490       if (pris[span].pri) {
11491          for (x = 0; x < NUM_DCHANS; x++) {
11492             if (pris[span].dchannels[x]) {
11493                build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
11494                ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
11495             }
11496          }
11497       }
11498    }
11499    return RESULT_SUCCESS;
11500 }

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

Definition at line 11378 of file chan_dahdi.c.

References ast_cli(), and RESULT_SUCCESS.

11378                                                              {
11379    ast_cli(fd, "libpri version: %s\n", pri_get_version());
11380    return RESULT_SUCCESS;
11381 }

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 13976 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.

13977 {
13978    int res;
13979 
13980 #ifdef HAVE_PRI
13981    int y,i;
13982    memset(pris, 0, sizeof(pris));
13983    for (y = 0; y < NUM_SPANS; y++) {
13984       ast_mutex_init(&pris[y].lock);
13985       pris[y].offset = -1;
13986       pris[y].master = AST_PTHREADT_NULL;
13987       for (i = 0; i < NUM_DCHANS; i++)
13988          pris[y].fds[i] = -1;
13989    }
13990    pri_set_error(dahdi_pri_error);
13991    pri_set_message(dahdi_pri_message);
13992    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13993       ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
13994          dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
13995    }
13996    ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
13997       zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
13998 #endif
13999 #ifdef HAVE_OPENR2
14000    init_mfcr2_globals();
14001    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
14002       ast_register_application(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec,
14003          dahdi_accept_r2_call_synopsis, dahdi_accept_r2_call_descrip);
14004    }
14005    ast_register_application(zap_accept_r2_call_app, zap_accept_r2_call_exec,
14006       zap_accept_r2_call_synopsis, zap_accept_r2_call_descrip);
14007 #endif
14008    if ((res = setup_dahdi(0))) {
14009       return AST_MODULE_LOAD_DECLINE;
14010    }
14011    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
14012       chan_tech = &dahdi_tech;
14013    } else {
14014       chan_tech = &zap_tech;
14015    }
14016    if (ast_channel_register(chan_tech)) {
14017       ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
14018       __unload_module();
14019       return -1;
14020    }
14021 #ifdef HAVE_PRI
14022    ast_string_field_init(&inuse, 16);
14023    ast_string_field_set(&inuse, name, "GR-303InUse");
14024    ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
14025 #endif   
14026 #ifdef HAVE_OPENR2
14027    ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
14028 #endif
14029    ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
14030    
14031    memset(round_robin, 0, sizeof(round_robin));
14032    local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
14033    local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
14034    local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
14035    local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
14036    local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
14037    local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
14038    local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
14039 
14040    ast_cond_init(&ss_thread_complete, NULL);
14041 
14042    return res;
14043 }

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

Definition at line 8478 of file chan_dahdi.c.

References ast_log(), LOG_ERROR, and r2links.

Referenced by mkintf().

08479 {
08480    if ((id < 0) || (id >= (sizeof(r2links)/sizeof(r2links[0])))) {
08481       ast_log(LOG_ERROR, "No more R2 links available!.\n");
08482       return NULL;
08483    }
08484    return &r2links[id];
08485 }

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

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

Referenced by setup_dahdi().

09635 {
09636    struct dahdi_pvt *p;
09637    struct dahdi_mfcr2 *mfcr2 = data;
09638    /* we should be using pthread_key_create
09639       and allocate pollers dynamically.
09640       I think do_monitor() could be leaking, since it
09641       could be cancelled at any time and is not
09642       using thread keys, why?, */
09643    struct pollfd pollers[mfcr2->numchans];
09644    int maxsleep = 20;
09645    int res = 0;
09646    int i = 0;
09647    int pollsize = 0;
09648    int oldstate = 0;
09649    int was_idle = 0;
09650    int quit_loop = 0;
09651    /* now that we're ready to get calls, unblock our side and
09652       get current line state */
09653    for (i = 0; i < mfcr2->numchans; i++) {
09654       p = mfcr2->pvts[i];
09655       pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
09656       if (openr2_chan_set_idle(p->r2chan)) {
09657          ast_log(LOG_ERROR, "Failed to set channel %d in IDLE\n", p->channel);
09658       } else {
09659          ast_mutex_lock(&p->lock);
09660          mfcr2->pvts[i]->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK;
09661          mfcr2->pvts[i]->mfcr2call = 0;
09662          ast_mutex_unlock(&p->lock);
09663       }
09664       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
09665    }
09666    while(1) {
09667       /* we trust here that the mfcr2 channel list will not ever change once
09668          the module is loaded */
09669       pollsize = 0;
09670       for (i = 0; i < mfcr2->numchans; i++) {
09671          pollers[i].events = 0;
09672          pollers[i].revents = 0;
09673          if (mfcr2->pvts[i]->owner) {
09674             continue;
09675          }
09676          if (!mfcr2->pvts[i]->r2chan) {
09677             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
09678             quit_loop = 1;
09679             break;
09680          }
09681          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
09682          pollers[i].events = POLLIN | POLLPRI;
09683          pollsize++;
09684       }
09685       if (quit_loop) {
09686          break;
09687       }
09688 
09689       if (pollsize == 0) {
09690          if (!was_idle) {
09691             ast_log(LOG_NOTICE, "Monitor thread going idle since everybody has an owner\n");
09692             was_idle = 1;
09693          }
09694          poll(NULL, 0, maxsleep);
09695          continue;
09696       }
09697       was_idle = 0;
09698 
09699       /* probably poll() is a valid cancel point, lets just be on the safe side
09700          by calling pthread_testcancel */
09701       pthread_testcancel();
09702       res = poll(pollers, mfcr2->numchans, maxsleep);
09703       pthread_testcancel();
09704       if ((res < 0) && (errno != EINTR)) {
09705          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
09706          break;
09707       } 
09708       /* do we want to allow to cancel while processing events? */
09709       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
09710       for (i = 0; i < mfcr2->numchans; i++) {
09711          if ((pollers[i].revents & POLLPRI) || (pollers[i].revents & POLLIN)) {
09712             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
09713          }
09714       }
09715       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
09716    }
09717    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
09718    return 0;
09719 }

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

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

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

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

Definition at line 6259 of file chan_dahdi.c.

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

Referenced by dahdi_write().

06260 {
06261    int sent=0;
06262    int size;
06263    int res;
06264    int fd;
06265    fd = p->subs[index].dfd;
06266    while (len) {
06267       size = len;
06268       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
06269          size = (linear ? READ_SIZE * 2 : READ_SIZE);
06270       res = write(fd, buf, size);
06271       if (res != size) {
06272          if (option_debug)
06273             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06274          return sent;
06275       }
06276       len -= size;
06277       buf += size;
06278    }
06279    return sent;
06280 }

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

Definition at line 6750 of file chan_dahdi.c.

References ast_waitfordigit().

Referenced by ss_thread().

06751 {
06752    char c;
06753 
06754    *str = 0; /* start with empty output buffer */
06755    for (;;)
06756    {
06757       /* Wait for the first digit (up to specified ms). */
06758       c = ast_waitfordigit(chan, ms);
06759       /* if timeout, hangup or error, return as such */
06760       if (c < 1)
06761          return c;
06762       *str++ = c;
06763       *str = 0;
06764       if (strchr(term, c))
06765          return 1;
06766    }
06767 }

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

09987 {
09988    do {
09989       pri->resetpos++;
09990    } while ((pri->resetpos < pri->numchans) &&
09991        (!pri->pvts[pri->resetpos] ||
09992         pri->pvts[pri->resetpos]->call ||
09993         pri->pvts[pri->resetpos]->resetting));
09994    if (pri->resetpos < pri->numchans) {
09995       /* Mark the channel as resetting and restart it */
09996       pri->pvts[pri->resetpos]->resetting = 1;
09997       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
09998    } else {
09999       pri->resetting = 0;
10000       time(&pri->lastreset);
10001    }
10002    return 0;
10003 }

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

Definition at line 8598 of file chan_dahdi.c.

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

Referenced by setup_dahdi().

08599 {
08600    if (pris[span].mastertrunkgroup) {
08601       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);
08602       return -1;
08603    }
08604    pris[span].mastertrunkgroup = trunkgroup;
08605    pris[span].prilogicalspan = logicalspan;
08606    return 0;
08607 }

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

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

08536 {
08537    struct dahdi_spaninfo si;
08538    struct dahdi_params p;
08539    int fd;
08540    int span;
08541    int ospan=0;
08542    int x,y;
08543    for (x = 0; x < NUM_SPANS; x++) {
08544       if (pris[x].trunkgroup == trunkgroup) {
08545          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
08546          return -1;
08547       }
08548    }
08549    for (y = 0; y < NUM_DCHANS; y++) {
08550       if (!channels[y]) 
08551          break;
08552       memset(&si, 0, sizeof(si));
08553       memset(&p, 0, sizeof(p));
08554       fd = open(DAHDI_FILE_CHANNEL, O_RDWR);
08555       if (fd < 0) {
08556          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
08557          return -1;
08558       }
08559       x = channels[y];
08560       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
08561          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
08562          close(fd);
08563          return -1;
08564       }
08565       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
08566          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
08567          return -1;
08568       }
08569       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
08570          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
08571          close(fd);
08572          return -1;
08573       }
08574       span = p.spanno - 1;
08575       if (pris[span].trunkgroup) {
08576          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
08577          close(fd);
08578          return -1;
08579       }
08580       if (pris[span].pvts[0]) {
08581          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
08582          close(fd);
08583          return -1;
08584       }
08585       if (!y) {
08586          pris[span].trunkgroup = trunkgroup;
08587          pris[span].offset = channels[y] - p.chanpos;
08588          ospan = span;
08589       }
08590       pris[ospan].dchannels[y] = channels[y];
08591       pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
08592       pris[span].span = span + 1;
08593       close(fd);
08594    }
08595    return 0;   
08596 }

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

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

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

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

Definition at line 9724 of file chan_dahdi.c.

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

09725 {
09726    struct dahdi_pvt *p;
09727    p = pri->crvs;
09728    while (p) {
09729       if (p->channel == crv)
09730          return p;
09731       p = p->next;
09732    }
09733    return NULL;
09734 }

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

09348 {
09349    int x;
09350    if (backwards)
09351       x = pri->numchans;
09352    else
09353       x = 0;
09354    for (;;) {
09355       if (backwards && (x < 0))
09356          break;
09357       if (!backwards && (x >= pri->numchans))
09358          break;
09359       if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
09360          ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n", 
09361             pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09362          return x;
09363       }
09364       if (backwards)
09365          x--;
09366       else
09367          x++;
09368    }
09369    return -1;
09370 }

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

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

09738 {
09739    int x;
09740    int span = PRI_SPAN(channel);
09741    int spanfd;
09742    struct dahdi_params param;
09743    int principle = -1;
09744    int explicit = PRI_EXPLICIT(channel);
09745    channel = PRI_CHANNEL(channel);
09746 
09747    if (!explicit) {
09748       spanfd = pri_active_dchan_fd(pri);
09749       memset(&param, 0, sizeof(param));
09750       if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
09751          return -1;
09752       span = pris[param.spanno - 1].prilogicalspan;
09753    }
09754 
09755    for (x = 0; x < pri->numchans; x++) {
09756       if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
09757          principle = x;
09758          break;
09759       }
09760    }
09761    
09762    return principle;
09763 }

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

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

09766 {
09767    int x;
09768    struct dahdi_pvt *crv;
09769    if (!c) {
09770       if (principle < 0)
09771          return -1;
09772       return principle;
09773    }
09774    if ((principle > -1) && 
09775       (principle < pri->numchans) && 
09776       (pri->pvts[principle]) && 
09777       (pri->pvts[principle]->call == c))
09778       return principle;
09779    /* First, check for other bearers */
09780    for (x = 0; x < pri->numchans; x++) {
09781       if (!pri->pvts[x])
09782          continue;
09783       if (pri->pvts[x]->call == c) {
09784          /* Found our call */
09785          if (principle != x) {
09786             struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
09787 
09788             if (option_verbose > 2)
09789                ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
09790                   old->channel, new->channel);
09791             if (new->owner) {
09792                ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
09793                   old->channel, new->channel, new->channel);
09794                return -1;
09795             }
09796             /* Fix it all up now */
09797             new->owner = old->owner;
09798             old->owner = NULL;
09799             if (new->owner) {
09800                ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
09801                new->owner->tech_pvt = new;
09802                new->owner->fds[0] = new->subs[SUB_REAL].dfd;
09803                new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
09804                old->subs[SUB_REAL].owner = NULL;
09805             } else
09806                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);
09807             new->call = old->call;
09808             old->call = NULL;
09809 
09810             /* Copy any DSP that may be present */
09811             new->dsp = old->dsp;
09812             new->dsp_features = old->dsp_features;
09813             old->dsp = NULL;
09814             old->dsp_features = 0;
09815          }
09816          return principle;
09817       }
09818    }
09819    /* Now check for a CRV with no bearer */
09820    crv = pri->crvs;
09821    while (crv) {
09822       if (crv->call == c) {
09823          /* This is our match...  Perform some basic checks */
09824          if (crv->bearer)
09825             ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
09826          else if (pri->pvts[principle]->owner) 
09827             ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
09828          else {
09829             /* Looks good.  Drop the pseudo channel now, clear up the assignment, and
09830                wakeup the potential sleeper */
09831             dahdi_close_sub(crv, SUB_REAL);
09832             pri->pvts[principle]->call = crv->call;
09833             pri_assign_bearer(crv, pri, pri->pvts[principle]);
09834             ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
09835                            pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
09836                            pri->trunkgroup, crv->channel);
09837             wakeup_sub(crv, SUB_REAL, pri);
09838          }
09839          return principle;
09840       }
09841       crv = crv->next;
09842    }
09843    ast_log(LOG_WARNING, "Call specified, but not found?\n");
09844    return -1;
09845 }

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 10005 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.

10006 {
10007    int x;
10008    int redo;
10009    ast_mutex_unlock(&pri->lock);
10010    ast_mutex_lock(&p->lock);
10011    do {
10012       redo = 0;
10013       for (x = 0; x < 3; x++) {
10014          while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
10015             redo++;
10016             DEADLOCK_AVOIDANCE(&p->lock);
10017          }
10018          if (p->subs[x].owner) {
10019             ast_queue_hangup(p->subs[x].owner);
10020             ast_mutex_unlock(&p->subs[x].owner->lock);
10021          }
10022       }
10023    } while (redo);
10024    ast_mutex_unlock(&p->lock);
10025    ast_mutex_lock(&pri->lock);
10026    return 0;
10027 }

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

08490 {
08491    int x;
08492    int trunkgroup;
08493    /* Get appropriate trunk group if there is one */
08494    trunkgroup = pris[*span].mastertrunkgroup;
08495    if (trunkgroup) {
08496       /* Select a specific trunk group */
08497       for (x = 0; x < NUM_SPANS; x++) {
08498          if (pris[x].trunkgroup == trunkgroup) {
08499             *span = x;
08500             return 0;
08501          }
08502       }
08503       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
08504       *span = -1;
08505    } else {
08506       if (pris[*span].trunkgroup) {
08507          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
08508          *span = -1;
08509       } else if (pris[*span].mastertrunkgroup) {
08510          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
08511          *span = -1;
08512       } else {
08513          if (si->totalchans == 31) {
08514             /* E1 */
08515             pris[*span].dchannels[0] = 16 + offset;
08516          } else if (si->totalchans == 24) {
08517             /* T1 or J1 */
08518             pris[*span].dchannels[0] = 24 + offset;
08519          } else if (si->totalchans == 3) {
08520             /* BRI */
08521             pris[*span].dchannels[0] = 3 + offset;
08522          } else {
08523             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);
08524             *span = -1;
08525             return 0;
08526          }
08527          pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
08528          pris[*span].offset = offset;
08529          pris[*span].span = *span + 1;
08530       }
08531    }
08532    return 0;
08533 }

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

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

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

static char* redirectingreason2str ( int  redirectingreason  )  [static]

Definition at line 10029 of file chan_dahdi.c.

Referenced by __oh323_new().

10030 {
10031    switch (redirectingreason) {
10032    case 0:
10033       return "UNKNOWN";
10034    case 1:
10035       return "BUSY";
10036    case 2:
10037       return "NO_REPLY";
10038    case 0xF:
10039       return "UNCONDITIONAL";
10040    default:
10041       return "NOREDIRECT";
10042    }
10043 }

static int reload ( void   )  [static]

Definition at line 14146 of file chan_dahdi.c.

References ast_log(), and setup_dahdi().

14147 {
14148    int res = 0;
14149 
14150    res = setup_dahdi(1);
14151    if (res) {
14152       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
14153       return -1;
14154    }
14155    return 0;
14156 }

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

08447 {
08448    pthread_attr_t attr;
08449    pthread_attr_init(&attr);
08450    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08451    /* If we're supposed to be stopped -- stay stopped */
08452    if (monitor_thread == AST_PTHREADT_STOP)
08453       return 0;
08454    ast_mutex_lock(&monlock);
08455    if (monitor_thread == pthread_self()) {
08456       ast_mutex_unlock(&monlock);
08457       ast_log(LOG_WARNING, "Cannot kill myself\n");
08458       return -1;
08459    }
08460    if (monitor_thread != AST_PTHREADT_NULL) {
08461       /* Wake up the thread */
08462       pthread_kill(monitor_thread, SIGURG);
08463    } else {
08464       /* Start a new monitor */
08465       if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
08466          ast_mutex_unlock(&monlock);
08467          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08468          pthread_attr_destroy(&attr);
08469          return -1;
08470       }
08471    }
08472    ast_mutex_unlock(&monlock);
08473    pthread_attr_destroy(&attr);
08474    return 0;
08475 }

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

13815 {
13816    struct ast_config *cfg;
13817    struct ast_variable *v;
13818    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
13819    int res;
13820 
13821 #ifdef HAVE_PRI
13822    char *c;
13823    int spanno;
13824    int i, x;
13825    int logicalspan;
13826    int trunkgroup;
13827    int dchannels[NUM_DCHANS];
13828 #endif
13829 
13830 #ifdef HAVE_ZAPTEL
13831    int load_from_zapata_conf = 1;
13832 #else
13833    int load_from_zapata_conf = (*dahdi_chan_mode == CHAN_ZAP_MODE);
13834 #endif
13835 
13836    if (load_from_zapata_conf) {
13837       if (!(cfg = ast_config_load("zapata.conf"))) {
13838          ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
13839          return 0;
13840       }
13841    } else {
13842       if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
13843          ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
13844          return 0;
13845       }
13846    }
13847 
13848    /* It's a little silly to lock it, but we mind as well just to be sure */
13849    ast_mutex_lock(&iflock);
13850 #ifdef HAVE_PRI
13851    if (reload != 1) {
13852       /* Process trunkgroups first */
13853       v = ast_variable_browse(cfg, "trunkgroups");
13854       while (v) {
13855          if (!strcasecmp(v->name, "trunkgroup")) {
13856             trunkgroup = atoi(v->value);
13857             if (trunkgroup > 0) {
13858                if ((c = strchr(v->value, ','))) {
13859                   i = 0;
13860                   memset(dchannels, 0, sizeof(dchannels));
13861                   while (c && (i < NUM_DCHANS)) {
13862                      dchannels[i] = atoi(c + 1);
13863                      if (dchannels[i] < 0) {
13864                         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);
13865                      } else
13866                         i++;
13867                      c = strchr(c + 1, ',');
13868                   }
13869                   if (i) {
13870                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
13871                         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);
13872                      } else if (option_verbose > 1)
13873                         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");
13874                   } else
13875                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
13876                } else
13877                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
13878             } else
13879                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
13880          } else if (!strcasecmp(v->name, "spanmap")) {
13881             spanno = atoi(v->value);
13882             if (spanno > 0) {
13883                if ((c = strchr(v->value, ','))) {
13884                   trunkgroup = atoi(c + 1);
13885                   if (trunkgroup > 0) {
13886                      if ((c = strchr(c + 1, ','))) 
13887                         logicalspan = atoi(c + 1);
13888                      else
13889                         logicalspan = 0;
13890                      if (logicalspan >= 0) {
13891                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
13892                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
13893                         } else if (option_verbose > 1) 
13894                            ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
13895                      } else
13896                         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);
13897                   } else
13898                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
13899                } else
13900                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
13901             } else
13902                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
13903          } else {
13904             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
13905          }
13906          v = v->next;
13907       }
13908    }
13909 #endif
13910    
13911    /* Copy the default jb config over global_jbconf */
13912    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
13913 
13914    v = ast_variable_browse(cfg, "channels");
13915    res = process_dahdi(&conf, "", v, reload, 0);
13916    ast_mutex_unlock(&iflock);
13917    ast_config_destroy(cfg);
13918    if (res)
13919       return res;
13920    cfg = ast_config_load("users.conf");
13921    if (cfg) {
13922       char *cat;
13923       process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
13924       for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
13925          if (!strcasecmp(cat, "general"))
13926             continue;
13927          if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) {
13928             struct dahdi_chan_conf sect_conf;
13929             memcpy(&sect_conf, &conf, sizeof(sect_conf));
13930 
13931             process_dahdi(&sect_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
13932          }
13933       }
13934       ast_config_destroy(cfg);
13935    }
13936 #ifdef HAVE_PRI
13937    if (reload != 1) {
13938       for (x = 0; x < NUM_SPANS; x++) {
13939          if (pris[x].pvts[0]) {
13940             if (start_pri(pris + x)) {
13941                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
13942                return -1;
13943             } else if (option_verbose > 1)
13944                ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
13945          }
13946       }
13947    }
13948 #endif
13949 #ifdef HAVE_OPENR2
13950    if (reload != 1) {
13951       int x;
13952       for (x = 0; x < NUM_SPANS; x++) {
13953          if (r2links[x].protocol_context) {
13954             if (ast_pthread_create(&r2links[x].master, NULL, mfcr2_monitor, &r2links[x])) {
13955                ast_log(LOG_ERROR, "Unable to start R2 context on span %d\n", x + 1);
13956                return -1;
13957             } else {
13958                ast_verbose(VERBOSE_PREFIX_2 "Starting R2 context on span %d\n", x + 1);
13959             }
13960          }
13961       }
13962    }
13963 #endif
13964    /* And start the monitor for the first time */
13965    restart_monitor();
13966    return 0;
13967 }

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

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

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

static int start_pri ( struct dahdi_pri pri  )  [static]

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

11220 {
11221    int res, x;
11222    struct dahdi_params p;
11223    struct dahdi_bufferinfo bi;
11224    struct dahdi_spaninfo si;
11225    int i;
11226    
11227    for (i = 0; i < NUM_DCHANS; i++) {
11228       if (!pri->dchannels[i])
11229          break;
11230       pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600);
11231       x = pri->dchannels[i];
11232       if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
11233          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
11234          return -1;
11235       }
11236       memset(&p, 0, sizeof(p));
11237       res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
11238       if (res) {
11239          dahdi_close_pri_fd(pri, i);
11240          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
11241          return -1;
11242       }
11243       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
11244          dahdi_close_pri_fd(pri, i);
11245          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.  See /etc/dahdi/system.conf\n", x);
11246          return -1;
11247       }
11248       memset(&si, 0, sizeof(si));
11249       res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
11250       if (res) {
11251          dahdi_close_pri_fd(pri, i);
11252          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
11253       }
11254       if (!si.alarms)
11255          pri->dchanavail[i] |= DCHAN_NOTINALARM;
11256       else
11257          pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
11258       memset(&bi, 0, sizeof(bi));
11259       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
11260       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
11261       bi.numbufs = 32;
11262       bi.bufsize = 1024;
11263       if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
11264          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
11265          dahdi_close_pri_fd(pri, i);
11266          return -1;
11267       }
11268       pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
11269       /* Force overlap dial if we're doing GR-303! */
11270       if (pri->switchtype == PRI_SWITCH_GR303_TMC)
11271          pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
11272       pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
11273 #ifdef HAVE_PRI_INBANDDISCONNECT
11274       pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
11275 #endif
11276       /* Enslave to master if appropriate */
11277       if (i)
11278          pri_enslave(pri->dchans[0], pri->dchans[i]);
11279       if (!pri->dchans[i]) {
11280          dahdi_close_pri_fd(pri, i);
11281          ast_log(LOG_ERROR, "Unable to create PRI structure\n");
11282          return -1;
11283       }
11284       pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
11285       pri_set_nsf(pri->dchans[i], pri->nsf);
11286 #ifdef PRI_GETSET_TIMERS
11287       for (x = 0; x < PRI_MAX_TIMERS; x++) {
11288          if (pritimers[x] != 0)
11289             pri_set_timer(pri->dchans[i], x, pritimers[x]);
11290       }
11291 #endif
11292    }
11293    /* Assume primary is the one we use */
11294    pri->pri = pri->dchans[0];
11295    pri->resetpos = -1;
11296    if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
11297       for (i = 0; i < NUM_DCHANS; i++) {
11298          if (!pri->dchannels[i])
11299             break;
11300          dahdi_close_pri_fd(pri, i);
11301       }
11302       ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
11303       return -1;
11304    }
11305    return 0;
11306 }

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

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

12881 {
12882 #ifdef HAVE_PRI      
12883    int y;
12884    for (y = 0; y < NUM_SPANS; y++)
12885       ast_mutex_destroy(&pris[y].lock);
12886 #endif
12887    return __unload_module();
12888 }

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

References __action_dialoffhook(), and s.

12705 {
12706    return __action_dialoffhook(s, m, 1);
12707 }

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

Definition at line 12604 of file chan_dahdi.c.

References __action_dnd(), and s.

12605 {
12606    return __action_dnd(s, m, 1, 0);
12607 }

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

Definition at line 12594 of file chan_dahdi.c.

References __action_dnd(), and s.

12595 {
12596    return __action_dnd(s, m, 1, 1);
12597 }

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

Definition at line 12783 of file chan_dahdi.c.

References __action_restart(), and s.

12784 {
12785    return __action_restart(s, m, 1);
12786 }

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

Definition at line 12759 of file chan_dahdi.c.

References __action_showchannels(), and s.

12760 {
12761    return __action_showchannels(s, m, 1);
12762 }

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

Definition at line 12633 of file chan_dahdi.c.

References __action_transfer(), and s.

12634 {
12635    return __action_transfer(s, m, 1);
12636 }

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

Definition at line 12661 of file chan_dahdi.c.

References __action_transferhangup(), and s.

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

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 14172 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 14172 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 12500 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 12505 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 12485 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 12495 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 12490 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 12510 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 12515 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct ast_cli_entry dahdi_mfcr2_cli[] [static]

Definition at line 11931 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct ast_cli_entry dahdi_pri_cli[] [static]

Definition at line 11591 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 11916 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 11925 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 11912 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 11920 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 11909 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 11906 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 11903 of file chan_dahdi.c.

char dahdi_restart_usage[] [static]

Definition at line 12478 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 12371 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 12470 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 12474 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 11571 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 11575 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 11579 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 11583 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 11587 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 12466 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 12462 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 Fri Aug 13 18:21:14 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7