Thu Dec 17 13:33:46 2009

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

Referenced by dahdi_callwait().

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

300 ms

Definition at line 297 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 1184 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 1185 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 299 of file chan_dahdi.c.

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 472 of file chan_dahdi.c.

#define CONF_USER_THIRDCALL   (1 << 1)

Definition at line 473 of file chan_dahdi.c.

#define DAHDI_EVENT_DTMFDOWN   0

Definition at line 126 of file chan_dahdi.c.

Referenced by dahdi_handle_event().

#define DAHDI_EVENT_DTMFUP   0

Definition at line 127 of file chan_dahdi.c.

Referenced by dahdi_handle_event().

#define DAHDI_OVERLAPDIAL_BOTH   (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)

Definition at line 212 of file chan_dahdi.c.

Referenced by process_dahdi(), and start_pri().

#define DAHDI_OVERLAPDIAL_INCOMING   2

Definition at line 211 of file chan_dahdi.c.

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

#define DAHDI_OVERLAPDIAL_NONE   0

Definition at line 209 of file chan_dahdi.c.

Referenced by process_dahdi().

#define DAHDI_OVERLAPDIAL_OUTGOING   1

Definition at line 210 of file chan_dahdi.c.

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

#define DAHDI_R2_LOCAL_BLOCK   (1 << 1)

Definition at line 1643 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 1642 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 412 of file chan_dahdi.c.

Referenced by start_pri().

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

8,000 ms

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

#define HANGUP   1

Definition at line 12438 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 1181 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 12468 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 12469 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 13861 of file chan_dahdi.c.

Referenced by load_module().

#define local_astman_unregister (  ) 

Definition at line 12689 of file chan_dahdi.c.

Referenced by __unload_module().

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 294 of file chan_dahdi.c.

#define MASK_INUSE   (1 << 1)

Channel currently in use

Definition at line 295 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 12883 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 475 of file chan_dahdi.c.

Referenced by isslavenative().

#define MIN_MS_SINCE_FLASH   ( (2000) )

2000 ms

Definition at line 300 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 1159 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 430 of file chan_dahdi.c.

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

#define POLARITY_REV   1

Definition at line 431 of file chan_dahdi.c.

Referenced by dahdi_handle_event(), and handle_init_event().

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

Definition at line 353 of file chan_dahdi.c.

Referenced by pri_find_principle().

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

Definition at line 355 of file chan_dahdi.c.

Referenced by pri_find_principle().

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

Definition at line 354 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 352 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 292 of file chan_dahdi.c.

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

#define sig2str   dahdi_sig2str

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

#define SIG_GR303FXOKS   (0x0100000 | DAHDI_SIG_FXOKS)

Definition at line 193 of file chan_dahdi.c.

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

#define SIG_GR303FXSKS   (0x0100000 | DAHDI_SIG_FXSKS)

Definition at line 194 of file chan_dahdi.c.

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

#define SIG_MFCR2   DAHDI_SIG_CAS

Definition at line 186 of file chan_dahdi.c.

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

#define SIG_PRI   DAHDI_SIG_CLEAR

Definition at line 185 of file chan_dahdi.c.

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

#define SIG_SF   DAHDI_SIG_SF

Definition at line 187 of file chan_dahdi.c.

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

#define SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)

Definition at line 191 of file chan_dahdi.c.

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

#define SIG_SF_FEATD   (0x0200000 | DAHDI_SIG_SF)

Definition at line 189 of file chan_dahdi.c.

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

#define SIG_SF_FEATDMF   (0x0400000 | DAHDI_SIG_SF)

Definition at line 190 of file chan_dahdi.c.

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

#define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)

Definition at line 188 of file chan_dahdi.c.

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

#define SMDI_MD_WAIT_TIMEOUT   1500

Definition at line 109 of file chan_dahdi.c.

Referenced by ss_thread().

#define SUB_CALLWAIT   1

Call-Waiting call on hold

Definition at line 426 of file chan_dahdi.c.

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

#define SUB_REAL   0

Active call

Definition at line 425 of file chan_dahdi.c.

Referenced by __dahdi_exception(), attempt_transfer(), available(), bump_gains(), chandup(), check_for_conference(), dahdi_answer(), dahdi_bridge(), dahdi_call(), dahdi_confmute(), dahdi_destroy_channel_bynum(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_r2_on_call_accepted(), dahdi_r2_on_call_answered(), dahdi_r2_on_call_disconnect(), dahdi_r2_on_call_offered(), dahdi_read(), dahdi_request(), dahdi_ring_phone(), dahdi_setoption(), dahdi_train_ec(), dahdi_unlink(), destroy_dahdi_pvt(), disable_dtmf_detect(), do_monitor(), enable_dtmf_detect(), features_hangup(), features_request(), get_alarms(), handle_init_event(), mkintf(), pri_assign_bearer(), pri_fixup_principle(), reset_conf(), restore_conference(), restore_gains(), save_conference(), send_callerid(), and ss_thread().

#define SUB_THREEWAY   2

Three-way call

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

#define TRAILER_MS   5

Referenced by dahdi_sendtext().

#define TRANSFER   0

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

12568 {
12569    struct dahdi_pvt *p = NULL;
12570    const char *channel = local_astman_header(m, "Channel", zap_mode);
12571    const char *number = astman_get_header(m, "Number");
12572    int i;
12573 
12574    if (ast_strlen_zero(channel)) {
12575       astman_send_error(s, m, "No channel specified");
12576       return 0;
12577    }
12578    if (ast_strlen_zero(number)) {
12579       astman_send_error(s, m, "No number specified");
12580       return 0;
12581    }
12582    if (!(p = find_channel(atoi(channel)))) {
12583       astman_send_error(s, m, "No such channel");
12584       return 0;
12585    }
12586    if (!p->owner) {
12587       astman_send_error(s, m, "Channel does not have an owner");
12588       return 0;
12589    }
12590    for (i = 0; i < strlen(number); i++) {
12591       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
12592 
12593       dahdi_queue_frame(p, &f, NULL); 
12594    }
12595    local_astman_ack(s, m, "DialOffHook", zap_mode);
12596 
12597    return 0;
12598 }

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

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

12472 {
12473    struct dahdi_pvt *p = NULL;
12474    const char *channel = local_astman_header(m, "Channel", zap_mode);
12475 
12476    if (ast_strlen_zero(channel)) {
12477       astman_send_error(s, m, "No channel specified");
12478       return 0;
12479    }
12480    if (!(p = find_channel(atoi(channel)))) {
12481       astman_send_error(s, m, "No such channel");
12482       return 0;
12483    }
12484    p->dnd = dnd;
12485    local_astman_ack(s, m, "DND", zap_mode);
12486 
12487    return 0;
12488 }

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

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

12666 {
12667    if (dahdi_restart() != 0) {
12668       if (zap_mode) {
12669          astman_send_error(s, m, "Failed to restart Zap");
12670       } else {
12671          astman_send_error(s, m, "Failed to restart DAHDI");
12672       }
12673       return 1;
12674    }
12675    local_astman_ack(s, m, "Restart: Success", zap_mode);
12676    return 0;
12677 }

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

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

12611 {
12612    struct dahdi_pvt *tmp = NULL;
12613    const char *id = astman_get_header(m, "ActionID");
12614    char idText[256] = "";
12615 
12616    local_astman_ack(s, m, " channel status will follow", zap_mode);
12617    if (!ast_strlen_zero(id))
12618       snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
12619 
12620    ast_mutex_lock(&iflock);
12621    
12622    tmp = iflist;
12623    while (tmp) {
12624       if (tmp->channel > 0) {
12625          int alarm = get_alarms(tmp);
12626          astman_append(s,
12627                   "Event: %sShowChannels\r\n"
12628                   "Channel: %d\r\n"
12629                   "Signalling: %s\r\n"
12630                   "Context: %s\r\n"
12631                   "DND: %s\r\n"
12632                   "Alarm: %s\r\n"
12633                   "%s"
12634                   "\r\n",
12635                   dahdi_chan_name,
12636                   tmp->channel, sig2str(tmp->sig), tmp->context, 
12637                   tmp->dnd ? "Enabled" : "Disabled",
12638                   alarm2str(alarm), idText);
12639       } 
12640 
12641       tmp = tmp->next;
12642    }
12643 
12644    ast_mutex_unlock(&iflock);
12645    
12646    astman_append(s, 
12647             "Event: %sShowChannelsComplete\r\n"
12648             "%s"
12649             "\r\n",
12650             dahdi_chan_name,
12651             idText);
12652    return 0;
12653 }

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

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

12511 {
12512    struct dahdi_pvt *p = NULL;
12513    const char *channel = local_astman_header(m, "Channel", zap_mode);
12514 
12515    if (ast_strlen_zero(channel)) {
12516       astman_send_error(s, m, "No channel specified");
12517       return 0;
12518    }
12519    if (!(p = find_channel(atoi(channel)))) {
12520       astman_send_error(s, m, "No such channel");
12521       return 0;
12522    }
12523    dahdi_fake_event(p,TRANSFER);
12524    local_astman_ack(s, m, "Transfer", zap_mode);
12525 
12526    return 0;
12527 }

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

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

12540 {
12541    struct dahdi_pvt *p = NULL;
12542    const char *channel = local_astman_header(m, "Channel", zap_mode);
12543 
12544    if (ast_strlen_zero(channel)) {
12545       astman_send_error(s, m, "No channel specified");
12546       return 0;
12547    }
12548    if (!(p = find_channel(atoi(channel)))) {
12549       astman_send_error(s, m, "No such channel");
12550       return 0;
12551    }
12552    dahdi_fake_event(p, HANGUP);
12553    local_astman_ack(s, m, "Hangup", zap_mode);
12554    return 0;
12555 }

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

Definition at line 5784 of file chan_dahdi.c.

References ast_bridged_channel(), AST_CONTROL_UNHOLD, AST_FRAME_NULL, ast_log(), ast_queue_control(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_tv(), ast_verbose(), dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index(), dahdi_handle_event(), dahdi_ring_phone(), dahdi_set_hook(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, event2str(), dahdi_subchannel::f, f, dahdi_pvt::fake_event, ast_channel::fds, ast_frame::frametype, LOG_DEBUG, ast_frame::mallocd, ast_channel::name, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, option_debug, option_verbose, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::radio, ast_frame::samples, ast_frame::src, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, update_conf(), and VERBOSE_PREFIX_3.

Referenced by dahdi_exception(), and dahdi_read().

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

static void __reg_module ( void   )  [static]

Definition at line 14064 of file chan_dahdi.c.

static int __unload_module ( void   )  [static]

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

12697 {
12698    struct dahdi_pvt *p;
12699 #ifdef HAVE_OPENR2
12700    int r;
12701 #endif
12702 #ifdef HAVE_PRI
12703    int i, j;
12704    for (i = 0; i < NUM_SPANS; i++) {
12705       if (pris[i].master != AST_PTHREADT_NULL) 
12706          pthread_cancel(pris[i].master);
12707    }
12708    ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
12709 
12710    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12711       ast_unregister_application(dahdi_send_keypad_facility_app);
12712    }
12713    ast_unregister_application(zap_send_keypad_facility_app);
12714 #endif
12715 #ifdef HAVE_OPENR2
12716    for (r = 0; r < NUM_SPANS; r++) {
12717       if (r2links[r].master != AST_PTHREADT_NULL) {
12718          pthread_cancel(r2links[r].master);
12719          pthread_join(r2links[r].master, NULL);
12720       }
12721    }
12722    ast_cli_unregister_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli) / sizeof(dahdi_mfcr2_cli[0]));
12723    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12724       ast_unregister_application(dahdi_accept_r2_call_app);
12725    }
12726    ast_unregister_application(zap_accept_r2_call_app);
12727 #endif
12728    ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
12729    local_astman_unregister("DialOffHook");
12730    local_astman_unregister("Hangup");
12731    local_astman_unregister("Transfer");
12732    local_astman_unregister("DNDoff");
12733    local_astman_unregister("DNDon");
12734    local_astman_unregister("ShowChannels");
12735    local_astman_unregister("Restart");
12736    ast_channel_unregister(chan_tech);
12737    ast_mutex_lock(&iflock);
12738    /* Hangup all interfaces if they have an owner */
12739    p = iflist;
12740    while (p) {
12741       if (p->owner)
12742          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
12743       p = p->next;
12744    }
12745    ast_mutex_unlock(&iflock);
12746    ast_mutex_lock(&monlock);
12747    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12748       pthread_cancel(monitor_thread);
12749       pthread_kill(monitor_thread, SIGURG);
12750       pthread_join(monitor_thread, NULL);
12751    }
12752    monitor_thread = AST_PTHREADT_STOP;
12753    ast_mutex_unlock(&monlock);
12754 
12755    destroy_all_channels();
12756 #ifdef HAVE_PRI      
12757    for (i = 0; i < NUM_SPANS; i++) {
12758       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
12759          pthread_join(pris[i].master, NULL);
12760       for (j = 0; j < NUM_DCHANS; j++) {
12761          dahdi_close_pri_fd(&(pris[i]), j);
12762       }
12763    }
12764 #endif
12765 #ifdef HAVE_OPENR2
12766    for (r = 0; r < NUM_SPANS; r++) {
12767       if (r2links[r].protocol_context) {
12768          openr2_context_delete(r2links[r].protocol_context);
12769       }
12770    }
12771 #endif
12772    ast_cond_destroy(&ss_thread_complete);
12773    return 0;
12774 }

static void __unreg_module ( void   )  [static]

Definition at line 14064 of file chan_dahdi.c.

static char* alarm2str ( int  alarm  )  [static]

Definition at line 2072 of file chan_dahdi.c.

References alarms, and name.

Referenced by __action_showchannels(), and handle_alarms().

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

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

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

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

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

09942 {
09943    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
09944       if (size) {
09945          *buf = '\0';
09946       }
09947       return;
09948    }
09949 
09950    switch (plan) {
09951    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
09952       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
09953       break;
09954    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
09955       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
09956       break;
09957    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
09958       snprintf(buf, size, "%s%s", pri->localprefix, number);
09959       break;
09960    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
09961       snprintf(buf, size, "%s%s", pri->privateprefix, number);
09962       break;
09963    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
09964       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
09965       break;
09966    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
09967       snprintf(buf, size, "%s", number);
09968       break;
09969    }
09970 }

static int attempt_transfer ( struct dahdi_pvt p  )  [static]

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

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

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

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

09091 {
09092    int res;
09093    struct dahdi_params par;
09094 
09095    /* First, check group matching */
09096    if (groupmatch) {
09097       if ((p->group & groupmatch) != groupmatch)
09098          return 0;
09099       *groupmatched = 1;
09100    }
09101    /* Check to see if we have a channel match */
09102    if (channelmatch != -1) {
09103       if (p->channel != channelmatch)
09104          return 0;
09105       *channelmatched = 1;
09106    }
09107    /* We're at least busy at this point */
09108    if (busy) {
09109       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
09110          *busy = 1;
09111    }
09112    /* If do not disturb, definitely not */
09113    if (p->dnd)
09114       return 0;
09115    /* If guard time, definitely not */
09116    if (p->guardtime && (time(NULL) < p->guardtime)) 
09117       return 0;
09118       
09119    /* If no owner definitely available */
09120    if (!p->owner) {
09121 #ifdef HAVE_PRI
09122       /* Trust PRI */
09123       if (p->pri) {
09124          if (p->resetting || p->call)
09125             return 0;
09126          else
09127             return 1;
09128       }
09129 #endif
09130 #ifdef HAVE_OPENR2
09131       /* Trust MFC/R2 */
09132       if (p->mfcr2) {
09133          if (p->mfcr2call || p->mfcr2block)
09134             return 0;
09135          else
09136             return 1;
09137       }
09138 #endif
09139       if (!(p->radio || (p->oprmode < 0)))
09140       {
09141          if (!p->sig || (p->sig == SIG_FXSLS))
09142             return 1;
09143          /* Check hook state */
09144          if (p->subs[SUB_REAL].dfd > -1) {
09145             memset(&par, 0, sizeof(par));
09146             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
09147          } else {
09148             /* Assume not off hook on CVRS */
09149             res = 0;
09150             par.rxisoffhook = 0;
09151          }
09152          if (res) {
09153             ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
09154          } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
09155             /* When "onhook" that means no battery on the line, and thus
09156               it is out of service..., if it's on a TDM card... If it's a channel
09157               bank, there is no telling... */
09158             if (par.rxbits > -1)
09159                return 1;
09160             if (par.rxisoffhook)
09161                return 1;
09162             else
09163 #ifdef DAHDI_CHECK_HOOKSTATE
09164                return 0;
09165 #else
09166                return 1;
09167 #endif
09168          } else if (par.rxisoffhook) {
09169             ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
09170             /* Not available when the other end is off hook */
09171             return 0;
09172          }
09173       }
09174       return 1;
09175    }
09176 
09177    /* If it's not an FXO, forget about call wait */
09178    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 
09179       return 0;
09180 
09181    if (!p->callwaiting) {
09182       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
09183       return 0;
09184    }
09185 
09186    if (p->subs[SUB_CALLWAIT].dfd > -1) {
09187       /* If there is already a call waiting call, then we can't take a second one */
09188       return 0;
09189    }
09190    
09191    if ((p->owner->_state != AST_STATE_UP) &&
09192        ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
09193       /* If the current call is not up, then don't allow the call */
09194       return 0;
09195    }
09196    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
09197       /* Can't take a call wait when the three way calling hasn't been merged yet. */
09198       return 0;
09199    }
09200    /* We're cool */
09201    return 1;
09202 }

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

12787 {
12788    char *c, *chan;
12789    int x, start, finish;
12790    struct dahdi_pvt *tmp;
12791 #ifdef HAVE_PRI
12792    struct dahdi_pri *pri;
12793    int trunkgroup, y;
12794 #endif
12795    
12796    if ((reload == 0) && (conf->chan.sig < 0)) {
12797       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
12798       return -1;
12799    }
12800 
12801    c = ast_strdupa(value);
12802 
12803 #ifdef HAVE_PRI
12804    pri = NULL;
12805    if (iscrv) {
12806       if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
12807          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
12808          return -1;
12809       }
12810       if (trunkgroup < 1) {
12811          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
12812          return -1;
12813       }
12814       c += y;
12815       for (y = 0; y < NUM_SPANS; y++) {
12816          if (pris[y].trunkgroup == trunkgroup) {
12817             pri = pris + y;
12818             break;
12819          }
12820       }
12821       if (!pri) {
12822          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
12823          return -1;
12824       }
12825    }
12826 #endif         
12827 
12828    while ((chan = strsep(&c, ","))) {
12829       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
12830          /* Range */
12831       } else if (sscanf(chan, "%30d", &start)) {
12832          /* Just one */
12833          finish = start;
12834       } else if (!strcasecmp(chan, "pseudo")) {
12835          finish = start = CHAN_PSEUDO;
12836          if (found_pseudo)
12837             *found_pseudo = 1;
12838       } else {
12839          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
12840          return -1;
12841       }
12842       if (finish < start) {
12843          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
12844          x = finish;
12845          finish = start;
12846          start = x;
12847       }
12848 
12849       for (x = start; x <= finish; x++) {
12850 #ifdef HAVE_PRI
12851          tmp = mkintf(x, conf, pri, reload);
12852 #else       
12853          tmp = mkintf(x, conf, NULL, reload);
12854 #endif         
12855 
12856          if (tmp) {
12857             if (option_verbose > 2) {
12858 #ifdef HAVE_PRI
12859                if (pri)
12860                   ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
12861                else
12862 #endif
12863                   ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
12864             }
12865          } else {
12866             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
12867                (reload == 1) ? "reconfigure" : "register", value);
12868             return -1;
12869          }
12870       }
12871 #ifdef HAVE_OPENR2
12872       if (reload != 1 && r2links[mfcr2_cur_context_index].protocol_context) {
12873          mfcr2_cur_context_index++;
12874       }  
12875 #endif
12876    }
12877 
12878    return 0;
12879 }

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

Definition at line 11356 of file chan_dahdi.c.

References DCHAN_NOTINALARM, and DCHAN_PROVISIONED.

Referenced by handle_pri_show_span(), and handle_pri_show_spans().

11357 {
11358    if (!s || len < 1) {
11359       return;
11360    }
11361    s[0] = '\0';
11362    if (status & DCHAN_PROVISIONED)
11363       strncat(s, "Provisioned, ", len - strlen(s) - 1);
11364    if (!(status & DCHAN_NOTINALARM))
11365       strncat(s, "In Alarm, ", len - strlen(s) - 1);
11366    if (status & DCHAN_UP)
11367       strncat(s, "Up", len - strlen(s) - 1);
11368    else
11369       strncat(s, "Down", len - strlen(s) - 1);
11370    if (active)
11371       strncat(s, ", Active", len - strlen(s) - 1);
11372    else
11373       strncat(s, ", Standby", len - strlen(s) - 1);
11374    s[len - 1] = '\0';
11375 }

static int bump_gains ( struct dahdi_pvt p  )  [static]

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

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

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

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

09205 {
09206    struct dahdi_pvt *p;
09207    struct dahdi_bufferinfo bi;
09208    int res;
09209    
09210    if ((p = ast_malloc(sizeof(*p)))) {
09211       memcpy(p, src, sizeof(struct dahdi_pvt));
09212       ast_mutex_init(&p->lock);
09213       p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
09214       /* Allocate a DAHDI structure */
09215       if (p->subs[SUB_REAL].dfd < 0) {
09216          ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
09217          destroy_dahdi_pvt(&p);
09218          return NULL;
09219       }
09220       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09221       if (!res) {
09222          bi.txbufpolicy = p->buf_policy;
09223          bi.rxbufpolicy = p->buf_policy;
09224          bi.numbufs = p->buf_no;
09225          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09226          if (res < 0) {
09227             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09228          }
09229       } else
09230          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09231    }
09232    p->destroy = 1;
09233    p->next = iflist;
09234    p->prev = NULL;
09235    iflist = p;
09236    if (iflist->next)
09237       iflist->next->prev = p;
09238    return p;
09239 }

static int check_for_conference ( struct dahdi_pvt p  )  [static]

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

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

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

Definition at line 11223 of file chan_dahdi.c.

References complete_span_helper().

11224 {
11225    return complete_span_helper(line,word,pos,state,3);
11226 }

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

Definition at line 11228 of file chan_dahdi.c.

References complete_span_helper().

11229 {
11230    return complete_span_helper(line,word,pos,state,4);
11231 }

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

Definition at line 11204 of file chan_dahdi.c.

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

Referenced by complete_span_4(), and complete_span_5().

11205 {
11206    int which, span;
11207    char *ret = NULL;
11208 
11209    if (pos != rpos)
11210       return ret;
11211 
11212    for (which = span = 0; span < NUM_SPANS; span++) {
11213       if (pris[span].pri && ++which > state) {
11214          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
11215             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
11216          }
11217          break;
11218       }
11219    }
11220    return ret;
11221 }

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

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

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

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

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

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

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

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

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

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

Definition at line 12605 of file chan_dahdi.c.

References __action_dialoffhook(), and s.

12606 {
12607    return __action_dialoffhook(s, m, 0);
12608 }

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

Definition at line 12505 of file chan_dahdi.c.

References __action_dnd(), and s.

12506 {
12507    return __action_dnd(s, m, 0, 0);
12508 }

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

Definition at line 12495 of file chan_dahdi.c.

References __action_dnd(), and s.

12496 {
12497    return __action_dnd(s, m, 0, 1);
12498 }

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

Definition at line 12684 of file chan_dahdi.c.

References __action_restart(), and s.

12685 {
12686    return __action_restart(s, m, 0);
12687 }

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

Definition at line 12660 of file chan_dahdi.c.

References __action_showchannels(), and s.

12661 {
12662    return __action_showchannels(s, m, 0);
12663 }

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

Definition at line 12534 of file chan_dahdi.c.

References __action_transfer(), and s.

12535 {
12536    return __action_transfer(s, m, 0);
12537 }

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

Definition at line 12562 of file chan_dahdi.c.

References __action_transferhangup(), and s.

12563 {
12564    return __action_transferhangup(s, m, 0);
12565 }

static int dahdi_answer ( struct ast_channel ast  )  [static]

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

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

static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause ( int  cause  )  [static]

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

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

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

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

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

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

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

static int dahdi_callwait ( struct ast_channel ast  )  [static]

Definition at line 2683 of file chan_dahdi.c.

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

Referenced by dahdi_call(), and dahdi_read().

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

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

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

static void dahdi_close ( int  fd  )  [static]

Definition at line 1844 of file chan_dahdi.c.

Referenced by dahdi_close_pri_fd(), and dahdi_close_sub().

01845 {
01846    if (fd > 0)
01847       close(fd);
01848 }

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

Definition at line 1857 of file chan_dahdi.c.

References dahdi_close(), and dahdi_pri::fds.

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

01858 {
01859    dahdi_close(pri->fds[fd_num]);
01860    pri->fds[fd_num] = -1;
01861 }

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

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

01851 {
01852    dahdi_close(chan_pvt->subs[sub_num].dfd);
01853    chan_pvt->subs[sub_num].dfd = -1;
01854 }

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

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

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

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

Definition at line 11860 of file chan_dahdi.c.

References dahdi_destroy_channel_bynum(), and RESULT_SHOWUSAGE.

11861 {
11862    int channel;
11863    
11864    if (argc != 4)
11865       return RESULT_SHOWUSAGE;
11866    
11867    channel = atoi(argv[3]);
11868 
11869    return dahdi_destroy_channel_bynum(channel);
11870 }

static int dahdi_destroy_channel_bynum ( int  channel  )  [static]

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

07911 {
07912    struct dahdi_pvt *tmp = NULL;
07913    struct dahdi_pvt *prev = NULL;
07914 
07915    ast_mutex_lock(&iflock);
07916    tmp = iflist;
07917    while (tmp) {
07918       if (tmp->channel == channel) {
07919          int x = DAHDI_FLASH;
07920          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 */
07921          destroy_channel(prev, tmp, 1);
07922          ast_mutex_unlock(&iflock);
07923          ast_module_unref(ast_module_info->self);
07924          return RESULT_SUCCESS;
07925       }
07926       prev = tmp;
07927       tmp = tmp->next;
07928    }
07929    ast_mutex_unlock(&iflock);
07930    return RESULT_FAILURE;
07931 }

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

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

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

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

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

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

static void dahdi_disable_ec ( struct dahdi_pvt p  )  [static]

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

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

static void dahdi_enable_ec ( struct dahdi_pvt p  )  [static]

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

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

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

Definition at line 5892 of file chan_dahdi.c.

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

05893 {
05894    struct dahdi_pvt *p = ast->tech_pvt;
05895    struct ast_frame *f;
05896    ast_mutex_lock(&p->lock);
05897    f = __dahdi_exception(ast);
05898    ast_mutex_unlock(&p->lock);
05899    return f;
05900 }

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

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

12441 {
12442    if (p) {
12443       switch (mode) {
12444          case TRANSFER:
12445             p->fake_event = DAHDI_EVENT_WINKFLASH;
12446             break;
12447          case HANGUP:
12448             p->fake_event = DAHDI_EVENT_ONHOOK;
12449             break;
12450          default:
12451             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
12452       }
12453    }
12454    return 0;
12455 }

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

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

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

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

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

04230 {
04231    struct dahdi_pvt *p = chan->tech_pvt;
04232    
04233    if (!strcasecmp(data, "rxgain")) {
04234       ast_mutex_lock(&p->lock);
04235       snprintf(buf, len, "%f", p->rxgain);
04236       ast_mutex_unlock(&p->lock);   
04237    } else if (!strcasecmp(data, "txgain")) {
04238       ast_mutex_lock(&p->lock);
04239       snprintf(buf, len, "%f", p->txgain);
04240       ast_mutex_unlock(&p->lock);   
04241    } else {
04242       ast_copy_string(buf, "", len);
04243    }
04244    return 0;
04245 }

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

Avoid the silly dahdi_getevent which ignores a bunch of events.

Definition at line 271 of file chan_dahdi.c.

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

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

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

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

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

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

Definition at line 4819 of file chan_dahdi.c.

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

Referenced by dahdi_handle_event(), and dahdi_read().

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

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

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

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

static int dahdi_hangup ( struct ast_channel ast  )  [static]

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

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

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

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

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

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

Definition at line 4304 of file chan_dahdi.c.

References ast_log(), LOG_WARNING, and master.

Referenced by dahdi_bridge().

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

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

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

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

static int dahdi_open ( char *  fn  )  [static]

Definition at line 1797 of file chan_dahdi.c.

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

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

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

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

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

09841 {
09842    int x, y;
09843    int dchan = -1, span = -1;
09844    int dchancount = 0;
09845 
09846    if (pri) {
09847       for (x = 0; x < NUM_SPANS; x++) {
09848          for (y = 0; y < NUM_DCHANS; y++) {
09849             if (pris[x].dchans[y])
09850                dchancount++;
09851 
09852             if (pris[x].dchans[y] == pri)
09853                dchan = y;
09854          }
09855          if (dchan >= 0) {
09856             span = x;
09857             break;
09858          }
09859          dchancount = 0;
09860       }
09861       if ((dchan >= 0) && (span >= 0)) {
09862          if (dchancount > 1)
09863             ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
09864          else
09865             ast_log(LOG_ERROR, "%s", s);
09866       } else
09867          ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
09868    } else
09869       ast_log(LOG_ERROR, "%s", s);
09870 
09871    ast_mutex_lock(&pridebugfdlock);
09872 
09873    if (pridebugfd >= 0) {
09874       if (write(pridebugfd, s, strlen(s)) < 0) {
09875          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
09876       }
09877    }
09878 
09879    ast_mutex_unlock(&pridebugfdlock);
09880 }

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

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

09799 {
09800    int x, y;
09801    int dchan = -1, span = -1;
09802    int dchancount = 0;
09803 
09804    if (pri) {
09805       for (x = 0; x < NUM_SPANS; x++) {
09806          for (y = 0; y < NUM_DCHANS; y++) {
09807             if (pris[x].dchans[y])
09808                dchancount++;
09809 
09810             if (pris[x].dchans[y] == pri)
09811                dchan = y;
09812          }
09813          if (dchan >= 0) {
09814             span = x;
09815             break;
09816          }
09817          dchancount = 0;
09818       }
09819       if ((dchan >= 0) && (span >= 0)) {
09820          if (dchancount > 1)
09821             ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
09822          else
09823             ast_verbose("%s", s);
09824       } else
09825          ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
09826    } else
09827       ast_verbose("%s", s);
09828 
09829    ast_mutex_lock(&pridebugfdlock);
09830 
09831    if (pridebugfd >= 0) {
09832       if (write(pridebugfd, s, strlen(s)) < 0) {
09833          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
09834       }
09835    }
09836 
09837    ast_mutex_unlock(&pridebugfdlock);
09838 }

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

Definition at line 1233 of file chan_dahdi.c.

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

Referenced by __action_dialoffhook().

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

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

Definition at line 1750 of file chan_dahdi.c.

References AST_ALAW.

01751 {
01752    return AST_ALAW(sample);
01753 }

static int dahdi_r2_answer ( struct dahdi_pvt p  )  [static]

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

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

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

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

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

static openr2_calling_party_category_t dahdi_r2_get_channel_category ( struct ast_channel c  )  [static]

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

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

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

Definition at line 1755 of file chan_dahdi.c.

References AST_LIN2A.

01756 {
01757    return AST_LIN2A(sample);
01758 }

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

Definition at line 1714 of file chan_dahdi.c.

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

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

static void dahdi_r2_on_billing_pulse_received ( openr2_chan_t *  r2chan  )  [static]

Definition at line 1724 of file chan_dahdi.c.

References ast_log(), and LOG_NOTICE.

01725 {
01726    ast_log(LOG_NOTICE, "MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
01727 }

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

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

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

static void dahdi_r2_on_call_answered ( openr2_chan_t *  r2chan  )  [static]

Definition at line 1519 of file chan_dahdi.c.

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

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

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

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

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

static void dahdi_r2_on_call_end ( openr2_chan_t *  r2chan  )  [static]

Definition at line 1472 of file chan_dahdi.c.

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

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

static void dahdi_r2_on_call_init ( openr2_chan_t *  r2chan  )  [static]

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

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

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

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

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

Definition at line 1526 of file chan_dahdi.c.

01527 {
01528    /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
01529 }

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

References dahdi_r2_write_log().

Referenced by mkintf().

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

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

References dahdi_r2_write_log().

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

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

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

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

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

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

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

static void dahdi_r2_on_line_blocked ( openr2_chan_t *  r2chan  )  [static]

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

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

static void dahdi_r2_on_line_idle ( openr2_chan_t *  r2chan  )  [static]

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

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

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

Definition at line 1390 of file chan_dahdi.c.

References ast_log(), and LOG_ERROR.

01391 {
01392    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
01393 }

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

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

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

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

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

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

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

Definition at line 5902 of file chan_dahdi.c.

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

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

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

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

09270 {
09271    ast_group_t groupmatch = 0;
09272    int channelmatch = -1;
09273    int roundrobin = 0;
09274    int callwait = 0;
09275    int busy = 0;
09276    struct dahdi_pvt *p;
09277    struct ast_channel *tmp = NULL;
09278    char *dest=NULL;
09279    int x;
09280    char *s;
09281    char opt=0;
09282    int res=0, y=0;
09283    int backwards = 0;
09284 #ifdef HAVE_PRI
09285    int crv;
09286    int bearer = -1;
09287    int trunkgroup;
09288    struct dahdi_pri *pri=NULL;
09289 #endif   
09290    struct dahdi_pvt *exit, *start, *end;
09291    ast_mutex_t *lock;
09292    int channelmatched = 0;
09293    int groupmatched = 0;
09294    
09295    /*
09296     * data is ---v
09297     * Dial(DAHDI/pseudo[/extension])
09298     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension])
09299     * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension])
09300     * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension])
09301     *
09302     * g - channel group allocation search forward
09303     * G - channel group allocation search backward
09304     * r - channel group allocation round robin search forward
09305     * R - channel group allocation round robin search backward
09306     *
09307     * c - Wait for DTMF digit to confirm answer
09308     * r<cadance#> - Set distintive ring cadance number
09309     * d - Force bearer capability for ISDN call to digital.
09310     */
09311 
09312    /* Assume we're locking the iflock */
09313    lock = &iflock;
09314    start = iflist;
09315    end = ifend;
09316    if (data) {
09317       dest = ast_strdupa((char *)data);
09318    } else {
09319       ast_log(LOG_WARNING, "Channel requested with no data\n");
09320       return NULL;
09321    }
09322    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
09323       /* Retrieve the group number */
09324       char *stringp;
09325 
09326       stringp = dest + 1;
09327       s = strsep(&stringp, "/");
09328       if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09329          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
09330          return NULL;
09331       }
09332       groupmatch = ((ast_group_t) 1 << x);
09333       if (toupper(dest[0]) == 'G') {
09334          if (dest[0] == 'G') {
09335             backwards = 1;
09336             p = ifend;
09337          } else
09338             p = iflist;
09339       } else {
09340          if (dest[0] == 'R') {
09341             backwards = 1;
09342             p = round_robin[x]?round_robin[x]->prev:ifend;
09343             if (!p)
09344                p = ifend;
09345          } else {
09346             p = round_robin[x]?round_robin[x]->next:iflist;
09347             if (!p)
09348                p = iflist;
09349          }
09350          roundrobin = 1;
09351       }
09352    } else {
09353       char *stringp;
09354 
09355       stringp = dest;
09356       s = strsep(&stringp, "/");
09357       p = iflist;
09358       if (!strcasecmp(s, "pseudo")) {
09359          /* Special case for pseudo */
09360          x = CHAN_PSEUDO;
09361          channelmatch = x;
09362       } 
09363 #ifdef HAVE_PRI
09364       else if ((res = sscanf(s, "%30d:%30d%c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
09365          if ((trunkgroup < 1) || (crv < 1)) {
09366             ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
09367             return NULL;
09368          }
09369          res--;
09370          for (x = 0; x < NUM_SPANS; x++) {
09371             if (pris[x].trunkgroup == trunkgroup) {
09372                pri = pris + x;
09373                lock = &pri->lock;
09374                start = pri->crvs;
09375                end = pri->crvend;
09376                break;
09377             }
09378          }
09379          if (!pri) {
09380             ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
09381             return NULL;
09382          }
09383          channelmatch = crv;
09384          p = pris[x].crvs;
09385       }
09386 #endif   
09387       else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09388          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
09389          return NULL;
09390       } else {
09391          channelmatch = x;
09392       }
09393    }
09394    /* Search for an unowned channel */
09395    ast_mutex_lock(lock);
09396    exit = p;
09397    while (p && !tmp) {
09398       if (roundrobin)
09399          round_robin[x] = p;
09400 #if 0
09401       ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
09402 #endif
09403 
09404       if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
09405          if (option_debug)
09406             ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
09407             if (p->inalarm) 
09408                goto next;
09409 
09410          callwait = (p->owner != NULL);
09411 #ifdef HAVE_PRI
09412          if (pri && (p->subs[SUB_REAL].dfd < 0)) {
09413             if (p->sig != SIG_FXSKS) {
09414                /* Gotta find an actual channel to use for this
09415                   CRV if this isn't a callwait */
09416                bearer = pri_find_empty_chan(pri, 0);
09417                if (bearer < 0) {
09418                   ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
09419                   p = NULL;
09420                   break;
09421                }
09422                pri_assign_bearer(p, pri, pri->pvts[bearer]);
09423             } else {
09424                if (alloc_sub(p, 0)) {
09425                   ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
09426                   p = NULL;
09427                   break;
09428                } else
09429                   ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
09430                p->pri = pri;
09431             }
09432          }
09433 #endif         
09434 #ifdef HAVE_OPENR2
09435          if (p->mfcr2) {
09436             ast_mutex_lock(&p->lock);
09437             if (p->mfcr2call) {
09438                ast_mutex_unlock(&p->lock);
09439                ast_log(LOG_NOTICE, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
09440                goto next;
09441             }
09442             if (p->mfcr2block) {
09443                ast_mutex_unlock(&p->lock);
09444                ast_log(LOG_NOTICE, "Yay!, channel %d just got blocked (%d).\n", p->channel, p->mfcr2block);
09445                goto next;
09446             }
09447             p->mfcr2call = 1;
09448             ast_mutex_unlock(&p->lock);
09449          }
09450 #endif
09451          if (p->channel == CHAN_PSEUDO) {
09452             p = chandup(p);
09453             if (!p) {
09454                break;
09455             }
09456          }
09457          if (p->owner) {
09458             if (alloc_sub(p, SUB_CALLWAIT)) {
09459                p = NULL;
09460                break;
09461             }
09462          }
09463          p->outgoing = 1;
09464          tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
09465          if (!tmp) {
09466             p->outgoing = 0;
09467          }
09468 #ifdef HAVE_PRI
09469          if (p->bearer) {
09470             /* Log owner to bearer channel, too */
09471             p->bearer->owner = tmp;
09472          }
09473 #endif         
09474          /* Make special notes */
09475          if (res > 1) {
09476             if (opt == 'c') {
09477                /* Confirm answer */
09478                p->confirmanswer = 1;
09479             } else if (opt == 'r') {
09480                /* Distinctive ring */
09481                if (res < 3)
09482                   ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
09483                else
09484                   p->distinctivering = y;
09485             } else if (opt == 'd') {
09486                /* If this is an ISDN call, make it digital */
09487                p->digital = 1;
09488                if (tmp)
09489                   tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
09490             } else {
09491                ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
09492             }
09493          }
09494          /* Note if the call is a call waiting call */
09495          if (tmp && callwait)
09496             tmp->cdrflags |= AST_CDR_CALLWAIT;
09497          break;
09498       }
09499 next:
09500       if (backwards) {
09501          p = p->prev;
09502          if (!p)
09503             p = end;
09504       } else {
09505          p = p->next;
09506          if (!p)
09507             p = start;
09508       }
09509       /* stop when you roll to the one that we started from */
09510       if (p == exit)
09511          break;
09512    }
09513    ast_mutex_unlock(lock);
09514    restart_monitor();
09515    if (callwait)
09516       *cause = AST_CAUSE_BUSY;
09517    else if (!tmp) {
09518       if (channelmatched) {
09519          if (busy)
09520             *cause = AST_CAUSE_BUSY;
09521       } else if (groupmatched) {
09522          *cause = AST_CAUSE_CONGESTION;
09523       }
09524    }
09525       
09526    return tmp;
09527 }

static int dahdi_restart ( void   )  [static]

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

11902 {
11903 #ifdef HAVE_OPENR2
11904    int r;
11905 #endif
11906 #if defined(HAVE_PRI)
11907    int i, j;
11908 #endif
11909    int cancel_code;
11910    struct dahdi_pvt *p;
11911 
11912    ast_mutex_lock(&restart_lock);
11913  
11914    if (option_verbose)
11915       ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
11916    dahdi_softhangup_all();
11917    if (option_verbose > 3)
11918       ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
11919 
11920 #ifdef HAVE_OPENR2
11921    for (r = 0; r < NUM_SPANS; r++) {
11922       if (r2links[r].master != AST_PTHREADT_NULL) {
11923          ast_log(LOG_DEBUG, "Killing MFC/R2 monitor thread %p\n", &r2links[r].master);
11924          pthread_cancel(r2links[r].master);
11925          pthread_join(r2links[r].master, NULL);
11926          openr2_context_delete(r2links[r].protocol_context);
11927       }
11928    }
11929    init_mfcr2_globals();
11930 #endif
11931 
11932    #if defined(HAVE_PRI)
11933    for (i = 0; i < NUM_SPANS; i++) {
11934       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
11935          cancel_code = pthread_cancel(pris[i].master);
11936          pthread_kill(pris[i].master, SIGURG);
11937          if (option_debug > 3)
11938             ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
11939             pthread_join(pris[i].master, NULL);
11940          if (option_debug > 3)
11941             ast_verbose("Joined thread of span %d\n", i);
11942       }
11943     }
11944    #endif
11945 
11946     ast_mutex_lock(&monlock);
11947     if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
11948       cancel_code = pthread_cancel(monitor_thread);
11949       pthread_kill(monitor_thread, SIGURG);
11950       if (option_debug > 3)
11951          ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
11952         pthread_join(monitor_thread, NULL);
11953       if (option_debug > 3)
11954          ast_verbose("Joined monitor thread\n");
11955     }
11956    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
11957 
11958    ast_mutex_lock(&ss_thread_lock);
11959    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
11960       int x = DAHDI_FLASH;
11961       if (option_debug > 2)
11962          ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
11963 
11964       for (p = iflist; p; p = p->next) {
11965          if (p->owner)
11966             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 */    
11967       }
11968       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
11969    }
11970 
11971    /* ensure any created channels before monitor threads were stopped are hungup */
11972    dahdi_softhangup_all();
11973    if (option_verbose > 3)
11974       ast_verbose("Final softhangup of all DAHDI channels complete.\n");
11975    destroy_all_channels();
11976    if (option_debug)
11977       ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
11978 
11979     ast_mutex_unlock(&monlock);
11980 
11981    #ifdef HAVE_PRI
11982    for (i = 0; i < NUM_SPANS; i++) {
11983       for (j = 0; j < NUM_DCHANS; j++)
11984             dahdi_close_pri_fd(&(pris[i]), j);
11985    }
11986 
11987    memset(pris, 0, sizeof(pris));
11988    for (i = 0; i < NUM_SPANS; i++) {
11989       ast_mutex_init(&pris[i].lock);
11990       pris[i].offset = -1;
11991       pris[i].master = AST_PTHREADT_NULL;
11992       for (j = 0; j < NUM_DCHANS; j++)
11993          pris[i].fds[j] = -1;
11994    }
11995    pri_set_error(dahdi_pri_error);
11996    pri_set_message(dahdi_pri_message);
11997    #endif
11998 
11999    if (setup_dahdi(2) != 0) {
12000       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
12001       ast_mutex_unlock(&ss_thread_lock);
12002       return 1;
12003    }
12004    ast_mutex_unlock(&ss_thread_lock);
12005    ast_mutex_unlock(&restart_lock);
12006    return 0;
12007 }

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

Definition at line 12009 of file chan_dahdi.c.

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

12010 {
12011    if (argc != 2) {
12012       return RESULT_SHOWUSAGE;
12013    }
12014 
12015    if (dahdi_restart() != 0)
12016       return RESULT_FAILURE;
12017    return RESULT_SUCCESS;
12018 }

static int dahdi_ring_phone ( struct dahdi_pvt p  )  [static]

Definition at line 4679 of file chan_dahdi.c.

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

Referenced by __dahdi_exception(), and dahdi_handle_event().

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

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

Definition at line 3333 of file chan_dahdi.c.

References send_keypad_facility_exec().

Referenced by load_module().

03334 {
03335    return send_keypad_facility_exec(chan, data);
03336 }

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

Definition at line 13937 of file chan_dahdi.c.

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

13938 {
13939 #define  END_SILENCE_LEN 400
13940 #define  HEADER_MS 50
13941 #define  TRAILER_MS 5
13942 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
13943 #define  ASCII_BYTES_PER_CHAR 80
13944 
13945    unsigned char *buf,*mybuf;
13946    struct dahdi_pvt *p = c->tech_pvt;
13947    struct pollfd fds[1];
13948    int size,res,fd,len,x;
13949    int bytes=0;
13950    /* Initial carrier (imaginary) */
13951    float cr = 1.0;
13952    float ci = 0.0;
13953    float scont = 0.0;
13954    int index;
13955 
13956    index = dahdi_get_index(c, p, 0);
13957    if (index < 0) {
13958       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
13959       return -1;
13960    }
13961    if (!text[0]) return(0); /* if nothing to send, dont */
13962    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
13963    if (p->mate) 
13964       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
13965    else
13966       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
13967    if (!buf)
13968       return -1;
13969    mybuf = buf;
13970    if (p->mate) {
13971       int codec = AST_LAW(p);
13972       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
13973          PUT_CLID_MARKMS;
13974       }
13975       /* Put actual message */
13976       for (x = 0; text[x]; x++) {
13977          PUT_CLID(text[x]);
13978       }
13979       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
13980          PUT_CLID_MARKMS;
13981       }
13982       len = bytes;
13983       buf = mybuf;
13984    } else {
13985       len = tdd_generate(p->tdd, buf, text);
13986       if (len < 1) {
13987          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
13988          free(mybuf);
13989          return -1;
13990       }
13991    }
13992    memset(buf + len, 0x7f, END_SILENCE_LEN);
13993    len += END_SILENCE_LEN;
13994    fd = p->subs[index].dfd;
13995    while (len) {
13996       if (ast_check_hangup(c)) {
13997          free(mybuf);
13998          return -1;
13999       }
14000       size = len;
14001       if (size > READ_SIZE)
14002          size = READ_SIZE;
14003       fds[0].fd = fd;
14004       fds[0].events = POLLOUT | POLLPRI;
14005       fds[0].revents = 0;
14006       res = poll(fds, 1, -1);
14007       if (!res) {
14008          ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
14009          continue;
14010       }
14011         /* if got exception */
14012       if (fds[0].revents & POLLPRI) {
14013          ast_free(mybuf);
14014          return -1;
14015       }
14016       if (!(fds[0].revents & POLLOUT)) {
14017          ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
14018          continue;
14019       }
14020       res = write(fd, buf, size);
14021       if (res != size) {
14022          if (res == -1) {
14023             free(mybuf);
14024             return -1;
14025          }
14026          if (option_debug)
14027             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
14028          break;
14029       }
14030       len -= size;
14031       buf += size;
14032    }
14033    free(mybuf);
14034    return(0);
14035 }

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

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

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

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

Definition at line 9972 of file chan_dahdi.c.

09973 {
09974    int res;
09975    res = ioctl(dfd, DAHDI_SETLAW, &law);
09976    if (res)
09977       return res;
09978    return 0;
09979 }

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

Definition at line 1864 of file chan_dahdi.c.

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

01865 {
01866    int res;
01867    res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
01868    if (res)
01869       return res;
01870    return 0;
01871 }

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

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

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

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

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

12082 {
12083    int channel;
12084    struct dahdi_pvt *tmp = NULL;
12085    struct dahdi_confinfo ci;
12086    struct dahdi_params ps;
12087    int x;
12088    ast_mutex_t *lock;
12089    struct dahdi_pvt *start;
12090 #ifdef HAVE_PRI
12091    char *c;
12092    int trunkgroup;
12093    struct dahdi_pri *pri=NULL;
12094 #endif
12095 
12096    lock = &iflock;
12097    start = iflist;
12098 
12099    if (argc != 4)
12100       return RESULT_SHOWUSAGE;
12101 #ifdef HAVE_PRI
12102    if ((c = strchr(argv[3], ':'))) {
12103       if (sscanf(argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
12104          return RESULT_SHOWUSAGE;
12105       if ((trunkgroup < 1) || (channel < 1))
12106          return RESULT_SHOWUSAGE;
12107       for (x = 0; x < NUM_SPANS; x++) {
12108          if (pris[x].trunkgroup == trunkgroup) {
12109             pri = pris + x;
12110             break;
12111          }
12112       }
12113       if (pri) {
12114          start = pri->crvs;
12115          lock = &pri->lock;
12116       } else {
12117          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
12118          return RESULT_FAILURE;
12119       }
12120    } else
12121 #endif
12122       channel = atoi(argv[3]);
12123 
12124    ast_mutex_lock(lock);
12125    tmp = start;
12126    while (tmp) {
12127       if (tmp->channel == channel) {
12128 #ifdef HAVE_PRI
12129          if (pri) 
12130             ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
12131          else
12132 #endif         
12133          ast_cli(fd, "Channel: %d\n", tmp->channel);
12134          ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
12135          ast_cli(fd, "Span: %d\n", tmp->span);
12136          ast_cli(fd, "Extension: %s\n", tmp->exten);
12137          ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
12138          ast_cli(fd, "Context: %s\n", tmp->context);
12139          ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
12140          ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
12141          ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
12142          ast_cli(fd, "Destroy: %d\n", tmp->destroy);
12143          ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
12144          ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
12145          ast_cli(fd, "Radio: %d\n", tmp->radio);
12146          ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
12147          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)" : "");
12148          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)" : "");
12149          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)" : "");
12150          ast_cli(fd, "Confno: %d\n", tmp->confno);
12151          ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
12152          ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
12153          ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
12154          ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
12155          ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
12156          ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
12157          ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
12158          ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
12159          ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
12160          if (tmp->master)
12161             ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
12162          for (x = 0; x < MAX_SLAVES; x++) {
12163             if (tmp->slaves[x])
12164                ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
12165          }
12166 #ifdef HAVE_OPENR2
12167          if (tmp->mfcr2) {
12168             char calldir[OR2_MAX_PATH];
12169             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
12170             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
12171             ast_cli(fd, "MFC/R2 Call: %s\n", tmp->mfcr2call ? "Yes" : "No");
12172             ast_cli(fd, "MFC/R2 Blocked: %s\n", tmp->mfcr2block ? "Yes" : "No");
12173             ast_cli(fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
12174             ast_cli(fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
12175             ast_cli(fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
12176             ast_cli(fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
12177             ast_cli(fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
12178             ast_cli(fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
12179             ast_cli(fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
12180             ast_cli(fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
12181 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
12182             ast_cli(fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
12183             ast_cli(fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
12184 #endif
12185             ast_cli(fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
12186             ast_cli(fd, "MFC/R2 Skip Category: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
12187             ast_cli(fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
12188             ast_cli(fd, "MFC/R2 Accept On Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
12189             ast_cli(fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
12190             ast_cli(fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
12191             ast_cli(fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
12192             ast_cli(fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
12193             ast_cli(fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
12194             ast_cli(fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
12195             ast_cli(fd, "MFC/R2 Tx CAS : %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
12196             ast_cli(fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
12197             ast_cli(fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
12198             ast_cli(fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
12199          }
12200 #endif
12201 #ifdef HAVE_PRI
12202          if (tmp->pri) {
12203             ast_cli(fd, "PRI Flags: ");
12204             if (tmp->resetting)
12205                ast_cli(fd, "Resetting ");
12206             if (tmp->call)
12207                ast_cli(fd, "Call ");
12208             if (tmp->bearer)
12209                ast_cli(fd, "Bearer ");
12210             ast_cli(fd, "\n");
12211             if (tmp->logicalspan) 
12212                ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
12213             else
12214                ast_cli(fd, "PRI Logical Span: Implicit\n");
12215          }
12216             
12217 #endif
12218          memset(&ci, 0, sizeof(ci));
12219          ps.channo = tmp->channel;
12220          if (tmp->subs[SUB_REAL].dfd > -1) {
12221             memset(&ci, 0, sizeof(ci));
12222             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
12223                ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
12224             }
12225 #ifdef DAHDI_GETCONFMUTE
12226             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
12227                ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
12228             }
12229 #endif
12230             memset(&ps, 0, sizeof(ps));
12231             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
12232                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
12233             } else {
12234                ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
12235             }
12236          }
12237          if (ISTRUNK(tmp)) {
12238             ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");  
12239             if (!ast_strlen_zero(progzone))
12240                ast_cli(fd, "Progress Zone: %s\n", progzone);
12241             ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");  
12242             if(tmp->busydetect) {
12243                ast_cli(fd, "Busy Count: %d\n", tmp->busycount);
12244                if(tmp->busytonelength > 0) {
12245                   ast_cli(fd, "Busy Pattern:\n");
12246                   ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
12247                   if (tmp->busyquietlength > 0) 
12248                      ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
12249                   else 
12250                      ast_cli(fd, " -- Detect Tone Only\n");
12251                   if(tmp->busyfuzziness > 0)
12252                      ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
12253                }
12254             }
12255          }
12256          ast_mutex_unlock(lock);
12257          return RESULT_SUCCESS;
12258       }
12259       tmp = tmp->next;
12260    }
12261    
12262    ast_cli(fd, "Unable to find given channel %d\n", channel);
12263    ast_mutex_unlock(lock);
12264    return RESULT_FAILURE;
12265 }

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

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

12021 {
12022 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
12023 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
12024    struct dahdi_pvt *tmp = NULL;
12025    char tmps[20] = "";
12026    ast_mutex_t *lock;
12027    struct dahdi_pvt *start;
12028 #ifdef HAVE_PRI
12029    int trunkgroup;
12030    struct dahdi_pri *pri = NULL;
12031    int x;
12032 #endif
12033 
12034    lock = &iflock;
12035    start = iflist;
12036 
12037 #ifdef HAVE_PRI
12038    if (argc == 4) {
12039       if ((trunkgroup = atoi(argv[3])) < 1)
12040          return RESULT_SHOWUSAGE;
12041       for (x = 0; x < NUM_SPANS; x++) {
12042          if (pris[x].trunkgroup == trunkgroup) {
12043             pri = pris + x;
12044             break;
12045          }
12046       }
12047       if (pri) {
12048          start = pri->crvs;
12049          lock = &pri->lock;
12050       } else {
12051          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
12052          return RESULT_FAILURE;
12053       }
12054    } else
12055 #endif
12056    if (argc != 3)
12057       return RESULT_SHOWUSAGE;
12058 
12059    ast_mutex_lock(lock);
12060 #ifdef HAVE_PRI
12061    ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
12062 #else
12063    ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
12064 #endif   
12065    
12066    tmp = start;
12067    while (tmp) {
12068       if (tmp->channel > 0) {
12069          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
12070       } else
12071          ast_copy_string(tmps, "pseudo", sizeof(tmps));
12072       ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
12073       tmp = tmp->next;
12074    }
12075    ast_mutex_unlock(lock);
12076    return RESULT_SUCCESS;
12077 #undef FORMAT
12078 #undef FORMAT2
12079 }

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

Definition at line 12298 of file chan_dahdi.c.

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

12298                                                              {
12299    #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
12300    #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
12301 
12302    int span;
12303    int res;
12304    char alarms[50];
12305 
12306    int ctl;
12307    struct dahdi_spaninfo s;
12308 
12309    if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) {
12310       ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno));
12311       ast_cli(fd, "No " DAHDI_NAME " interface found.\n");
12312       return RESULT_FAILURE;
12313    }
12314    ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
12315 
12316    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
12317       s.spanno = span;
12318       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
12319       if (res) {
12320          continue;
12321       }
12322       alarms[0] = '\0';
12323       if (s.alarms > 0) {
12324          if (s.alarms & DAHDI_ALARM_BLUE)
12325             strcat(alarms, "BLU/");
12326          if (s.alarms & DAHDI_ALARM_YELLOW)
12327             strcat(alarms, "YEL/");
12328          if (s.alarms & DAHDI_ALARM_RED)
12329             strcat(alarms, "RED/");
12330          if (s.alarms & DAHDI_ALARM_LOOPBACK)
12331             strcat(alarms, "LB/");
12332          if (s.alarms & DAHDI_ALARM_RECOVER)
12333             strcat(alarms, "REC/");
12334          if (s.alarms & DAHDI_ALARM_NOTOPEN)
12335             strcat(alarms, "NOP/");
12336          if (!strlen(alarms))
12337             strcat(alarms, "UUU/");
12338          if (strlen(alarms)) {
12339             /* Strip trailing / */
12340             alarms[strlen(alarms) - 1] = '\0';
12341          }
12342       } else {
12343          if (s.numchans)
12344             strcpy(alarms, "OK");
12345          else
12346             strcpy(alarms, "UNCONFIGURED");
12347       }
12348 
12349       ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
12350    }
12351    close(ctl);
12352 
12353    return RESULT_SUCCESS;
12354 #undef FORMAT
12355 #undef FORMAT2
12356 }

static char* dahdi_sig2str ( int  sig  )  [static]

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

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

static void dahdi_softhangup_all ( void   )  [static]

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

11873 {
11874    struct dahdi_pvt *p;
11875 retry:
11876    ast_mutex_lock(&iflock);
11877     for (p = iflist; p; p = p->next) {
11878       ast_mutex_lock(&p->lock);
11879         if (p->owner && !p->restartpending) {
11880          if (ast_channel_trylock(p->owner)) {
11881             if (option_debug > 2)
11882                ast_verbose("Avoiding deadlock\n");
11883             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
11884             ast_mutex_unlock(&p->lock);
11885             ast_mutex_unlock(&iflock);
11886             goto retry;
11887          }
11888          if (option_debug > 2)
11889             ast_verbose("Softhanging up on %s\n", p->owner->name);
11890          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
11891          p->restartpending = 1;
11892          num_restart_pending++;
11893          ast_channel_unlock(p->owner);
11894       }
11895       ast_mutex_unlock(&p->lock);
11896     }
11897    ast_mutex_unlock(&iflock);
11898 }

static void dahdi_train_ec ( struct dahdi_pvt p  )  [static]

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

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

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

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

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

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

Avoid the silly dahdi_waitevent which ignores a bunch of events.

Definition at line 280 of file chan_dahdi.c.

Referenced by ss_thread().

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

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

Definition at line 6732 of file chan_dahdi.c.

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

Referenced by ss_thread().

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

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

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

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

static void destroy_all_channels ( void   )  [static]

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

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

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

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

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

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

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

03182 {
03183    struct dahdi_pvt *p = *pvt;
03184    /* Remove channel from the list */
03185    if (p->prev)
03186       p->prev->next = p->next;
03187    if (p->next)
03188       p->next->prev = p->prev;
03189    if (p->use_smdi)
03190       ast_smdi_interface_unref(p->smdi_iface);
03191    ast_mutex_destroy(&p->lock);
03192    dahdi_close_sub(p, SUB_REAL);
03193    if (p->owner)
03194       p->owner->tech_pvt = NULL;
03195    free(p);
03196    *pvt = NULL;
03197 }

static char* dialplan2str ( int  dialplan  )  [static]

Definition at line 2092 of file chan_dahdi.c.

Referenced by dahdi_call(), and mkintf().

02093 {
02094    if (dialplan == -1) {
02095       return("Dynamically set dialplan in ISDN");
02096    }
02097    return (pri_plan2str(dialplan));
02098 }

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 1925 of file chan_dahdi.c.

Referenced by dahdi_digit_begin().

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

static void disable_dtmf_detect ( struct dahdi_pvt p  )  [static]

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

04328 {
04329 #ifdef DAHDI_TONEDETECT
04330    int val;
04331 #endif
04332 
04333    p->ignoredtmf = 1;
04334 
04335 #ifdef DAHDI_TONEDETECT
04336    val = 0;
04337    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04338 #endif      
04339    if (!p->hardwaredtmf && p->dsp) {
04340       p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
04341       ast_dsp_set_features(p->dsp, p->dsp_features);
04342    }
04343 }

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

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

09744 {
09745    struct ast_channel *chan = vchan;
09746    struct dahdi_pvt *pvt = chan->tech_pvt;
09747    struct ast_frame *f;
09748    char ex[80];
09749    /* Wait up to 30 seconds for an answer */
09750    int newms, ms = 30000;
09751    if (option_verbose > 2) 
09752       ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
09753    snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
09754    if (ast_call(chan, ex, 0)) {
09755       ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
09756       ast_hangup(chan);
09757       return NULL;
09758    }
09759    while ((newms = ast_waitfor(chan, ms)) > 0) {
09760       f = ast_read(chan);
09761       if (!f) {
09762          /* Got hangup */
09763          break;
09764       }
09765       if (f->frametype == AST_FRAME_CONTROL) {
09766          switch (f->subclass) {
09767          case AST_CONTROL_ANSWER:
09768             /* Launch the PBX */
09769             ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
09770             ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
09771             chan->priority = 1;
09772             if (option_verbose > 3) 
09773                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
09774             ast_pbx_run(chan);
09775             /* It's already hungup, return immediately */
09776             return NULL;
09777          case AST_CONTROL_BUSY:
09778             if (option_verbose > 3) 
09779                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
09780             break;
09781          case AST_CONTROL_CONGESTION:
09782             if (option_verbose > 3) 
09783                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
09784             break;
09785          };
09786       }
09787       ast_frfree(f);
09788       ms = newms;
09789    }
09790    /* Hangup the channel since nothing happend */
09791    ast_hangup(chan);
09792    return NULL;
09793 }

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

Definition at line 8143 of file chan_dahdi.c.

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

Referenced by restart_monitor().

08144 {
08145    int count, res, res2, spoint, pollres=0;
08146    struct dahdi_pvt *i;
08147    struct dahdi_pvt *last = NULL;
08148    struct dahdi_pvt *doomed;
08149    time_t thispass = 0, lastpass = 0;
08150    int found;
08151    char buf[1024];
08152    struct pollfd *pfds=NULL;
08153    int lastalloc = -1;
08154    /* This thread monitors all the frame relay interfaces which are not yet in use
08155       (and thus do not have a separate thread) indefinitely */
08156    /* From here on out, we die whenever asked */
08157 #if 0
08158    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
08159       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
08160       return NULL;
08161    }
08162    ast_log(LOG_DEBUG, "Monitor starting...\n");
08163 #endif
08164    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08165 
08166    for (;;) {
08167       /* Lock the interface list */
08168       ast_mutex_lock(&iflock);
08169       if (!pfds || (lastalloc != ifcount)) {
08170          if (pfds) {
08171             free(pfds);
08172             pfds = NULL;
08173          }
08174          if (ifcount) {
08175             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
08176                ast_mutex_unlock(&iflock);
08177                return NULL;
08178             }
08179          }
08180          lastalloc = ifcount;
08181       }
08182       /* Build the stuff we're going to poll on, that is the socket of every
08183          dahdi_pvt that does not have an associated owner channel */
08184       count = 0;
08185       i = iflist;
08186       while (i) {
08187          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
08188             if (!i->owner && !i->subs[SUB_REAL].owner) {
08189                /* This needs to be watched, as it lacks an owner */
08190                pfds[count].fd = i->subs[SUB_REAL].dfd;
08191                pfds[count].events = POLLPRI;
08192                pfds[count].revents = 0;
08193                /* Message waiting or r2 channels also get watched for reading */
08194                if (i->cidspill)
08195                   pfds[count].events |= POLLIN;
08196                count++;
08197             }
08198          }
08199          i = i->next;
08200       }
08201       /* Okay, now that we know what to do, release the interface lock */
08202       ast_mutex_unlock(&iflock);
08203       
08204       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08205       pthread_testcancel();
08206       /* Wait at least a second for something to happen */
08207       res = poll(pfds, count, 1000);
08208       pthread_testcancel();
08209       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08210 
08211       /* Okay, poll has finished.  Let's see what happened.  */
08212       if (res < 0) {
08213          if ((errno != EAGAIN) && (errno != EINTR))
08214             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
08215          continue;
08216       }
08217       /* Alright, lock the interface list again, and let's look and see what has
08218          happened */
08219       ast_mutex_lock(&iflock);
08220       found = 0;
08221       spoint = 0;
08222       lastpass = thispass;
08223       thispass = time(NULL);
08224       doomed = NULL;
08225       for (i = iflist;; i = i->next) {
08226          if (doomed) {
08227             int res;
08228             res = dahdi_destroy_channel_bynum(doomed->channel);
08229             if (!res) {
08230                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
08231             }
08232             doomed = NULL;
08233          }
08234          if (!i) {
08235             break;
08236          }
08237          if (thispass != lastpass) {
08238             if (!found && ((i == last) || ((i == iflist) && !last))) {
08239                last = i;
08240                if (last) {
08241                   if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
08242                      (last->sig & __DAHDI_SIG_FXO)) {
08243                      res = ast_app_has_voicemail(last->mailbox, NULL);
08244                      if (last->msgstate != res) {
08245                         int x;
08246                         ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
08247                         x = DAHDI_FLUSH_BOTH;
08248                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
08249                         if (res2)
08250                            ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
08251                         if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
08252                            /* Turn on on hook transfer for 4 seconds */
08253                            x = 4000;
08254                            ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
08255                            last->cidlen = ast_callerid_vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
08256                            last->cidpos = 0;
08257                            last->msgstate = res;
08258                            last->onhooktime = thispass;
08259                         }
08260                         found ++;
08261                      }
08262                   }
08263                   last = last->next;
08264                }
08265             }
08266          }
08267          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
08268             if (i->radio && !i->owner)
08269             {
08270                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08271                if (res)
08272                {
08273                   if (option_debug)
08274                      ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
08275                   /* Don't hold iflock while handling init events */
08276                   ast_mutex_unlock(&iflock);
08277                   doomed = handle_init_event(i, res);
08278                   ast_mutex_lock(&iflock);   
08279                }
08280                continue;
08281             }              
08282             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
08283             if (pollres & POLLIN) {
08284                if (i->owner || i->subs[SUB_REAL].owner) {
08285 #ifdef HAVE_PRI
08286                   if (!i->pri)
08287 #endif                  
08288                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
08289                   continue;
08290                }
08291                if (!i->cidspill) {
08292                   ast_log(LOG_WARNING, "Whoa....  I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
08293                   continue;
08294                }
08295                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
08296                if (res > 0) {
08297                   /* We read some number of bytes.  Write an equal amount of data */
08298                   if (res > i->cidlen - i->cidpos) 
08299                      res = i->cidlen - i->cidpos;
08300                   res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res);
08301                   if (res2 > 0) {
08302                      i->cidpos += res2;
08303                      if (i->cidpos >= i->cidlen) {
08304                         free(i->cidspill);
08305                         i->cidspill = 0;
08306                         i->cidpos = 0;
08307                         i->cidlen = 0;
08308                      }
08309                   } else {
08310                      ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
08311                      i->msgstate = -1;
08312                   }
08313                } else {
08314                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
08315                }
08316             }
08317             if (pollres & POLLPRI) {
08318                if (i->owner || i->subs[SUB_REAL].owner) {
08319 #ifdef HAVE_PRI
08320                   if (!i->pri)
08321 #endif                  
08322                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
08323                   continue;
08324                }
08325                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08326                if (option_debug)
08327                   ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
08328                /* Don't hold iflock while handling init events */
08329                ast_mutex_unlock(&iflock);
08330                doomed = handle_init_event(i, res);
08331                ast_mutex_lock(&iflock);   
08332             }
08333          }
08334       }
08335       ast_mutex_unlock(&iflock);
08336    }
08337    /* Never reached */
08338    return NULL;
08339    
08340 }

static void enable_dtmf_detect ( struct dahdi_pvt p  )  [static]

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

04346 {
04347 #ifdef DAHDI_TONEDETECT
04348    int val;
04349 #endif
04350 
04351    if (p->channel == CHAN_PSEUDO)
04352       return;
04353 
04354    p->ignoredtmf = 0;
04355 
04356 #ifdef DAHDI_TONEDETECT
04357    val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
04358    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04359 #endif      
04360    if (!p->hardwaredtmf && p->dsp) {
04361       p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
04362       ast_dsp_set_features(p->dsp, p->dsp_features);
04363    }
04364 }

static char* event2str ( int  event  )  [static]

Definition at line 2082 of file chan_dahdi.c.

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

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

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

Definition at line 2447 of file chan_dahdi.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_rxgain().

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

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

Definition at line 2413 of file chan_dahdi.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_txgain().

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

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

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

12457 {
12458    struct dahdi_pvt *p = iflist;
12459    while (p) {
12460       if (p->channel == channel) {
12461          break;
12462       }
12463       p = p->next;
12464    }
12465    return p;
12466 }

static int get_alarms ( struct dahdi_pvt p  )  [static]

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

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

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

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

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

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

Definition at line 12271 of file chan_dahdi.c.

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

12272 {
12273    int i, j;
12274    for (i = 0; i < num_cadence; i++) {
12275       char output[1024];
12276       char tmp[16], tmp2[64];
12277       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
12278       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
12279 
12280       for (j = 0; j < 16; j++) {
12281          if (cadences[i].ringcadence[j] == 0)
12282             break;
12283          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
12284          if (cidrings[i] * 2 - 1 == j)
12285             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
12286          else
12287             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
12288          if (j != 0)
12289             strncat(output, ",", sizeof(output) - strlen(output) - 1);
12290          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
12291       }
12292       ast_cli(fd,"%s\n",output);
12293    }
12294    return 0;
12295 }

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

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

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

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

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

11680 {
11681    struct dahdi_pvt *p = NULL;
11682    int channo = 0;
11683    if (argc < 4) {
11684       return RESULT_SHOWUSAGE;
11685    }
11686    channo = (argc == 5) ? atoi(argv[4]) : -1;
11687    ast_mutex_lock(&iflock);
11688    p = iflist;
11689    while (p) {
11690       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11691          p = p->next;
11692          continue;
11693       }
11694       if ((channo != -1) && (p->channel != channo )) {
11695          p = p->next;
11696          continue;
11697       }
11698       if (ast_true(argv[3])) {
11699          openr2_chan_enable_call_files(p->r2chan);
11700       } else {
11701          openr2_chan_disable_call_files(p->r2chan);
11702       }
11703       if (channo != -1) {
11704          if (ast_true(argv[3])) {
11705             ast_cli(fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
11706          } else {
11707             ast_cli(fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
11708          }
11709          break;
11710       } else {
11711          p = p->next;
11712       }
11713    }
11714    if ((channo != -1) && !p) {
11715       ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11716    }
11717    if (channo == -1) {
11718       if (ast_true(argv[3])) {
11719          ast_cli(fd, "MFC/R2 Call files enabled for all channels.\n");
11720       } else {
11721          ast_cli(fd, "MFC/R2 Call files disabled for all channels.\n");
11722       }  
11723    }
11724    ast_mutex_unlock(&iflock);
11725    return RESULT_SUCCESS;
11726 }  

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

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

11764 {
11765    struct dahdi_pvt *p = NULL;
11766    int channo = 0;
11767    channo = (argc == 4) ? atoi(argv[3]) : -1;
11768    ast_mutex_lock(&iflock);
11769    p = iflist;
11770    while (p) {
11771       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11772          p = p->next;
11773          continue;
11774       }
11775       if ((channo != -1) && (p->channel != channo )) {
11776          p = p->next;
11777          continue;
11778       }
11779       if (!openr2_chan_set_blocked(p->r2chan)) {
11780          ast_mutex_lock(&p->lock);
11781          p->mfcr2block |= DAHDI_R2_LOCAL_BLOCK;
11782          ast_mutex_unlock(&p->lock);
11783       } else {
11784          ast_cli(fd, "MFC/R2 channel %d could not be blocked.\n", p->channel);
11785       }
11786       if (channo != -1) {
11787          break;
11788       } else {
11789          p = p->next;
11790       }
11791    }
11792    if ((channo != -1) && !p) {
11793       ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11794    }
11795    ast_mutex_unlock(&iflock);
11796    return RESULT_SUCCESS;
11797 }

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

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

11621 {
11622    struct dahdi_pvt *p = NULL;
11623    int channo = 0;
11624    char *toklevel = NULL;
11625    char *saveptr = NULL;
11626    char *logval = NULL;
11627    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
11628    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
11629    if (argc < 4) {
11630       return RESULT_SHOWUSAGE;
11631    }
11632    channo = (argc == 5) ? atoi(argv[4]) : -1;
11633    logval = ast_strdupa(argv[3]);
11634    toklevel = strtok_r(logval, ",", &saveptr);
11635    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
11636       ast_cli(fd, "Invalid MFC/R2 logging level '%s'.\n", argv[3]);
11637       return RESULT_FAILURE;
11638    } else if (OR2_LOG_NOTHING == tmplevel) {
11639       loglevel = tmplevel;
11640    } else {
11641       loglevel |= tmplevel;
11642       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
11643          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
11644             ast_cli(fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
11645             continue;
11646          }
11647          loglevel |= tmplevel;
11648       }
11649    }
11650    ast_mutex_lock(&iflock);
11651    p = iflist;
11652    while (p) {
11653       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11654          p = p->next;
11655          continue;
11656       }
11657       if ((channo != -1) && (p->channel != channo )) {
11658          p = p->next;
11659          continue;
11660       }
11661       openr2_chan_set_log_level(p->r2chan, loglevel);
11662       if (channo != -1) {
11663          ast_cli(fd, "MFC/R2 debugging set to '%s' for channel %d.\n", argv[3], p->channel);
11664          break;
11665       } else {
11666          p = p->next;
11667       }
11668    }
11669    if ((channo != -1) && !p) {
11670       ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11671    }
11672    if (channo == -1) {
11673       ast_cli(fd, "MFC/R2 debugging set to '%s' for all channels.\n", argv[3]);
11674    }
11675    ast_mutex_unlock(&iflock);
11676    return RESULT_SUCCESS;
11677 }

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

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

11729 {
11730    struct dahdi_pvt *p = NULL;
11731    int channo = 0;
11732    channo = (argc == 4) ? atoi(argv[3]) : -1;
11733    ast_mutex_lock(&iflock);
11734    p = iflist;
11735    while (p) {
11736       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11737          p = p->next;
11738          continue;
11739       }
11740       if ((channo != -1) && (p->channel != channo )) {
11741          p = p->next;
11742          continue;
11743       }
11744       if (!openr2_chan_set_idle(p->r2chan)) {
11745          ast_mutex_lock(&p->lock);
11746          p->mfcr2call = 0;
11747          p->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK;
11748          ast_mutex_unlock(&p->lock);
11749       }
11750       if (channo != -1) {
11751          break;
11752       } else {
11753          p = p->next;
11754       }
11755    }
11756    if ((channo != -1) && !p) {
11757       ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11758    }
11759    ast_mutex_unlock(&iflock);
11760    return RESULT_SUCCESS;
11761 }

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

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

11552 {
11553 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
11554    int filtertype = 0;
11555    int targetnum = 0;
11556    char channo[5];
11557    char anino[5];
11558    char dnisno[5];
11559    struct dahdi_pvt *p;
11560    openr2_context_t *r2context;
11561    openr2_variant_t r2variant;
11562    if (!((argc == 3) || (argc == 5))) {
11563       return RESULT_SHOWUSAGE;
11564    }
11565    if (argc == 5) {
11566       if (!strcasecmp(argv[3], "group")) {
11567          targetnum = atoi(argv[4]);
11568          if ((targetnum < 0) || (targetnum > 63))
11569             return RESULT_SHOWUSAGE;
11570          targetnum = 1 << targetnum;
11571          filtertype = 1;
11572       } else if (!strcasecmp(argv[3], "context")) {
11573          filtertype = 2;
11574       } else {
11575          return RESULT_SHOWUSAGE;
11576       }
11577    }
11578    ast_cli(fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
11579    ast_mutex_lock(&iflock);
11580    p = iflist;
11581    while (p) {
11582       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11583          p = p->next;
11584          continue;
11585       }
11586       if (filtertype) {
11587          switch(filtertype) {
11588          case 1: /* mfcr2 show channels group <group> */
11589             if (p->group != targetnum) {
11590                p = p->next;
11591                continue;
11592             }
11593             break;
11594          case 2: /* mfcr2 show channels context <context> */
11595             if (strcasecmp(p->context, argv[4])) {
11596                p= p->next;
11597                continue;
11598             }
11599             break;
11600          default:
11601             ;
11602          }
11603       }
11604       r2context = openr2_chan_get_context(p->r2chan);
11605       r2variant = openr2_context_get_variant(r2context);
11606       snprintf(channo, sizeof(channo), "%d", p->channel);
11607       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
11608       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
11609       ast_cli(fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant), 
11610             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",  
11611             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
11612             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
11613       p = p->next;
11614    }
11615    ast_mutex_unlock(&iflock);
11616    return RESULT_SUCCESS;
11617 #undef FORMAT
11618 }

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

Definition at line 11533 of file chan_dahdi.c.

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

11534 {
11535 #define FORMAT "%4s %40s\n"
11536    int numvariants = 0;
11537    int i;
11538    const openr2_variant_entry_t *variants;
11539    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
11540       ast_cli(fd, "Failed to get list of variants.\n");
11541       return RESULT_FAILURE;
11542    }
11543    ast_cli(fd, FORMAT, "Variant Code", "Country");
11544    for (i = 0; i < numvariants; i++) {
11545       ast_cli(fd, FORMAT, variants[i].name, variants[i].country);
11546    }
11547    return RESULT_SUCCESS;
11548 #undef FORMAT
11549 }  

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

Definition at line 11527 of file chan_dahdi.c.

References ast_cli(), and RESULT_SUCCESS.

11528 {
11529    ast_cli(fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
11530    return RESULT_SUCCESS;
11531 }

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

Definition at line 11280 of file chan_dahdi.c.

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

11281 {
11282    int span;
11283    int x;
11284    if (argc < 4) {
11285       return RESULT_SHOWUSAGE;
11286    }
11287    span = atoi(argv[3]);
11288    if ((span < 1) || (span > NUM_SPANS)) {
11289       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
11290       return RESULT_SUCCESS;
11291    }
11292    if (!pris[span-1].pri) {
11293       ast_cli(fd, "No PRI running on span %d\n", span);
11294       return RESULT_SUCCESS;
11295    }
11296    for (x = 0; x < NUM_DCHANS; x++) {
11297       if (pris[span-1].dchans[x])
11298          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11299                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11300                                                PRI_DEBUG_Q921_STATE);
11301    }
11302    ast_cli(fd, "Enabled debugging on span %d\n", span);
11303    return RESULT_SUCCESS;
11304 }

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

Definition at line 11308 of file chan_dahdi.c.

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

11309 {
11310    int span;
11311    int x;
11312    if (argc < 5)
11313       return RESULT_SHOWUSAGE;
11314    span = atoi(argv[4]);
11315    if ((span < 1) || (span > NUM_SPANS)) {
11316       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
11317       return RESULT_SUCCESS;
11318    }
11319    if (!pris[span-1].pri) {
11320       ast_cli(fd, "No PRI running on span %d\n", span);
11321       return RESULT_SUCCESS;
11322    }
11323    for (x = 0; x < NUM_DCHANS; x++) {
11324       if (pris[span-1].dchans[x])
11325          pri_set_debug(pris[span-1].dchans[x], 0);
11326    }
11327    ast_cli(fd, "Disabled debugging on span %d\n", span);
11328    return RESULT_SUCCESS;
11329 }

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

Definition at line 11331 of file chan_dahdi.c.

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

11332 {
11333    int span;
11334    int x;
11335    if (argc < 5)
11336       return RESULT_SHOWUSAGE;
11337    span = atoi(argv[4]);
11338    if ((span < 1) || (span > NUM_SPANS)) {
11339       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
11340       return RESULT_SUCCESS;
11341    }
11342    if (!pris[span-1].pri) {
11343       ast_cli(fd, "No PRI running on span %d\n", span);
11344       return RESULT_SUCCESS;
11345    }
11346    for (x = 0; x < NUM_DCHANS; x++) {
11347       if (pris[span-1].dchans[x])
11348          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11349                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11350                                                PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
11351    }
11352    ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
11353    return RESULT_SUCCESS;
11354 }

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

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

11234 {
11235    int myfd;
11236 
11237    if (!strncasecmp(argv[1], "set", 3)) {
11238       if (argc < 5) 
11239          return RESULT_SHOWUSAGE;
11240 
11241       if (ast_strlen_zero(argv[4]))
11242          return RESULT_SHOWUSAGE;
11243 
11244       myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
11245       if (myfd < 0) {
11246          ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
11247          return RESULT_SUCCESS;
11248       }
11249 
11250       ast_mutex_lock(&pridebugfdlock);
11251 
11252       if (pridebugfd >= 0)
11253          close(pridebugfd);
11254 
11255       pridebugfd = myfd;
11256       ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
11257       
11258       ast_mutex_unlock(&pridebugfdlock);
11259 
11260       ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
11261    } else {
11262       /* Assume it is unset */
11263       ast_mutex_lock(&pridebugfdlock);
11264       close(pridebugfd);
11265       pridebugfd = -1;
11266       ast_cli(fd, "PRI debug output to file disabled\n");
11267       ast_mutex_unlock(&pridebugfdlock);
11268    }
11269 
11270    return RESULT_SUCCESS;
11271 }

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

Definition at line 11437 of file chan_dahdi.c.

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

11438 {
11439    int x;
11440    int span;
11441    int count=0;
11442    int debug=0;
11443 
11444    for (span = 0; span < NUM_SPANS; span++) {
11445            if (pris[span].pri) {
11446          for (x = 0; x < NUM_DCHANS; x++) {
11447             debug = 0;
11448                if (pris[span].dchans[x]) {
11449                   debug = pri_get_debug(pris[span].dchans[x]);
11450                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" );
11451                count++;
11452             }
11453          }
11454       }
11455 
11456    }
11457    ast_mutex_lock(&pridebugfdlock);
11458    if (pridebugfd >= 0) 
11459       ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
11460    ast_mutex_unlock(&pridebugfdlock);
11461        
11462    if (!count) 
11463       ast_cli(fd, "No debug set or no PRI running\n");
11464    return RESULT_SUCCESS;
11465 }

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

Definition at line 11398 of file chan_dahdi.c.

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

11399 {
11400    int span;
11401    int x;
11402    char status[256];
11403    if (argc < 4)
11404       return RESULT_SHOWUSAGE;
11405    span = atoi(argv[3]);
11406    if ((span < 1) || (span > NUM_SPANS)) {
11407       ast_cli(fd, "Invalid span '%s'.  Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
11408       return RESULT_SUCCESS;
11409    }
11410    if (!pris[span-1].pri) {
11411       ast_cli(fd, "No PRI running on span %d\n", span);
11412       return RESULT_SUCCESS;
11413    }
11414    for (x = 0; x < NUM_DCHANS; x++) {
11415       if (pris[span-1].dchannels[x]) {
11416 #ifdef PRI_DUMP_INFO_STR
11417          char *info_str = NULL;
11418 #endif
11419          ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
11420          build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
11421          ast_cli(fd, "Status: %s\n", status);
11422 #ifdef PRI_DUMP_INFO_STR
11423          info_str = pri_dump_info_str(pris[span-1].pri);
11424          if (info_str) {
11425             ast_cli(fd, "%s", info_str);
11426             free(info_str);
11427          }
11428 #else
11429          pri_dump_info(pris[span-1].pri);
11430 #endif
11431          ast_cli(fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
11432       }
11433    }
11434    return RESULT_SUCCESS;
11435 }

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

Definition at line 11377 of file chan_dahdi.c.

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

11378 {
11379    int span;
11380    int x;
11381    char status[256];
11382    if (argc != 3)
11383       return RESULT_SHOWUSAGE;
11384 
11385    for (span = 0; span < NUM_SPANS; span++) {
11386       if (pris[span].pri) {
11387          for (x = 0; x < NUM_DCHANS; x++) {
11388             if (pris[span].dchannels[x]) {
11389                build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
11390                ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
11391             }
11392          }
11393       }
11394    }
11395    return RESULT_SUCCESS;
11396 }

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

Definition at line 11274 of file chan_dahdi.c.

References ast_cli(), and RESULT_SUCCESS.

11274                                                              {
11275    ast_cli(fd, "libpri version: %s\n", pri_get_version());
11276    return RESULT_SUCCESS;
11277 }

static int has_voicemail ( struct dahdi_pvt p  )  [static]

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

02645 {
02646 
02647    return ast_app_has_voicemail(p->mailbox, NULL);
02648 }

static void init_mfcr2_globals ( void   )  [static]

Definition at line 1263 of file chan_dahdi.c.

References AST_PTHREADT_NULL, master, NUM_SPANS, and r2links.

Referenced by dahdi_restart(), and load_module().

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

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

Definition at line 2203 of file chan_dahdi.c.

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

Referenced by conf_del().

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

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

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

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

static int load_module ( void   )  [static]

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

13869 {
13870    int res;
13871 
13872 #ifdef HAVE_PRI
13873    int y,i;
13874    memset(pris, 0, sizeof(pris));
13875    for (y = 0; y < NUM_SPANS; y++) {
13876       ast_mutex_init(&pris[y].lock);
13877       pris[y].offset = -1;
13878       pris[y].master = AST_PTHREADT_NULL;
13879       for (i = 0; i < NUM_DCHANS; i++)
13880          pris[y].fds[i] = -1;
13881    }
13882    pri_set_error(dahdi_pri_error);
13883    pri_set_message(dahdi_pri_message);
13884    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13885       ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
13886          dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
13887    }
13888    ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
13889       zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
13890 #endif
13891 #ifdef HAVE_OPENR2
13892    init_mfcr2_globals();
13893    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13894       ast_register_application(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec,
13895          dahdi_accept_r2_call_synopsis, dahdi_accept_r2_call_descrip);
13896    }
13897    ast_register_application(zap_accept_r2_call_app, zap_accept_r2_call_exec,
13898       zap_accept_r2_call_synopsis, zap_accept_r2_call_descrip);
13899 #endif
13900    if ((res = setup_dahdi(0))) {
13901       return AST_MODULE_LOAD_DECLINE;
13902    }
13903    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13904       chan_tech = &dahdi_tech;
13905    } else {
13906       chan_tech = &zap_tech;
13907    }
13908    if (ast_channel_register(chan_tech)) {
13909       ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
13910       __unload_module();
13911       return -1;
13912    }
13913 #ifdef HAVE_PRI
13914    ast_string_field_init(&inuse, 16);
13915    ast_string_field_set(&inuse, name, "GR-303InUse");
13916    ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
13917 #endif   
13918 #ifdef HAVE_OPENR2
13919    ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
13920 #endif
13921    ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
13922    
13923    memset(round_robin, 0, sizeof(round_robin));
13924    local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
13925    local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
13926    local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
13927    local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
13928    local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
13929    local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
13930    local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
13931 
13932    ast_cond_init(&ss_thread_complete, NULL);
13933 
13934    return res;
13935 }

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

Definition at line 8374 of file chan_dahdi.c.

References ast_log(), LOG_ERROR, and r2links.

Referenced by mkintf().

08375 {
08376    if ((id < 0) || (id >= (sizeof(r2links)/sizeof(r2links[0])))) {
08377       ast_log(LOG_ERROR, "No more R2 links available!.\n");
08378       return NULL;
08379    }
08380    return &r2links[id];
08381 }

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

Definition at line 9530 of file chan_dahdi.c.

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

Referenced by setup_dahdi().

09531 {
09532    struct dahdi_pvt *p;
09533    struct dahdi_mfcr2 *mfcr2 = data;
09534    /* we should be using pthread_key_create
09535       and allocate pollers dynamically.
09536       I think do_monitor() could be leaking, since it
09537       could be cancelled at any time and is not
09538       using thread keys, why?, */
09539    struct pollfd pollers[sizeof(mfcr2->pvts)];
09540    int maxsleep = 20;
09541    int res = 0;
09542    int i = 0;
09543    int pollsize = 0;
09544    int oldstate = 0;
09545    int was_idle = 0;
09546    int quit_loop = 0;
09547    /* now that we're ready to get calls, unblock our side and
09548       get current line state */
09549    for (i = 0; i < mfcr2->numchans; i++) {
09550       p = mfcr2->pvts[i];
09551       if (openr2_chan_set_idle(p->r2chan)) {
09552          ast_log(LOG_ERROR, "Failed to set channel %d in IDLE\n", p->channel);
09553       } else {
09554          ast_mutex_lock(&p->lock);
09555          mfcr2->pvts[i]->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK;
09556          mfcr2->pvts[i]->mfcr2call = 0;
09557          ast_mutex_unlock(&p->lock);
09558       }
09559       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
09560    }
09561    while(1) {
09562       /* we trust here that the mfcr2 channel list will not ever change once
09563          the module is loaded */
09564       pollsize = 0;
09565       for (i = 0; i < mfcr2->numchans; i++) {
09566          pollers[i].revents = 0;
09567          pollers[i].events = 0;
09568          if (mfcr2->pvts[i]->owner) {
09569             continue;
09570          }
09571          if (!mfcr2->pvts[i]->r2chan) {
09572             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
09573             quit_loop = 1;
09574             break;
09575          }
09576          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
09577          pollers[i].events = POLLIN | POLLPRI;
09578          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
09579          pollsize++;
09580       }
09581       if (quit_loop) {
09582          break;
09583       }
09584 
09585       if (pollsize == 0) {
09586          if (!was_idle) {
09587             ast_log(LOG_NOTICE, "Monitor thread going idle since everybody has an owner\n");
09588             was_idle = 1;
09589          }
09590          poll(NULL, 0, maxsleep);
09591          continue;
09592       }
09593       was_idle = 0;
09594 
09595       /* probably poll() is a valid cancel point, lets just be on the safe side
09596          by calling pthread_testcancel */
09597       pthread_testcancel();
09598       res = poll(pollers, pollsize, maxsleep);
09599       pthread_testcancel();
09600       if ((res < 0) && (errno != EINTR)) {
09601          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
09602          break;
09603       } 
09604       /* do we want to allow to cancel while processing events? */
09605       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
09606       for (i = 0; i < mfcr2->numchans; i++) {
09607          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
09608             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
09609          }
09610       }
09611       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
09612    }
09613    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
09614    return 0;
09615 }

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

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

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

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

Definition at line 6222 of file chan_dahdi.c.

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

Referenced by dahdi_write().

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

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

Definition at line 6713 of file chan_dahdi.c.

References ast_waitfordigit().

Referenced by ss_thread().

06714 {
06715    char c;
06716 
06717    *str = 0; /* start with empty output buffer */
06718    for (;;)
06719    {
06720       /* Wait for the first digit (up to specified ms). */
06721       c = ast_waitfordigit(chan, ms);
06722       /* if timeout, hangup or error, return as such */
06723       if (c < 1)
06724          return c;
06725       *str++ = c;
06726       *str = 0;
06727       if (strchr(term, c))
06728          return 1;
06729    }
06730 }

static int pri_active_dchan_fd ( struct dahdi_pri pri  )  [static]

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

03385 {
03386    int x = -1;
03387 
03388    for (x = 0; x < NUM_DCHANS; x++) {
03389       if ((pri->dchans[x] == pri->pri))
03390          break;
03391    }
03392 
03393    return pri->fds[x];
03394 }

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

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

03355 {
03356    bearer->owner = &inuse;
03357    bearer->realcall = crv;
03358    crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
03359    if (crv->subs[SUB_REAL].owner)
03360       crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
03361    crv->bearer = bearer;
03362    crv->call = bearer->call;
03363    crv->pri = pri;
03364    return 0;
03365 }

static int pri_check_restart ( struct dahdi_pri pri  )  [static]

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

09883 {
09884    do {
09885       pri->resetpos++;
09886    } while ((pri->resetpos < pri->numchans) &&
09887        (!pri->pvts[pri->resetpos] ||
09888         pri->pvts[pri->resetpos]->call ||
09889         pri->pvts[pri->resetpos]->resetting));
09890    if (pri->resetpos < pri->numchans) {
09891       /* Mark the channel as resetting and restart it */
09892       pri->pvts[pri->resetpos]->resetting = 1;
09893       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
09894    } else {
09895       pri->resetting = 0;
09896       time(&pri->lastreset);
09897    }
09898    return 0;
09899 }

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

Definition at line 8494 of file chan_dahdi.c.

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

Referenced by setup_dahdi().

08495 {
08496    if (pris[span].mastertrunkgroup) {
08497       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);
08498       return -1;
08499    }
08500    pris[span].mastertrunkgroup = trunkgroup;
08501    pris[span].prilogicalspan = logicalspan;
08502    return 0;
08503 }

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

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

08432 {
08433    struct dahdi_spaninfo si;
08434    struct dahdi_params p;
08435    int fd;
08436    int span;
08437    int ospan=0;
08438    int x,y;
08439    for (x = 0; x < NUM_SPANS; x++) {
08440       if (pris[x].trunkgroup == trunkgroup) {
08441          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
08442          return -1;
08443       }
08444    }
08445    for (y = 0; y < NUM_DCHANS; y++) {
08446       if (!channels[y]) 
08447          break;
08448       memset(&si, 0, sizeof(si));
08449       memset(&p, 0, sizeof(p));
08450       fd = open(DAHDI_FILE_CHANNEL, O_RDWR);
08451       if (fd < 0) {
08452          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
08453          return -1;
08454       }
08455       x = channels[y];
08456       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
08457          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
08458          close(fd);
08459          return -1;
08460       }
08461       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
08462          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
08463          return -1;
08464       }
08465       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
08466          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
08467          close(fd);
08468          return -1;
08469       }
08470       span = p.spanno - 1;
08471       if (pris[span].trunkgroup) {
08472          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
08473          close(fd);
08474          return -1;
08475       }
08476       if (pris[span].pvts[0]) {
08477          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
08478          close(fd);
08479          return -1;
08480       }
08481       if (!y) {
08482          pris[span].trunkgroup = trunkgroup;
08483          pris[span].offset = channels[y] - p.chanpos;
08484          ospan = span;
08485       }
08486       pris[ospan].dchannels[y] = channels[y];
08487       pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
08488       pris[span].span = span + 1;
08489       close(fd);
08490    }
08491    return 0;   
08492 }

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

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

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

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

Definition at line 9620 of file chan_dahdi.c.

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

09621 {
09622    struct dahdi_pvt *p;
09623    p = pri->crvs;
09624    while (p) {
09625       if (p->channel == crv)
09626          return p;
09627       p = p->next;
09628    }
09629    return NULL;
09630 }

static int pri_find_dchan ( struct dahdi_pri pri  )  [static]

Definition at line 3396 of file chan_dahdi.c.

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

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

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

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

09244 {
09245    int x;
09246    if (backwards)
09247       x = pri->numchans;
09248    else
09249       x = 0;
09250    for (;;) {
09251       if (backwards && (x < 0))
09252          break;
09253       if (!backwards && (x >= pri->numchans))
09254          break;
09255       if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
09256          ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n", 
09257             pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09258          return x;
09259       }
09260       if (backwards)
09261          x--;
09262       else
09263          x++;
09264    }
09265    return -1;
09266 }

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

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

09634 {
09635    int x;
09636    int span = PRI_SPAN(channel);
09637    int spanfd;
09638    struct dahdi_params param;
09639    int principle = -1;
09640    int explicit = PRI_EXPLICIT(channel);
09641    channel = PRI_CHANNEL(channel);
09642 
09643    if (!explicit) {
09644       spanfd = pri_active_dchan_fd(pri);
09645       memset(&param, 0, sizeof(param));
09646       if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
09647          return -1;
09648       span = pris[param.spanno - 1].prilogicalspan;
09649    }
09650 
09651    for (x = 0; x < pri->numchans; x++) {
09652       if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
09653          principle = x;
09654          break;
09655       }
09656    }
09657    
09658    return principle;
09659 }

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

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

09662 {
09663    int x;
09664    struct dahdi_pvt *crv;
09665    if (!c) {
09666       if (principle < 0)
09667          return -1;
09668       return principle;
09669    }
09670    if ((principle > -1) && 
09671       (principle < pri->numchans) && 
09672       (pri->pvts[principle]) && 
09673       (pri->pvts[principle]->call == c))
09674       return principle;
09675    /* First, check for other bearers */
09676    for (x = 0; x < pri->numchans; x++) {
09677       if (!pri->pvts[x])
09678          continue;
09679       if (pri->pvts[x]->call == c) {
09680          /* Found our call */
09681          if (principle != x) {
09682             struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
09683 
09684             if (option_verbose > 2)
09685                ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
09686                   old->channel, new->channel);
09687             if (new->owner) {
09688                ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
09689                   old->channel, new->channel, new->channel);
09690                return -1;
09691             }
09692             /* Fix it all up now */
09693             new->owner = old->owner;
09694             old->owner = NULL;
09695             if (new->owner) {
09696                ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
09697                new->owner->tech_pvt = new;
09698                new->owner->fds[0] = new->subs[SUB_REAL].dfd;
09699                new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
09700                old->subs[SUB_REAL].owner = NULL;
09701             } else
09702                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);
09703             new->call = old->call;
09704             old->call = NULL;
09705 
09706             /* Copy any DSP that may be present */
09707             new->dsp = old->dsp;
09708             new->dsp_features = old->dsp_features;
09709             old->dsp = NULL;
09710             old->dsp_features = 0;
09711          }
09712          return principle;
09713       }
09714    }
09715    /* Now check for a CRV with no bearer */
09716    crv = pri->crvs;
09717    while (crv) {
09718       if (crv->call == c) {
09719          /* This is our match...  Perform some basic checks */
09720          if (crv->bearer)
09721             ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
09722          else if (pri->pvts[principle]->owner) 
09723             ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
09724          else {
09725             /* Looks good.  Drop the pseudo channel now, clear up the assignment, and
09726                wakeup the potential sleeper */
09727             dahdi_close_sub(crv, SUB_REAL);
09728             pri->pvts[principle]->call = crv->call;
09729             pri_assign_bearer(crv, pri, pri->pvts[principle]);
09730             ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
09731                            pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
09732                            pri->trunkgroup, crv->channel);
09733             wakeup_sub(crv, SUB_REAL, pri);
09734          }
09735          return principle;
09736       }
09737       crv = crv->next;
09738    }
09739    ast_log(LOG_WARNING, "Call specified, but not found?\n");
09740    return -1;
09741 }

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

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

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

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

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

09902 {
09903    int x;
09904    int redo;
09905    ast_mutex_unlock(&pri->lock);
09906    ast_mutex_lock(&p->lock);
09907    do {
09908       redo = 0;
09909       for (x = 0; x < 3; x++) {
09910          while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
09911             redo++;
09912             DEADLOCK_AVOIDANCE(&p->lock);
09913          }
09914          if (p->subs[x].owner) {
09915             ast_queue_hangup(p->subs[x].owner);
09916             ast_mutex_unlock(&p->subs[x].owner->lock);
09917          }
09918       }
09919    } while (redo);
09920    ast_mutex_unlock(&p->lock);
09921    ast_mutex_lock(&pri->lock);
09922    return 0;
09923 }

static int pri_is_up ( struct dahdi_pri pri  )  [static]

Definition at line 3344 of file chan_dahdi.c.

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

Referenced by pri_dchannel().

03345 {
03346    int x;
03347    for (x = 0; x < NUM_DCHANS; x++) {
03348       if (pri->dchanavail[x] == DCHAN_AVAILABLE)
03349          return 1;
03350    }
03351    return 0;
03352 }

static char* pri_order ( int  level  )  [static]

Definition at line 3367 of file chan_dahdi.c.

Referenced by handle_pri_show_span().

03368 {
03369    switch (level) {
03370    case 0:
03371       return "Primary";
03372    case 1:
03373       return "Secondary";
03374    case 2:
03375       return "Tertiary";
03376    case 3:
03377       return "Quaternary";
03378    default:
03379       return "<Unknown>";
03380    }     
03381 }

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

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

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

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

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

08386 {
08387    int x;
08388    int trunkgroup;
08389    /* Get appropriate trunk group if there is one */
08390    trunkgroup = pris[*span].mastertrunkgroup;
08391    if (trunkgroup) {
08392       /* Select a specific trunk group */
08393       for (x = 0; x < NUM_SPANS; x++) {
08394          if (pris[x].trunkgroup == trunkgroup) {
08395             *span = x;
08396             return 0;
08397          }
08398       }
08399       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
08400       *span = -1;
08401    } else {
08402       if (pris[*span].trunkgroup) {
08403          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
08404          *span = -1;
08405       } else if (pris[*span].mastertrunkgroup) {
08406          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
08407          *span = -1;
08408       } else {
08409          if (si->totalchans == 31) {
08410             /* E1 */
08411             pris[*span].dchannels[0] = 16 + offset;
08412          } else if (si->totalchans == 24) {
08413             /* T1 or J1 */
08414             pris[*span].dchannels[0] = 24 + offset;
08415          } else if (si->totalchans == 3) {
08416             /* BRI */
08417             pris[*span].dchannels[0] = 3 + offset;
08418          } else {
08419             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);
08420             *span = -1;
08421             return 0;
08422          }
08423          pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
08424          pris[*span].offset = offset;
08425          pris[*span].span = *span + 1;
08426       }
08427    }
08428    return 0;
08429 }

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

Definition at line 12884 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_POLARITY, CID_START_RING, dahdi_pvt::context, ringContextData::contextData, DAHDI_OVERLAPDIAL_BOTH, DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_NONE, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_pvt::dahditrcallerid, dahdi_pri::dialplan, drings, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echotraining, dahdi_pri::facilityenable, global_jbconf, dahdi_pvt::group, dahdi_pvt::hanguponpolarityswitch, HAVE_PRI, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pri::idledial, dahdi_pri::idleext, dahdi_pvt::immediate, dahdi_pri::inbanddisconnect, dahdi_pri::internationalprefix, dahdi_pvt::language, ast_variable::lineno, dahdi_pri::localdialplan, dahdi_pri::localprefix, LOG_ERROR, dahdi_pvt::mailbox, MAX_CHANLIST_LEN, dahdi_pri::minidle, dahdi_pri::minunused, dahdi_pvt::mohinterpret, dahdi_pvt::mohsuggest, ast_variable::name, dahdi_pri::nationalprefix, ast_variable::next, dahdi_pri::nodetype, dahdi_pri::nsf, option_verbose, dahdi_pvt::outsigmod, dahdi_pri::overlapdial, dahdi_pvt::pickupgroup, dahdi_pvt::polarityonanswerdelay, dahdi_chan_conf::pri, dahdi_pvt::priexclusive, dahdi_pvt::priindication_oob, dahdi_pri::privateprefix, dahdi_pvt::pulse, dahdi_pvt::radio, READ_SIZE, dahdi_pri::resetinterval, dahdi_pvt::restrictcid, distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::rxgain, dahdi_pvt::sendcalleridafter, dahdi_pvt::sig, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SFWINK, dahdi_pvt::silencethreshold, dahdi_chan_conf::smdi_port, dahdi_pvt::stripmsd, dahdi_pri::switchtype, dahdi_pvt::threewaycalling, dahdi_chan_conf::timing, dahdi_pvt::tonezone, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, dahdi_pvt::txgain, dahdi_pri::unknownprefix, dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, dahdi_pvt::use_smdi, dahdi_pvt::usedistinctiveringdetection, ast_variable::value, and VERBOSE_PREFIX_3.

Referenced by setup_dahdi().

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

static char* redirectingreason2str ( int  redirectingreason  )  [static]

Definition at line 9925 of file chan_dahdi.c.

Referenced by __oh323_new().

09926 {
09927    switch (redirectingreason) {
09928    case 0:
09929       return "UNKNOWN";
09930    case 1:
09931       return "BUSY";
09932    case 2:
09933       return "NO_REPLY";
09934    case 0xF:
09935       return "UNCONDITIONAL";
09936    default:
09937       return "NOREDIRECT";
09938    }
09939 }

static int reload ( void   )  [static]

Definition at line 14038 of file chan_dahdi.c.

References ast_log(), and setup_dahdi().

14039 {
14040    int res = 0;
14041 
14042    res = setup_dahdi(1);
14043    if (res) {
14044       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
14045       return -1;
14046    }
14047    return 0;
14048 }

static int reset_conf ( struct dahdi_pvt p  )  [static]

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

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

static int restart_monitor ( void   )  [static]

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

08343 {
08344    pthread_attr_t attr;
08345    pthread_attr_init(&attr);
08346    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08347    /* If we're supposed to be stopped -- stay stopped */
08348    if (monitor_thread == AST_PTHREADT_STOP)
08349       return 0;
08350    ast_mutex_lock(&monlock);
08351    if (monitor_thread == pthread_self()) {
08352       ast_mutex_unlock(&monlock);
08353       ast_log(LOG_WARNING, "Cannot kill myself\n");
08354       return -1;
08355    }
08356    if (monitor_thread != AST_PTHREADT_NULL) {
08357       /* Wake up the thread */
08358       pthread_kill(monitor_thread, SIGURG);
08359    } else {
08360       /* Start a new monitor */
08361       if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
08362          ast_mutex_unlock(&monlock);
08363          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08364          pthread_attr_destroy(&attr);
08365          return -1;
08366       }
08367    }
08368    ast_mutex_unlock(&monlock);
08369    pthread_attr_destroy(&attr);
08370    return 0;
08371 }

static int restore_conference ( struct dahdi_pvt p  )  [static]

Definition at line 2610 of file chan_dahdi.c.

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

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

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

static int restore_gains ( struct dahdi_pvt p  )  [static]

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

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

static int save_conference ( struct dahdi_pvt p  )  [static]

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

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

static int send_callerid ( struct dahdi_pvt p  )  [static]

Definition at line 2650 of file chan_dahdi.c.

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

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

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

static int send_cwcidspill ( struct dahdi_pvt p  )  [static]

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

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

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

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

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

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

Definition at line 2518 of file chan_dahdi.c.

References set_actual_rxgain(), and set_actual_txgain().

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

02519 {
02520    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02521 }

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

Definition at line 2500 of file chan_dahdi.c.

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

Referenced by dahdi_setoption(), and set_actual_gain().

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

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

Definition at line 2481 of file chan_dahdi.c.

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

Referenced by dahdi_setoption(), and set_actual_gain().

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

static int setup_dahdi ( int  reload  )  [static]

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

13707 {
13708    struct ast_config *cfg;
13709    struct ast_variable *v;
13710    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
13711    int res;
13712 
13713 #ifdef HAVE_PRI
13714    char *c;
13715    int spanno;
13716    int i, x;
13717    int logicalspan;
13718    int trunkgroup;
13719    int dchannels[NUM_DCHANS];
13720 #endif
13721 
13722 #ifdef HAVE_ZAPTEL
13723    int load_from_zapata_conf = 1;
13724 #else
13725    int load_from_zapata_conf = (*dahdi_chan_mode == CHAN_ZAP_MODE);
13726 #endif
13727 
13728    if (load_from_zapata_conf) {
13729       if (!(cfg = ast_config_load("zapata.conf"))) {
13730          ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
13731          return 0;
13732       }
13733    } else {
13734       if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
13735          ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
13736          return 0;
13737       }
13738    }
13739 
13740    /* It's a little silly to lock it, but we mind as well just to be sure */
13741    ast_mutex_lock(&iflock);
13742 #ifdef HAVE_PRI
13743    if (reload != 1) {
13744       /* Process trunkgroups first */
13745       v = ast_variable_browse(cfg, "trunkgroups");
13746       while (v) {
13747          if (!strcasecmp(v->name, "trunkgroup")) {
13748             trunkgroup = atoi(v->value);
13749             if (trunkgroup > 0) {
13750                if ((c = strchr(v->value, ','))) {
13751                   i = 0;
13752                   memset(dchannels, 0, sizeof(dchannels));
13753                   while (c && (i < NUM_DCHANS)) {
13754                      dchannels[i] = atoi(c + 1);
13755                      if (dchannels[i] < 0) {
13756                         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);
13757                      } else
13758                         i++;
13759                      c = strchr(c + 1, ',');
13760                   }
13761                   if (i) {
13762                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
13763                         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);
13764                      } else if (option_verbose > 1)
13765                         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");
13766                   } else
13767                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
13768                } else
13769                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
13770             } else
13771                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
13772          } else if (!strcasecmp(v->name, "spanmap")) {
13773             spanno = atoi(v->value);
13774             if (spanno > 0) {
13775                if ((c = strchr(v->value, ','))) {
13776                   trunkgroup = atoi(c + 1);
13777                   if (trunkgroup > 0) {
13778                      if ((c = strchr(c + 1, ','))) 
13779                         logicalspan = atoi(c + 1);
13780                      else
13781                         logicalspan = 0;
13782                      if (logicalspan >= 0) {
13783                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
13784                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
13785                         } else if (option_verbose > 1) 
13786                            ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
13787                      } else
13788                         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);
13789                   } else
13790                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
13791                } else
13792                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
13793             } else
13794                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
13795          } else {
13796             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
13797          }
13798          v = v->next;
13799       }
13800    }
13801 #endif
13802    
13803    /* Copy the default jb config over global_jbconf */
13804    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
13805 
13806    v = ast_variable_browse(cfg, "channels");
13807    res = process_dahdi(&conf, "", v, reload, 0);
13808    ast_mutex_unlock(&iflock);
13809    ast_config_destroy(cfg);
13810    if (res)
13811       return res;
13812    cfg = ast_config_load("users.conf");
13813    if (cfg) {
13814       char *cat;
13815       process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
13816       for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
13817          if (!strcasecmp(cat, "general"))
13818             continue;
13819          if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) {
13820             struct dahdi_chan_conf sect_conf;
13821             memcpy(&sect_conf, &conf, sizeof(sect_conf));
13822 
13823             process_dahdi(&sect_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
13824          }
13825       }
13826       ast_config_destroy(cfg);
13827    }
13828 #ifdef HAVE_PRI
13829    if (reload != 1) {
13830       for (x = 0; x < NUM_SPANS; x++) {
13831          if (pris[x].pvts[0]) {
13832             if (start_pri(pris + x)) {
13833                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
13834                return -1;
13835             } else if (option_verbose > 1)
13836                ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
13837          }
13838       }
13839    }
13840 #endif
13841 #ifdef HAVE_OPENR2
13842    if (reload != 1) {
13843       int x;
13844       for (x = 0; x < NUM_SPANS; x++) {
13845          if (r2links[x].protocol_context) {
13846             if (ast_pthread_create(&r2links[x].master, NULL, mfcr2_monitor, &r2links[x])) {
13847                ast_log(LOG_ERROR, "Unable to start R2 context on span %d\n", x + 1);
13848                return -1;
13849             } else {
13850                ast_verbose(VERBOSE_PREFIX_2 "Starting R2 context on span %d\n", x + 1);
13851             }
13852          }
13853       }
13854    }
13855 #endif
13856    /* And start the monitor for the first time */
13857    restart_monitor();
13858    return 0;
13859 }

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

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

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

static int start_pri ( struct dahdi_pri pri  )  [static]

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

11116 {
11117    int res, x;
11118    struct dahdi_params p;
11119    struct dahdi_bufferinfo bi;
11120    struct dahdi_spaninfo si;
11121    int i;
11122    
11123    for (i = 0; i < NUM_DCHANS; i++) {
11124       if (!pri->dchannels[i])
11125          break;
11126       pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600);
11127       x = pri->dchannels[i];
11128       if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
11129          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
11130          return -1;
11131       }
11132       memset(&p, 0, sizeof(p));
11133       res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
11134       if (res) {
11135          dahdi_close_pri_fd(pri, i);
11136          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
11137          return -1;
11138       }
11139       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
11140          dahdi_close_pri_fd(pri, i);
11141          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.  See /etc/dahdi/system.conf\n", x);
11142          return -1;
11143       }
11144       memset(&si, 0, sizeof(si));
11145       res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
11146       if (res) {
11147          dahdi_close_pri_fd(pri, i);
11148          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
11149       }
11150       if (!si.alarms)
11151          pri->dchanavail[i] |= DCHAN_NOTINALARM;
11152       else
11153          pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
11154       memset(&bi, 0, sizeof(bi));
11155       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
11156       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
11157       bi.numbufs = 32;
11158       bi.bufsize = 1024;
11159       if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
11160          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
11161          dahdi_close_pri_fd(pri, i);
11162          return -1;
11163       }
11164       pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
11165       /* Force overlap dial if we're doing GR-303! */
11166       if (pri->switchtype == PRI_SWITCH_GR303_TMC)
11167          pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
11168       pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
11169 #ifdef HAVE_PRI_INBANDDISCONNECT
11170       pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
11171 #endif
11172       /* Enslave to master if appropriate */
11173       if (i)
11174          pri_enslave(pri->dchans[0], pri->dchans[i]);
11175       if (!pri->dchans[i]) {
11176          dahdi_close_pri_fd(pri, i);
11177          ast_log(LOG_ERROR, "Unable to create PRI structure\n");
11178          return -1;
11179       }
11180       pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
11181       pri_set_nsf(pri->dchans[i], pri->nsf);
11182 #ifdef PRI_GETSET_TIMERS
11183       for (x = 0; x < PRI_MAX_TIMERS; x++) {
11184          if (pritimers[x] != 0)
11185             pri_set_timer(pri->dchans[i], x, pritimers[x]);
11186       }
11187 #endif
11188    }
11189    /* Assume primary is the one we use */
11190    pri->pri = pri->dchans[0];
11191    pri->resetpos = -1;
11192    if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
11193       for (i = 0; i < NUM_DCHANS; i++) {
11194          if (!pri->dchannels[i])
11195             break;
11196          dahdi_close_pri_fd(pri, i);
11197       }
11198       ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
11199       return -1;
11200    }
11201    return 0;
11202 }

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

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

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

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

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

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

static int unload_module ( void   )  [static]

Definition at line 12776 of file chan_dahdi.c.

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

12777 {
12778 #ifdef HAVE_PRI      
12779    int y;
12780    for (y = 0; y < NUM_SPANS; y++)
12781       ast_mutex_destroy(&pris[y].lock);
12782 #endif
12783    return __unload_module();
12784 }

static int update_conf ( struct dahdi_pvt p  )  [static]

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

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

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

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

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

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

Definition at line 3539 of file chan_dahdi.c.

References dahdi_accept_r2_call_exec().

Referenced by load_module().

03540 {
03541    return dahdi_accept_r2_call_exec(chan, data);
03542 }

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

Definition at line 12600 of file chan_dahdi.c.

References __action_dialoffhook(), and s.

12601 {
12602    return __action_dialoffhook(s, m, 1);
12603 }

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

Definition at line 12500 of file chan_dahdi.c.

References __action_dnd(), and s.

12501 {
12502    return __action_dnd(s, m, 1, 0);
12503 }

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

Definition at line 12490 of file chan_dahdi.c.

References __action_dnd(), and s.

12491 {
12492    return __action_dnd(s, m, 1, 1);
12493 }

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

Definition at line 12679 of file chan_dahdi.c.

References __action_restart(), and s.

12680 {
12681    return __action_restart(s, m, 1);
12682 }

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

Definition at line 12655 of file chan_dahdi.c.

References __action_showchannels(), and s.

12656 {
12657    return __action_showchannels(s, m, 1);
12658 }

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

Definition at line 12529 of file chan_dahdi.c.

References __action_transfer(), and s.

12530 {
12531    return __action_transfer(s, m, 1);
12532 }

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

Definition at line 12557 of file chan_dahdi.c.

References __action_transferhangup(), and s.

12558 {
12559    return __action_transferhangup(s, m, 1);
12560 }

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

Definition at line 3338 of file chan_dahdi.c.

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

Referenced by load_module().

03339 {
03340    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);  
03341    return send_keypad_facility_exec(chan, data);
03342 }


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

int alarm

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

struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static]

Definition at line 1163 of file chan_dahdi.c.

struct ast_channel_tech* chan_tech [static]

Definition at line 1131 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 1174 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 12396 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 12401 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 12381 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 12391 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 12386 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 12406 of file chan_dahdi.c.

char* dahdi_accept_r2_call_app = "DAHDIAcceptR2Call" [static]

Definition at line 3424 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 3430 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 3427 of file chan_dahdi.c.

struct ast_cli_entry dahdi_cli[] [static]

Definition at line 12411 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct ast_cli_entry dahdi_mfcr2_cli[] [static]

Definition at line 11827 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct ast_cli_entry dahdi_pri_cli[] [static]

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

openr2_event_interface_t dahdi_r2_event_iface [static]

Definition at line 1729 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 11821 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 11808 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 11816 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 11805 of file chan_dahdi.c.

openr2_transcoder_interface_t dahdi_r2_transcode_iface [static]

Initial value:

Definition at line 1760 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 11802 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 11799 of file chan_dahdi.c.

char dahdi_restart_usage[] [static]

Definition at line 12374 of file chan_dahdi.c.

char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static]

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

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

Definition at line 3283 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 12267 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 12366 of file chan_dahdi.c.

struct ast_channel_tech dahdi_tech [static]

Definition at line 1089 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 12370 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 434 of file chan_dahdi.c.

Referenced by process_dahdi().

char* events[] [static]

Definition at line 2037 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 233 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 236 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 245 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 242 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 224 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 239 of file chan_dahdi.c.

Referenced by mgcp_ss(), and skinny_ss().

int mfcr2_cur_accept_on_offer = 1 [static]

Definition at line 331 of file chan_dahdi.c.

int mfcr2_cur_allow_collect_calls = 0 [static]

Definition at line 330 of file chan_dahdi.c.

int mfcr2_cur_call_files = 0 [static]

Definition at line 329 of file chan_dahdi.c.

openr2_calling_party_category_t mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER [static]

Definition at line 346 of file chan_dahdi.c.

int mfcr2_cur_charge_calls = 1 [static]

Definition at line 332 of file chan_dahdi.c.

int mfcr2_cur_context_index = 0 [static]

Definition at line 328 of file chan_dahdi.c.

int mfcr2_cur_double_answer = 0 [static]

Definition at line 334 of file chan_dahdi.c.

int mfcr2_cur_forced_release = 0 [static]

Definition at line 333 of file chan_dahdi.c.

int mfcr2_cur_get_ani_first = -1 [static]

Definition at line 326 of file chan_dahdi.c.

int mfcr2_cur_immediate_accept = -1 [static]

Definition at line 335 of file chan_dahdi.c.

char mfcr2_cur_logdir[OR2_MAX_PATH] [static]

Definition at line 343 of file chan_dahdi.c.

openr2_log_level_t mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING [static]

Definition at line 345 of file chan_dahdi.c.

int mfcr2_cur_max_ani = 10 [static]

Definition at line 324 of file chan_dahdi.c.

int mfcr2_cur_max_dnis = 4 [static]

Definition at line 325 of file chan_dahdi.c.

int mfcr2_cur_metering_pulse_timeout = -1 [static]

Definition at line 323 of file chan_dahdi.c.

int mfcr2_cur_mfback_timeout = -1 [static]

Definition at line 322 of file chan_dahdi.c.

char mfcr2_cur_r2proto_file[OR2_MAX_PATH] [static]

Definition at line 344 of file chan_dahdi.c.

int mfcr2_cur_skip_category = -1 [static]

Definition at line 327 of file chan_dahdi.c.

openr2_variant_t mfcr2_cur_variant = OR2_VAR_UNKNOWN [static]

Definition at line 321 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 257 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 253 of file chan_dahdi.c.

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

char* name

Definition at line 2061 of file chan_dahdi.c.

int num_cadence = 4 [static]

Definition at line 1160 of file chan_dahdi.c.

int num_restart_pending = 0 [static]

Definition at line 262 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 11467 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 11471 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 11475 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 11479 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 11483 of file chan_dahdi.c.

int pridebugfd = -1 [static]

Definition at line 228 of file chan_dahdi.c.

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

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

struct dahdi_pri pris[NUM_SPANS] [static]

Definition at line 407 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 320 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 260 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 309 of file chan_dahdi.c.

struct dahdi_pvt* round_robin[32]

Definition at line 1139 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 12362 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 12358 of file chan_dahdi.c.

ast_cond_t ss_thread_complete [static]

Definition at line 258 of file chan_dahdi.c.

int ss_thread_count = 0 [static]

Definition at line 261 of file chan_dahdi.c.

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

Definition at line 259 of file chan_dahdi.c.

Referenced by dahdi_restart(), and ss_thread().

char* subnames[] [static]

Initial value:

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

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

char* zap_accept_r2_call_app = "ZapAcceptR2Call" [static]

Definition at line 3425 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 3434 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 3428 of file chan_dahdi.c.

char* zap_send_keypad_facility_app = "ZapSendKeypadFacility" [static]

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

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

Definition at line 3284 of file chan_dahdi.c.

struct ast_channel_tech zap_tech [static]

Definition at line 1110 of file chan_dahdi.c.

Referenced by load_module().


Generated on Thu Dec 17 13:33:47 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7