Thu Mar 25 10:39:21 2010

Asterisk developer's documentation


chan_dahdi.c File Reference

DAHDI Pseudo TDM interface. More...

#include "asterisk.h"
#include <stdio.h>
#include <string.h>
#include <sys/signal.h>
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <math.h>
#include <ctype.h>
#include <libpri.h>
#include <openr2.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/file.h"
#include "asterisk/ulaw.h"
#include "asterisk/alaw.h"
#include "asterisk/callerid.h"
#include "asterisk/adsi.h"
#include "asterisk/cli.h"
#include "asterisk/cdr.h"
#include "asterisk/features.h"
#include "asterisk/musiconhold.h"
#include "asterisk/say.h"
#include "asterisk/tdd.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/astdb.h"
#include "asterisk/manager.h"
#include "asterisk/causes.h"
#include "asterisk/term.h"
#include "asterisk/utils.h"
#include "asterisk/transcap.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/smdi.h"
#include "asterisk/astobj.h"
#include "asterisk/dahdi_compat.h"
#include "asterisk/tonezone_compat.h"

Go to the source code of this file.

Data Structures

struct  dahdi_chan_conf
 Channel configuration from chan_dahdi.conf . This struct is used for parsing the [channels] section of chan_dahdi.conf. Generally there is a field here for every possible configuration item. More...
struct  dahdi_distRings
struct  dahdi_mfcr2
struct  dahdi_pri
struct  dahdi_pvt
struct  dahdi_subchannel
struct  distRingData
struct  ringContextData

Defines

#define ASCII_BYTES_PER_CHAR   80
#define AST_LAW(p)   (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
#define CALLWAITING_REPEAT_SAMPLES   ( (10000 * 8) / READ_SIZE)
#define CALLWAITING_SILENT_SAMPLES   ( (300 * 8) / READ_SIZE)
#define CANBUSYDETECT(p)   (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
#define CANPROGRESSDETECT(p)   (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
#define CHAN_PSEUDO   -2
#define CHANNEL_PSEUDO   -12
#define CIDCW_EXPIRE_SAMPLES   ( (500 * 8) / READ_SIZE)
#define CONF_USER_REAL   (1 << 0)
#define CONF_USER_THIRDCALL   (1 << 1)
#define DAHDI_EVENT_DTMFDOWN   0
#define DAHDI_EVENT_DTMFUP   0
#define DAHDI_OVERLAPDIAL_BOTH   (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
#define DAHDI_OVERLAPDIAL_INCOMING   2
#define DAHDI_OVERLAPDIAL_NONE   0
#define DAHDI_OVERLAPDIAL_OUTGOING   1
#define DAHDI_R2_LOCAL_BLOCK   (1 << 1)
#define DAHDI_R2_REMOTE_BLOCK   (1 << 0)
#define DCHAN_AVAILABLE   (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
#define DCHAN_NOTINALARM   (1 << 1)
#define DCHAN_PROVISIONED   (1 << 0)
#define DCHAN_UP   (1 << 2)
#define DEFAULT_CIDRINGS   1
 Typically, how many rings before we should send Caller*ID.
#define DEFAULT_PRI_DEBUG   0
#define DEFAULT_RINGT   ( (8000 * 8) / READ_SIZE)
#define END_SILENCE_LEN   400
#define FORMAT   "%-40.40s %-10.10s %-10d %-10d %-10d\n"
#define FORMAT   "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
#define FORMAT   "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
#define FORMAT   "%4s %40s\n"
#define FORMAT2   "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
#define FORMAT2   "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
#define GET_CHANNEL(p)   ((p)->bearer ? (p)->bearer->channel : p->channel)
#define HANGUP   1
#define HEADER_LEN   ((HEADER_MS + TRAILER_MS) * 8)
#define HEADER_MS   50
#define ISTRUNK(p)
#define local_astman_ack(s, m, msg, zap)   do { if (!zap) astman_send_ack(s, m, "DAHDI" msg); else astman_send_ack(s, m, "Zap" msg); } while (0)
#define local_astman_header(m, hdr, zap)   astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
#define local_astman_register(a, b, c, d)
#define local_astman_unregister(a)
#define MASK_AVAIL   (1 << 0)
#define MASK_INUSE   (1 << 1)
#define MAX_CHANLIST_LEN   80
#define MAX_CHANNELS   672
#define MAX_SLAVES   4
#define MIN_MS_SINCE_FLASH   ( (2000) )
#define NEED_MFDETECT(p)   (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
 Signaling types that need to use MF detection should be placed in this macro.
#define NUM_CADENCE_MAX   25
#define NUM_DCHANS   4
#define NUM_SPANS   32
#define POLARITY_IDLE   0
#define POLARITY_REV   1
#define PRI_CHANNEL(p)   ((p) & 0xff)
#define PRI_EXPLICIT(p)   (((p) >> 16) & 0x01)
#define PRI_SPAN(p)   (((p) >> 8) & 0xff)
#define PVT_TO_CHANNEL(p)   (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
#define READ_SIZE   160
#define sig2str   dahdi_sig2str
#define SIG_E911   (0x1000000 | DAHDI_SIG_EM)
#define SIG_EM   DAHDI_SIG_EM
#define SIG_EM_E1   DAHDI_SIG_EM_E1
#define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
#define SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
#define SIG_FEATD   (0x0200000 | DAHDI_SIG_EM)
#define SIG_FEATDMF   (0x0400000 | DAHDI_SIG_EM)
#define SIG_FEATDMF_TA   (0x2000000 | DAHDI_SIG_EM)
#define SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
#define SIG_FGC_CAMAMF   (0x8000000 | DAHDI_SIG_EM)
#define SIG_FXOGS   DAHDI_SIG_FXOGS
#define SIG_FXOKS   DAHDI_SIG_FXOKS
#define SIG_FXOLS   DAHDI_SIG_FXOLS
#define SIG_FXSGS   DAHDI_SIG_FXSGS
#define SIG_FXSKS   DAHDI_SIG_FXSKS
#define SIG_FXSLS   DAHDI_SIG_FXSLS
#define SIG_GR303FXOKS   (0x0100000 | DAHDI_SIG_FXOKS)
#define SIG_GR303FXSKS   (0x0100000 | DAHDI_SIG_FXSKS)
#define SIG_MFCR2   DAHDI_SIG_CAS
#define SIG_PRI   DAHDI_SIG_CLEAR
#define SIG_SF   DAHDI_SIG_SF
#define SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
#define SIG_SF_FEATD   (0x0200000 | DAHDI_SIG_SF)
#define SIG_SF_FEATDMF   (0x0400000 | DAHDI_SIG_SF)
#define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
#define SMDI_MD_WAIT_TIMEOUT   1500
#define SUB_CALLWAIT   1
#define SUB_REAL   0
#define SUB_THREEWAY   2
#define tdesc   "DAHDI Telephony w/PRI"
#define TRAILER_MS   5
#define TRANSFER   0

Functions

static int __action_dialoffhook (struct mansession *s, const struct message *m, int zap_mode)
static int __action_dnd (struct mansession *s, const struct message *m, int zap_mode, int dnd)
static int __action_restart (struct mansession *s, const struct message *m, int zap_mode)
static int __action_showchannels (struct mansession *s, const struct message *m, int zap_mode)
static int __action_transfer (struct mansession *s, const struct message *m, int zap_mode)
static int __action_transferhangup (struct mansession *s, const struct message *m, int zap_mode)
static struct ast_frame__dahdi_exception (struct ast_channel *ast)
static void __reg_module (void)
static int __unload_module (void)
static void __unreg_module (void)
static char * alarm2str (int alarm)
static int alloc_sub (struct dahdi_pvt *p, int x)
static void apply_plan_to_number (char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
static int attempt_transfer (struct dahdi_pvt *p)
static int available (struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
static int build_channels (struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
static void build_status (char *s, size_t len, int status, int active)
static int bump_gains (struct dahdi_pvt *p)
static 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 12442 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 12472 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 12473 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 13865 of file chan_dahdi.c.

Referenced by load_module().

#define local_astman_unregister (  ) 

Definition at line 12693 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 12887 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 14059 of file chan_dahdi.c.

#define TRAILER_MS   5

Referenced by dahdi_sendtext().

#define TRANSFER   0

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static void __reg_module ( void   )  [static]

Definition at line 14068 of file chan_dahdi.c.

static int __unload_module ( void   )  [static]

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

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

static void __unreg_module ( void   )  [static]

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

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

static int attempt_transfer ( struct dahdi_pvt p  )  [static]

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

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

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

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

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

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

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

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

Definition at line 11360 of file chan_dahdi.c.

References DCHAN_NOTINALARM, and DCHAN_PROVISIONED.

Referenced by handle_pri_show_span(), and handle_pri_show_spans().

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

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

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

static int check_for_conference ( struct dahdi_pvt p  )  [static]

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

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

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

Definition at line 11227 of file chan_dahdi.c.

References complete_span_helper().

11228 {
11229    return complete_span_helper(line,word,pos,state,3);
11230 }

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

Definition at line 11232 of file chan_dahdi.c.

References complete_span_helper().

11233 {
11234    return complete_span_helper(line,word,pos,state,4);
11235 }

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

Definition at line 11208 of file chan_dahdi.c.

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

Referenced by complete_span_4(), and complete_span_5().

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

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

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

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

Definition at line 12609 of file chan_dahdi.c.

References __action_dialoffhook(), and s.

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

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

Definition at line 12509 of file chan_dahdi.c.

References __action_dnd(), and s.

12510 {
12511    return __action_dnd(s, m, 0, 0);
12512 }

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

Definition at line 12499 of file chan_dahdi.c.

References __action_dnd(), and s.

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

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

Definition at line 12688 of file chan_dahdi.c.

References __action_restart(), and s.

12689 {
12690    return __action_restart(s, m, 0);
12691 }

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

Definition at line 12664 of file chan_dahdi.c.

References __action_showchannels(), and s.

12665 {
12666    return __action_showchannels(s, m, 0);
12667 }

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

Definition at line 12538 of file chan_dahdi.c.

References __action_transfer(), and s.

12539 {
12540    return __action_transfer(s, m, 0);
12541 }

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

Definition at line 12566 of file chan_dahdi.c.

References __action_transferhangup(), and s.

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

static int dahdi_answer ( struct ast_channel ast  )  [static]

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

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

static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause ( int  cause  )  [static]

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

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

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

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

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

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

References dahdi_destroy_channel_bynum(), and RESULT_SHOWUSAGE.

11865 {
11866    int channel;
11867    
11868    if (argc != 4)
11869       return RESULT_SHOWUSAGE;
11870    
11871    channel = atoi(argv[3]);
11872 
11873    return dahdi_destroy_channel_bynum(channel);
11874 }

static int dahdi_destroy_channel_bynum ( int  channel  )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static int dahdi_hangup ( struct ast_channel ast  )  [static]

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

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

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

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

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

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

Definition at line 4308 of file chan_dahdi.c.

References ast_log(), LOG_WARNING, and master.

Referenced by dahdi_bridge().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static int dahdi_restart ( void   )  [static]

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

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

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

Definition at line 12013 of file chan_dahdi.c.

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

12014 {
12015    if (argc != 2) {
12016       return RESULT_SHOWUSAGE;
12017    }
12018 
12019    if (dahdi_restart() != 0)
12020       return RESULT_FAILURE;
12021    return RESULT_SUCCESS;
12022 }

static int dahdi_ring_phone ( struct dahdi_pvt p  )  [static]

Definition at line 4683 of file chan_dahdi.c.

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

Referenced by __dahdi_exception(), and dahdi_handle_event().

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

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

Definition at line 3337 of file chan_dahdi.c.

References send_keypad_facility_exec().

Referenced by load_module().

03338 {
03339    return send_keypad_facility_exec(chan, data);
03340 }

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

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

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

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

09977 {
09978    int res;
09979    res = ioctl(dfd, DAHDI_SETLAW, &law);
09980    if (res)
09981       return res;
09982    return 0;
09983 }

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

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

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

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

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

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

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

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

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

Definition at line 12302 of file chan_dahdi.c.

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

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

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

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

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

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

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

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

Referenced by ss_thread().

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

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

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

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

static void destroy_all_channels ( void   )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static void enable_dtmf_detect ( struct dahdi_pvt p  )  [static]

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

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

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

12461 {
12462    struct dahdi_pvt *p = iflist;
12463    while (p) {
12464       if (p->channel == channel) {
12465          break;
12466       }
12467       p = p->next;
12468    }
12469    return p;
12470 }

static int get_alarms ( struct dahdi_pvt p  )  [static]

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

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

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

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

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

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

Definition at line 12275 of file chan_dahdi.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 11537 of file chan_dahdi.c.

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

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

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

Definition at line 11531 of file chan_dahdi.c.

References ast_cli(), and RESULT_SUCCESS.

11532 {
11533    ast_cli(fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
11534    return RESULT_SUCCESS;
11535 }

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

Definition at line 11284 of file chan_dahdi.c.

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

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

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

Definition at line 11312 of file chan_dahdi.c.

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

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

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

Definition at line 11335 of file chan_dahdi.c.

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

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

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

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

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

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

Definition at line 11441 of file chan_dahdi.c.

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

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

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

Definition at line 11402 of file chan_dahdi.c.

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

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

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

Definition at line 11381 of file chan_dahdi.c.

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

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

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

Definition at line 11278 of file chan_dahdi.c.

References ast_cli(), and RESULT_SUCCESS.

11278                                                              {
11279    ast_cli(fd, "libpri version: %s\n", pri_get_version());
11280    return RESULT_SUCCESS;
11281 }

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

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

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

Definition at line 8378 of file chan_dahdi.c.

References ast_log(), LOG_ERROR, and r2links.

Referenced by mkintf().

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

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

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

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

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

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

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

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

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

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

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

Definition at line 6717 of file chan_dahdi.c.

References ast_waitfordigit().

Referenced by ss_thread().

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

static int pri_active_dchan_fd ( struct dahdi_pri pri  )  [static]

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

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

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

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

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

static int pri_check_restart ( struct dahdi_pri pri  )  [static]

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

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

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

Definition at line 8498 of file chan_dahdi.c.

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

Referenced by setup_dahdi().

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

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

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

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

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

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

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

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

Definition at line 9624 of file chan_dahdi.c.

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

09625 {
09626    struct dahdi_pvt *p;
09627    p = pri->crvs;
09628    while (p) {
09629       if (p->channel == crv)
09630          return p;
09631       p = p->next;
09632    }
09633    return NULL;
09634 }

static int pri_find_dchan ( struct dahdi_pri pri  )  [static]

Definition at line 3400 of file chan_dahdi.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

static int pri_is_up ( struct dahdi_pri pri  )  [static]

Definition at line 3348 of file chan_dahdi.c.

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

Referenced by pri_dchannel().

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

static char* pri_order ( int  level  )  [static]

Definition at line 3371 of file chan_dahdi.c.

Referenced by handle_pri_show_span().

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

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

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

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

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

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

static char* redirectingreason2str ( int  redirectingreason  )  [static]

Definition at line 9929 of file chan_dahdi.c.

Referenced by __oh323_new().

09930 {
09931    switch (redirectingreason) {
09932    case 0:
09933       return "UNKNOWN";
09934    case 1:
09935       return "BUSY";
09936    case 2:
09937       return "NO_REPLY";
09938    case 0xF:
09939       return "UNCONDITIONAL";
09940    default:
09941       return "NOREDIRECT";
09942    }
09943 }

static int reload ( void   )  [static]

Definition at line 14042 of file chan_dahdi.c.

References ast_log(), and setup_dahdi().

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

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

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

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

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

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

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

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

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

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

static int start_pri ( struct dahdi_pri pri  )  [static]

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

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

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

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

12781 {
12782 #ifdef HAVE_PRI      
12783    int y;
12784    for (y = 0; y < NUM_SPANS; y++)
12785       ast_mutex_destroy(&pris[y].lock);
12786 #endif
12787    return __unload_module();
12788 }

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

References dahdi_accept_r2_call_exec().

Referenced by load_module().

03544 {
03545    return dahdi_accept_r2_call_exec(chan, data);
03546 }

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

Definition at line 12604 of file chan_dahdi.c.

References __action_dialoffhook(), and s.

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

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

Definition at line 12504 of file chan_dahdi.c.

References __action_dnd(), and s.

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

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

Definition at line 12494 of file chan_dahdi.c.

References __action_dnd(), and s.

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

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

Definition at line 12683 of file chan_dahdi.c.

References __action_restart(), and s.

12684 {
12685    return __action_restart(s, m, 1);
12686 }

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

Definition at line 12659 of file chan_dahdi.c.

References __action_showchannels(), and s.

12660 {
12661    return __action_showchannels(s, m, 1);
12662 }

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

Definition at line 12533 of file chan_dahdi.c.

References __action_transfer(), and s.

12534 {
12535    return __action_transfer(s, m, 1);
12536 }

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

Definition at line 12561 of file chan_dahdi.c.

References __action_transferhangup(), and s.

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

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

Definition at line 3342 of file chan_dahdi.c.

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

Referenced by load_module().

03343 {
03344    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);  
03345    return send_keypad_facility_exec(chan, data);
03346 }


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 14068 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 14068 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 12400 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 12405 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 12385 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 12395 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 12390 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 12410 of file chan_dahdi.c.

char* dahdi_accept_r2_call_app = "DAHDIAcceptR2Call" [static]

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

struct ast_cli_entry dahdi_cli[] [static]

Definition at line 12415 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct ast_cli_entry dahdi_mfcr2_cli[] [static]

Definition at line 11831 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct ast_cli_entry dahdi_pri_cli[] [static]

Definition at line 11491 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 11816 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 11825 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 11812 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 11820 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 11809 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 11806 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 11803 of file chan_dahdi.c.

char dahdi_restart_usage[] [static]

Definition at line 12378 of file chan_dahdi.c.

char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static]

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

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

Definition at line 3287 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 12271 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 12370 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 12374 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 11471 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 11475 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 11479 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 11483 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 11487 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 12366 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 12362 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 3429 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 3438 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 3432 of file chan_dahdi.c.

char* zap_send_keypad_facility_app = "ZapSendKeypadFacility" [static]

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

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

Definition at line 3288 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 Mar 25 10:39:22 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7