#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 "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_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 | 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 | 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_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_pvt * | chandup (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_action_dialoffhook (struct mansession *s, const struct message *m) |
static int | dahdi_action_dndoff (struct mansession *s, const struct message *m) |
static int | dahdi_action_dndon (struct mansession *s, const struct message *m) |
static int | dahdi_action_restart (struct mansession *s, const struct message *m) |
static int | dahdi_action_showchannels (struct mansession *s, const struct message *m) |
static int | dahdi_action_transfer (struct mansession *s, const struct message *m) |
static int | dahdi_action_transferhangup (struct mansession *s, const struct message *m) |
static int | dahdi_answer (struct ast_channel *ast) |
static enum ast_bridge_result | dahdi_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms) |
static int | dahdi_call (struct ast_channel *ast, char *rdest, int timeout) |
static int | dahdi_callwait (struct ast_channel *ast) |
static struct dahdi_chan_conf | dahdi_chan_conf_default (void) |
static void | dahdi_close (int fd) |
static void | dahdi_close_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_frame * | dahdi_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_frame * | dahdi_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_channel * | dahdi_new (struct dahdi_pvt *, int, int, int, int, int) |
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 struct ast_frame * | dahdi_read (struct ast_channel *ast) |
static struct ast_channel * | dahdi_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_pvt * | find_channel (int channel) |
static int | get_alarms (struct dahdi_pvt *p) |
static void | handle_alarms (struct dahdi_pvt *p, int alarms) |
static int | handle_dahdi_show_cadences (int fd, int argc, char *argv[]) |
static int | handle_init_event (struct dahdi_pvt *i, int event) |
static int | 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 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_pvt * | mkintf (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_pvt * | pri_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_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 = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, .reload = reload, } |
struct { | |
int alarm | |
char * name | |
} | alarms [] |
static const struct ast_module_info * | ast_module_info = &__mod_info |
static struct dahdi_ring_cadence | cadences [NUM_CADENCE_MAX] |
static struct ast_channel_tech * | chan_tech |
static int | cidrings [NUM_CADENCE_MAX] |
cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on. | |
static struct ast_cli_entry | cli_zap_destroy_channel_deprecated |
static struct ast_cli_entry | cli_zap_restart_deprecated |
static struct ast_cli_entry | cli_zap_show_cadences_deprecated |
static struct ast_cli_entry | cli_zap_show_channel_deprecated |
static struct ast_cli_entry | cli_zap_show_channels_deprecated |
static struct ast_cli_entry | cli_zap_show_status_deprecated |
static struct ast_cli_entry | dahdi_cli [] |
static struct ast_cli_entry | dahdi_pri_cli [] |
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_pvt * | ifend |
static struct dahdi_pvt * | iflist |
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 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 ast_mutex_t | restart_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
static int | ringt_base = DEFAULT_RINGT |
Configured ring timeout base. | |
dahdi_pvt * | round_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_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 |
You need to install libraries before you attempt to compile and install the DAHDI channel.
Definition in file chan_dahdi.c.
#define ASCII_BYTES_PER_CHAR 80 |
Referenced by dahdi_sendtext().
#define AST_LAW | ( | p | ) | (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW) |
Definition at line 151 of file chan_dahdi.c.
Referenced by dahdi_call(), dahdi_callwait(), dahdi_sendtext(), send_cwcidspill(), and ss_thread().
#define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) |
#define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) |
300 ms
Definition at line 282 of file chan_dahdi.c.
#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 |
Definition at line 191 of file chan_dahdi.c.
Referenced by build_channels(), dahdi_new(), dahdi_request(), enable_dtmf_detect(), and mkintf().
#define CHANNEL_PSEUDO -12 |
Definition at line 149 of file chan_dahdi.c.
#define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) |
#define CONF_USER_REAL (1 << 0) |
Definition at line 418 of file chan_dahdi.c.
#define CONF_USER_THIRDCALL (1 << 1) |
Definition at line 419 of file chan_dahdi.c.
#define DAHDI_EVENT_DTMFDOWN 0 |
#define DAHDI_EVENT_DTMFUP 0 |
#define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP) |
#define DCHAN_NOTINALARM (1 << 1) |
#define DCHAN_PROVISIONED (1 << 0) |
Definition at line 193 of file chan_dahdi.c.
Referenced by build_status(), pri_create_trunkgroup(), and pri_resolve_span().
#define DCHAN_UP (1 << 2) |
Definition at line 195 of file chan_dahdi.c.
#define DEFAULT_CIDRINGS 1 |
Typically, how many rings before we should send Caller*ID.
Definition at line 147 of file chan_dahdi.c.
Referenced by dahdi_chan_conf_default().
#define DEFAULT_PRI_DEBUG 0 |
#define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) |
8,000 ms
Definition at line 286 of file chan_dahdi.c.
#define END_SILENCE_LEN 400 |
Referenced by dahdi_sendtext().
#define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n" |
#define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" |
#define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n" |
#define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" |
#define GET_CHANNEL | ( | p | ) | ((p)->bearer ? (p)->bearer->channel : p->channel) |
Definition at line 1064 of file chan_dahdi.c.
#define HANGUP 1 |
Definition at line 10911 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 | ( | p | ) |
Value:
Definition at line 1111 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 10941 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 10942 of file chan_dahdi.c.
Referenced by __action_dialoffhook(), __action_dnd(), __action_transfer(), and __action_transferhangup().
#define local_astman_register | ( | a, | |||
b, | |||||
c, | |||||
d | ) |
#define local_astman_unregister | ( | a | ) |
#define MASK_AVAIL (1 << 0) |
Channel available for PRI use
Definition at line 279 of file chan_dahdi.c.
#define MASK_INUSE (1 << 1) |
Channel currently in use
Definition at line 280 of file chan_dahdi.c.
#define MAX_CHANLIST_LEN 80 |
The length of the parameters list of 'dahdichan'.
Definition at line 11329 of file chan_dahdi.c.
Referenced by process_dahdi().
#define MAX_CHANNELS 672 |
No more than a DS3 per trunk group
Definition at line 189 of file chan_dahdi.c.
Referenced by mkintf().
#define MAX_SLAVES 4 |
#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.
Definition at line 154 of file chan_dahdi.c.
Referenced by dahdi_new(), and ss_thread().
#define NUM_CADENCE_MAX 25 |
Definition at line 1089 of file chan_dahdi.c.
#define NUM_DCHANS 4 |
No more than 4 d-channels
Definition at line 188 of file chan_dahdi.c.
Referenced by dahdi_pri_error(), dahdi_pri_message(), mkintf(), pri_active_dchan_fd(), pri_create_trunkgroup(), pri_dchannel(), pri_find_dchan(), and pri_is_up().
#define NUM_SPANS 32 |
Definition at line 187 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_trunkgroup(), pri_resolve_span(), setup_dahdi(), and unload_module().
#define POLARITY_IDLE 0 |
Definition at line 376 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_hangup(), and unalloc_sub().
#define POLARITY_REV 1 |
Definition at line 377 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), and handle_init_event().
#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)) |
Definition at line 298 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 277 of file chan_dahdi.c.
Referenced by dahdi_callwait(), dahdi_open(), dahdi_read(), dahdi_sendtext(), dahdi_setoption(), my_dahdi_write(), process_dahdi(), and send_cwcidspill().
#define sig2str dahdi_sig2str |
Definition at line 1585 of file chan_dahdi.c.
Referenced by __action_showchannels(), build_channels(), dahdi_handle_event(), dahdi_show_channel(), handle_init_event(), and mkintf().
#define SIG_E911 (0x1000000 | DAHDI_SIG_EM) |
Definition at line 167 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_EM DAHDI_SIG_EM |
Definition at line 162 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_EM_E1 DAHDI_SIG_EM_E1 |
Definition at line 183 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM) |
Definition at line 163 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FEATB (0x0800000 | DAHDI_SIG_EM) |
Definition at line 166 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FEATD (0x0200000 | DAHDI_SIG_EM) |
Definition at line 164 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM) |
Definition at line 165 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM) |
Definition at line 168 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM) |
Definition at line 169 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM) |
Definition at line 170 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FXOGS DAHDI_SIG_FXOGS |
Definition at line 175 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FXOKS DAHDI_SIG_FXOKS |
Definition at line 176 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
#define SIG_FXOLS DAHDI_SIG_FXOLS |
Definition at line 174 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FXSGS DAHDI_SIG_FXSGS |
Definition at line 172 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FXSKS DAHDI_SIG_FXSKS |
Definition at line 173 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_request(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
#define SIG_FXSLS DAHDI_SIG_FXSLS |
Definition at line 171 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS) |
Definition at line 184 of file chan_dahdi.c.
Referenced by dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().
#define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS) |
Definition at line 185 of file chan_dahdi.c.
Referenced by dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().
#define SIG_PRI DAHDI_SIG_CLEAR |
Definition at line 177 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_read(), dahdi_sig2str(), dahdi_write(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
#define SIG_SF DAHDI_SIG_SF |
Definition at line 178 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF) |
Definition at line 182 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF) |
Definition at line 180 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), and ss_thread().
#define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF) |
Definition at line 181 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), and ss_thread().
#define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF) |
Definition at line 179 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SMDI_MD_WAIT_TIMEOUT 1500 |
#define SUB_CALLWAIT 1 |
Call-Waiting call on hold
Definition at line 372 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 371 of file chan_dahdi.c.
Referenced by __dahdi_exception(), attempt_transfer(), available(), bump_gains(), chandup(), check_for_conference(), dahdi_answer(), dahdi_bridge(), dahdi_call(), dahdi_confmute(), dahdi_destroy_channel_bynum(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_read(), dahdi_request(), dahdi_ring_phone(), dahdi_setoption(), dahdi_train_ec(), dahdi_unlink(), destroy_dahdi_pvt(), disable_dtmf_detect(), do_monitor(), enable_dtmf_detect(), features_hangup(), features_request(), get_alarms(), handle_init_event(), mkintf(), 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 373 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 12358 of file chan_dahdi.c.
#define TRAILER_MS 5 |
Referenced by dahdi_sendtext().
#define TRANSFER 0 |
Definition at line 10910 of file chan_dahdi.c.
Referenced by __action_transfer(), and dahdi_fake_event().
static int __action_dialoffhook | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 11040 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().
11041 { 11042 struct dahdi_pvt *p = NULL; 11043 const char *channel = local_astman_header(m, "Channel", zap_mode); 11044 const char *number = astman_get_header(m, "Number"); 11045 int i; 11046 11047 if (ast_strlen_zero(channel)) { 11048 astman_send_error(s, m, "No channel specified"); 11049 return 0; 11050 } 11051 if (ast_strlen_zero(number)) { 11052 astman_send_error(s, m, "No number specified"); 11053 return 0; 11054 } 11055 if (!(p = find_channel(atoi(channel)))) { 11056 astman_send_error(s, m, "No such channel"); 11057 return 0; 11058 } 11059 if (!p->owner) { 11060 astman_send_error(s, m, "Channel does not have an owner"); 11061 return 0; 11062 } 11063 for (i = 0; i < strlen(number); i++) { 11064 struct ast_frame f = { AST_FRAME_DTMF, number[i] }; 11065 11066 dahdi_queue_frame(p, &f, NULL); 11067 } 11068 local_astman_ack(s, m, "DialOffHook", zap_mode); 11069 11070 return 0; 11071 }
static int __action_dnd | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode, | |||
int | dnd | |||
) | [static] |
Definition at line 10944 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().
10945 { 10946 struct dahdi_pvt *p = NULL; 10947 const char *channel = local_astman_header(m, "Channel", zap_mode); 10948 10949 if (ast_strlen_zero(channel)) { 10950 astman_send_error(s, m, "No channel specified"); 10951 return 0; 10952 } 10953 if (!(p = find_channel(atoi(channel)))) { 10954 astman_send_error(s, m, "No such channel"); 10955 return 0; 10956 } 10957 p->dnd = dnd; 10958 local_astman_ack(s, m, "DND", zap_mode); 10959 10960 return 0; 10961 }
static int __action_restart | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 11138 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().
11139 { 11140 if (dahdi_restart() != 0) { 11141 if (zap_mode) { 11142 astman_send_error(s, m, "Failed to restart Zap"); 11143 } else { 11144 astman_send_error(s, m, "Failed to restart DAHDI"); 11145 } 11146 return 1; 11147 } 11148 local_astman_ack(s, m, "Restart: Success", zap_mode); 11149 return 0; 11150 }
static int __action_showchannels | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 11083 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().
11084 { 11085 struct dahdi_pvt *tmp = NULL; 11086 const char *id = astman_get_header(m, "ActionID"); 11087 char idText[256] = ""; 11088 11089 local_astman_ack(s, m, " channel status will follow", zap_mode); 11090 if (!ast_strlen_zero(id)) 11091 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id); 11092 11093 ast_mutex_lock(&iflock); 11094 11095 tmp = iflist; 11096 while (tmp) { 11097 if (tmp->channel > 0) { 11098 int alarm = get_alarms(tmp); 11099 astman_append(s, 11100 "Event: %sShowChannels\r\n" 11101 "Channel: %d\r\n" 11102 "Signalling: %s\r\n" 11103 "Context: %s\r\n" 11104 "DND: %s\r\n" 11105 "Alarm: %s\r\n" 11106 "%s" 11107 "\r\n", 11108 dahdi_chan_name, 11109 tmp->channel, sig2str(tmp->sig), tmp->context, 11110 tmp->dnd ? "Enabled" : "Disabled", 11111 alarm2str(alarm), idText); 11112 } 11113 11114 tmp = tmp->next; 11115 } 11116 11117 ast_mutex_unlock(&iflock); 11118 11119 astman_append(s, 11120 "Event: %sShowChannelsComplete\r\n" 11121 "%s" 11122 "\r\n", 11123 dahdi_chan_name, 11124 idText); 11125 return 0; 11126 }
static int __action_transfer | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 10983 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().
10984 { 10985 struct dahdi_pvt *p = NULL; 10986 const char *channel = local_astman_header(m, "Channel", zap_mode); 10987 10988 if (ast_strlen_zero(channel)) { 10989 astman_send_error(s, m, "No channel specified"); 10990 return 0; 10991 } 10992 if (!(p = find_channel(atoi(channel)))) { 10993 astman_send_error(s, m, "No such channel"); 10994 return 0; 10995 } 10996 dahdi_fake_event(p,TRANSFER); 10997 local_astman_ack(s, m, "Transfer", zap_mode); 10998 10999 return 0; 11000 }
static int __action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 11012 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().
11013 { 11014 struct dahdi_pvt *p = NULL; 11015 const char *channel = local_astman_header(m, "Channel", zap_mode); 11016 11017 if (ast_strlen_zero(channel)) { 11018 astman_send_error(s, m, "No channel specified"); 11019 return 0; 11020 } 11021 if (!(p = find_channel(atoi(channel)))) { 11022 astman_send_error(s, m, "No such channel"); 11023 return 0; 11024 } 11025 dahdi_fake_event(p, HANGUP); 11026 local_astman_ack(s, m, "Hangup", zap_mode); 11027 return 0; 11028 }
static struct ast_frame* __dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 4959 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().
04960 { 04961 struct dahdi_pvt *p = ast->tech_pvt; 04962 int res; 04963 int usedindex=-1; 04964 int index; 04965 struct ast_frame *f; 04966 04967 04968 index = dahdi_get_index(ast, p, 1); 04969 04970 p->subs[index].f.frametype = AST_FRAME_NULL; 04971 p->subs[index].f.datalen = 0; 04972 p->subs[index].f.samples = 0; 04973 p->subs[index].f.mallocd = 0; 04974 p->subs[index].f.offset = 0; 04975 p->subs[index].f.subclass = 0; 04976 p->subs[index].f.delivery = ast_tv(0,0); 04977 p->subs[index].f.src = "dahdi_exception"; 04978 p->subs[index].f.data = NULL; 04979 04980 04981 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) { 04982 /* If nobody owns us, absorb the event appropriately, otherwise 04983 we loop indefinitely. This occurs when, during call waiting, the 04984 other end hangs up our channel so that it no longer exists, but we 04985 have neither FLASH'd nor ONHOOK'd to signify our desire to 04986 change to the other channel. */ 04987 if (p->fake_event) { 04988 res = p->fake_event; 04989 p->fake_event = 0; 04990 } else 04991 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 04992 /* Switch to real if there is one and this isn't something really silly... */ 04993 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) && 04994 (res != DAHDI_EVENT_HOOKCOMPLETE)) { 04995 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res); 04996 p->owner = p->subs[SUB_REAL].owner; 04997 if (p->owner && ast_bridged_channel(p->owner)) 04998 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 04999 p->subs[SUB_REAL].needunhold = 1; 05000 } 05001 switch (res) { 05002 case DAHDI_EVENT_ONHOOK: 05003 dahdi_disable_ec(p); 05004 if (p->owner) { 05005 if (option_verbose > 2) 05006 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name); 05007 dahdi_ring_phone(p); 05008 p->callwaitingrepeat = 0; 05009 p->cidcwexpire = 0; 05010 } else 05011 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 05012 update_conf(p); 05013 break; 05014 case DAHDI_EVENT_RINGOFFHOOK: 05015 dahdi_enable_ec(p); 05016 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 05017 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) { 05018 p->subs[SUB_REAL].needanswer = 1; 05019 p->dialing = 0; 05020 } 05021 break; 05022 case DAHDI_EVENT_HOOKCOMPLETE: 05023 case DAHDI_EVENT_RINGERON: 05024 case DAHDI_EVENT_RINGEROFF: 05025 /* Do nothing */ 05026 break; 05027 case DAHDI_EVENT_WINKFLASH: 05028 gettimeofday(&p->flashtime, NULL); 05029 if (p->owner) { 05030 if (option_verbose > 2) 05031 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name); 05032 if (p->owner->_state != AST_STATE_UP) { 05033 /* Answer if necessary */ 05034 usedindex = dahdi_get_index(p->owner, p, 0); 05035 if (usedindex > -1) { 05036 p->subs[usedindex].needanswer = 1; 05037 } 05038 ast_setstate(p->owner, AST_STATE_UP); 05039 } 05040 p->callwaitingrepeat = 0; 05041 p->cidcwexpire = 0; 05042 if (ast_bridged_channel(p->owner)) 05043 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05044 p->subs[SUB_REAL].needunhold = 1; 05045 } else 05046 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 05047 update_conf(p); 05048 break; 05049 default: 05050 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res)); 05051 } 05052 f = &p->subs[index].f; 05053 return f; 05054 } 05055 if (!(p->radio || (p->oprmode < 0)) && option_debug) 05056 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel); 05057 /* If it's not us, return NULL immediately */ 05058 if (ast != p->owner) { 05059 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name); 05060 f = &p->subs[index].f; 05061 return f; 05062 } 05063 f = dahdi_handle_event(ast); 05064 return f; 05065 }
static void __reg_module | ( | void | ) | [static] |
Definition at line 12367 of file chan_dahdi.c.
static int __unload_module | ( | void | ) | [static] |
Definition at line 11169 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_pri_cli, destroy_all_channels(), iflist, iflock, local_astman_unregister, master, monlock, dahdi_pvt::next, NUM_SPANS, dahdi_pvt::owner, and pris.
Referenced by load_module(), and unload_module().
11170 { 11171 struct dahdi_pvt *p; 11172 11173 #ifdef HAVE_PRI 11174 int i, j; 11175 for (i = 0; i < NUM_SPANS; i++) { 11176 if (pris[i].master != AST_PTHREADT_NULL) 11177 pthread_cancel(pris[i].master); 11178 } 11179 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry)); 11180 11181 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 11182 ast_unregister_application(dahdi_send_keypad_facility_app); 11183 } 11184 ast_unregister_application(zap_send_keypad_facility_app); 11185 #endif 11186 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 11187 local_astman_unregister("DialOffHook"); 11188 local_astman_unregister("Hangup"); 11189 local_astman_unregister("Transfer"); 11190 local_astman_unregister("DNDoff"); 11191 local_astman_unregister("DNDon"); 11192 local_astman_unregister("ShowChannels"); 11193 local_astman_unregister("Restart"); 11194 ast_channel_unregister(chan_tech); 11195 ast_mutex_lock(&iflock); 11196 /* Hangup all interfaces if they have an owner */ 11197 p = iflist; 11198 while (p) { 11199 if (p->owner) 11200 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 11201 p = p->next; 11202 } 11203 ast_mutex_unlock(&iflock); 11204 ast_mutex_lock(&monlock); 11205 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 11206 pthread_cancel(monitor_thread); 11207 pthread_kill(monitor_thread, SIGURG); 11208 pthread_join(monitor_thread, NULL); 11209 } 11210 monitor_thread = AST_PTHREADT_STOP; 11211 ast_mutex_unlock(&monlock); 11212 11213 destroy_all_channels(); 11214 #ifdef HAVE_PRI 11215 for (i = 0; i < NUM_SPANS; i++) { 11216 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) 11217 pthread_join(pris[i].master, NULL); 11218 for (j = 0; j < NUM_DCHANS; j++) { 11219 dahdi_close_pri_fd(&(pris[i]), j); 11220 } 11221 } 11222 #endif 11223 ast_cond_destroy(&ss_thread_complete); 11224 return 0; 11225 }
static void __unreg_module | ( | void | ) | [static] |
Definition at line 12367 of file chan_dahdi.c.
static char* alarm2str | ( | int | alarm | ) | [static] |
Definition at line 1496 of file chan_dahdi.c.
Referenced by __action_showchannels(), and handle_alarms().
01497 { 01498 int x; 01499 for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) { 01500 if (alarms[x].alarm & alarm) 01501 return alarms[x].name; 01502 } 01503 return alarm ? "Unknown Alarm" : "No Alarm"; 01504 }
static int alloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 1298 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().
01299 { 01300 struct dahdi_bufferinfo bi; 01301 int res; 01302 if (p->subs[x].dfd < 0) { 01303 p->subs[x].dfd = dahdi_open(DAHDI_FILE_PSEUDO); 01304 if (p->subs[x].dfd > -1) { 01305 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi); 01306 if (!res) { 01307 bi.txbufpolicy = p->buf_policy; 01308 bi.rxbufpolicy = p->buf_policy; 01309 bi.numbufs = p->buf_no; 01310 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi); 01311 if (res < 0) { 01312 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno)); 01313 } 01314 } else 01315 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno)); 01316 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) { 01317 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno)); 01318 dahdi_close_sub(p, x); 01319 return -1; 01320 } 01321 if (option_debug) 01322 ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan); 01323 return 0; 01324 } else 01325 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 01326 return -1; 01327 } 01328 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel); 01329 return -1; 01330 }
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 8839 of file chan_dahdi.c.
References dahdi_pri::internationalprefix, dahdi_pri::localprefix, dahdi_pri::nationalprefix, dahdi_pri::privateprefix, and dahdi_pri::unknownprefix.
08840 { 08841 switch (plan) { 08842 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */ 08843 snprintf(buf, size, "%s%s", pri->internationalprefix, number); 08844 break; 08845 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */ 08846 snprintf(buf, size, "%s%s", pri->nationalprefix, number); 08847 break; 08848 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */ 08849 snprintf(buf, size, "%s%s", pri->localprefix, number); 08850 break; 08851 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */ 08852 snprintf(buf, size, "%s%s", pri->privateprefix, number); 08853 break; 08854 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */ 08855 snprintf(buf, size, "%s%s", pri->unknownprefix, number); 08856 break; 08857 default: /* other Q.931 dialplan => don't twiddle with callingnum */ 08858 snprintf(buf, size, "%s", number); 08859 break; 08860 } 08861 }
static int attempt_transfer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3908 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().
03909 { 03910 /* In order to transfer, we need at least one of the channels to 03911 actually be in a call bridge. We can't conference two applications 03912 together (but then, why would we want to?) */ 03913 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 03914 /* The three-way person we're about to transfer to could still be in MOH, so 03915 stop if now if appropriate */ 03916 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) 03917 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD); 03918 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) { 03919 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING); 03920 } 03921 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) { 03922 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 03923 } 03924 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { 03925 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 03926 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name); 03927 return -1; 03928 } 03929 /* Orphan the channel after releasing the lock */ 03930 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 03931 unalloc_sub(p, SUB_THREEWAY); 03932 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 03933 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 03934 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) { 03935 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING); 03936 } 03937 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) { 03938 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 03939 } 03940 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { 03941 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 03942 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); 03943 return -1; 03944 } 03945 /* Three-way is now the REAL */ 03946 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03947 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock); 03948 unalloc_sub(p, SUB_THREEWAY); 03949 /* Tell the caller not to hangup */ 03950 return 1; 03951 } else { 03952 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n", 03953 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name); 03954 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 03955 return -1; 03956 } 03957 return 0; 03958 }
static int available | ( | struct dahdi_pvt * | p, | |
int | channelmatch, | |||
ast_group_t | groupmatch, | |||
int * | busy, | |||
int * | channelmatched, | |||
int * | groupmatched | |||
) | [inline, static] |
Definition at line 8108 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::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().
08109 { 08110 int res; 08111 struct dahdi_params par; 08112 08113 /* First, check group matching */ 08114 if (groupmatch) { 08115 if ((p->group & groupmatch) != groupmatch) 08116 return 0; 08117 *groupmatched = 1; 08118 } 08119 /* Check to see if we have a channel match */ 08120 if (channelmatch != -1) { 08121 if (p->channel != channelmatch) 08122 return 0; 08123 *channelmatched = 1; 08124 } 08125 /* We're at least busy at this point */ 08126 if (busy) { 08127 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS)) 08128 *busy = 1; 08129 } 08130 /* If do not disturb, definitely not */ 08131 if (p->dnd) 08132 return 0; 08133 /* If guard time, definitely not */ 08134 if (p->guardtime && (time(NULL) < p->guardtime)) 08135 return 0; 08136 08137 /* If no owner definitely available */ 08138 if (!p->owner) { 08139 #ifdef HAVE_PRI 08140 /* Trust PRI */ 08141 if (p->pri) { 08142 if (p->resetting || p->call) 08143 return 0; 08144 else 08145 return 1; 08146 } 08147 #endif 08148 if (!(p->radio || (p->oprmode < 0))) 08149 { 08150 if (!p->sig || (p->sig == SIG_FXSLS)) 08151 return 1; 08152 /* Check hook state */ 08153 if (p->subs[SUB_REAL].dfd > -1) 08154 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 08155 else { 08156 /* Assume not off hook on CVRS */ 08157 res = 0; 08158 par.rxisoffhook = 0; 08159 } 08160 if (res) { 08161 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno)); 08162 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) { 08163 /* When "onhook" that means no battery on the line, and thus 08164 it is out of service..., if it's on a TDM card... If it's a channel 08165 bank, there is no telling... */ 08166 if (par.rxbits > -1) 08167 return 1; 08168 if (par.rxisoffhook) 08169 return 1; 08170 else 08171 #ifdef DAHDI_CHECK_HOOKSTATE 08172 return 0; 08173 #else 08174 return 1; 08175 #endif 08176 } else if (par.rxisoffhook) { 08177 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel); 08178 /* Not available when the other end is off hook */ 08179 return 0; 08180 } 08181 } 08182 return 1; 08183 } 08184 08185 /* If it's not an FXO, forget about call wait */ 08186 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 08187 return 0; 08188 08189 if (!p->callwaiting) { 08190 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */ 08191 return 0; 08192 } 08193 08194 if (p->subs[SUB_CALLWAIT].dfd > -1) { 08195 /* If there is already a call waiting call, then we can't take a second one */ 08196 return 0; 08197 } 08198 08199 if ((p->owner->_state != AST_STATE_UP) && 08200 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) { 08201 /* If the current call is not up, then don't allow the call */ 08202 return 0; 08203 } 08204 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) { 08205 /* Can't take a call wait when the three way calling hasn't been merged yet. */ 08206 return 0; 08207 } 08208 /* We're cool */ 08209 return 1; 08210 }
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 11237 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, dahdi_pvt::sig, sig2str, dahdi_pri::trunkgroup, and VERBOSE_PREFIX_3.
Referenced by process_dahdi().
11238 { 11239 char *c, *chan; 11240 int x, start, finish; 11241 struct dahdi_pvt *tmp; 11242 #ifdef HAVE_PRI 11243 struct dahdi_pri *pri; 11244 int trunkgroup, y; 11245 #endif 11246 11247 if ((reload == 0) && (conf->chan.sig < 0)) { 11248 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); 11249 return -1; 11250 } 11251 11252 c = ast_strdupa(value); 11253 11254 #ifdef HAVE_PRI 11255 pri = NULL; 11256 if (iscrv) { 11257 if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) { 11258 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno); 11259 return -1; 11260 } 11261 if (trunkgroup < 1) { 11262 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno); 11263 return -1; 11264 } 11265 c += y; 11266 for (y = 0; y < NUM_SPANS; y++) { 11267 if (pris[y].trunkgroup == trunkgroup) { 11268 pri = pris + y; 11269 break; 11270 } 11271 } 11272 if (!pri) { 11273 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno); 11274 return -1; 11275 } 11276 } 11277 #endif 11278 11279 while ((chan = strsep(&c, ","))) { 11280 if (sscanf(chan, "%d-%d", &start, &finish) == 2) { 11281 /* Range */ 11282 } else if (sscanf(chan, "%d", &start)) { 11283 /* Just one */ 11284 finish = start; 11285 } else if (!strcasecmp(chan, "pseudo")) { 11286 finish = start = CHAN_PSEUDO; 11287 if (found_pseudo) 11288 *found_pseudo = 1; 11289 } else { 11290 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan); 11291 return -1; 11292 } 11293 if (finish < start) { 11294 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); 11295 x = finish; 11296 finish = start; 11297 start = x; 11298 } 11299 11300 for (x = start; x <= finish; x++) { 11301 #ifdef HAVE_PRI 11302 tmp = mkintf(x, conf, pri, reload); 11303 #else 11304 tmp = mkintf(x, conf, NULL, reload); 11305 #endif 11306 11307 if (tmp) { 11308 if (option_verbose > 2) { 11309 #ifdef HAVE_PRI 11310 if (pri) 11311 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig)); 11312 else 11313 #endif 11314 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig)); 11315 } 11316 } else { 11317 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n", 11318 (reload == 1) ? "reconfigure" : "register", value); 11319 return -1; 11320 } 11321 } 11322 } 11323 11324 return 0; 11325 }
static void build_status | ( | char * | s, | |
size_t | len, | |||
int | status, | |||
int | active | |||
) | [static] |
Definition at line 10216 of file chan_dahdi.c.
References DCHAN_NOTINALARM, and DCHAN_PROVISIONED.
Referenced by handle_pri_show_span(), and handle_pri_show_spans().
10217 { 10218 if (!s || len < 1) { 10219 return; 10220 } 10221 s[0] = '\0'; 10222 if (status & DCHAN_PROVISIONED) 10223 strncat(s, "Provisioned, ", len - strlen(s) - 1); 10224 if (!(status & DCHAN_NOTINALARM)) 10225 strncat(s, "In Alarm, ", len - strlen(s) - 1); 10226 if (status & DCHAN_UP) 10227 strncat(s, "Up", len - strlen(s) - 1); 10228 else 10229 strncat(s, "Down", len - strlen(s) - 1); 10230 if (active) 10231 strncat(s, ", Active", len - strlen(s) - 1); 10232 else 10233 strncat(s, ", Standby", len - strlen(s) - 1); 10234 s[len - 1] = '\0'; 10235 }
static int bump_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1947 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().
01948 { 01949 int res; 01950 01951 /* Bump receive gain by 5.0db */ 01952 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law); 01953 if (res) { 01954 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno)); 01955 return -1; 01956 } 01957 01958 return 0; 01959 }
Definition at line 8212 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().
08213 { 08214 struct dahdi_pvt *p; 08215 struct dahdi_bufferinfo bi; 08216 int res; 08217 08218 if ((p = ast_malloc(sizeof(*p)))) { 08219 memcpy(p, src, sizeof(struct dahdi_pvt)); 08220 ast_mutex_init(&p->lock); 08221 p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO); 08222 /* Allocate a DAHDI structure */ 08223 if (p->subs[SUB_REAL].dfd < 0) { 08224 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno)); 08225 destroy_dahdi_pvt(&p); 08226 return NULL; 08227 } 08228 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 08229 if (!res) { 08230 bi.txbufpolicy = p->buf_policy; 08231 bi.rxbufpolicy = p->buf_policy; 08232 bi.numbufs = p->buf_no; 08233 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 08234 if (res < 0) { 08235 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno)); 08236 } 08237 } else 08238 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno)); 08239 } 08240 p->destroy = 1; 08241 p->next = iflist; 08242 p->prev = NULL; 08243 iflist = p; 08244 if (iflist->next) 08245 iflist->next->prev = p; 08246 return p; 08247 }
static int check_for_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3960 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().
03961 { 03962 struct dahdi_confinfo ci; 03963 /* Fine if we already have a master, etc */ 03964 if (p->master || (p->confno > -1)) 03965 return 0; 03966 memset(&ci, 0, sizeof(ci)); 03967 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 03968 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno)); 03969 return 0; 03970 } 03971 /* If we have no master and don't have a confno, then 03972 if we're in a conference, it's probably a MeetMe room or 03973 some such, so don't let us 3-way out! */ 03974 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) { 03975 if (option_verbose > 2) 03976 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n"); 03977 return 1; 03978 } 03979 return 0; 03980 }
static char* complete_span_4 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 10083 of file chan_dahdi.c.
References complete_span_helper().
10084 { 10085 return complete_span_helper(line,word,pos,state,3); 10086 }
static char* complete_span_5 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 10088 of file chan_dahdi.c.
References complete_span_helper().
10089 { 10090 return complete_span_helper(line,word,pos,state,4); 10091 }
static char* complete_span_helper | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state, | |||
int | rpos | |||
) | [static] |
Definition at line 10064 of file chan_dahdi.c.
References asprintf, ast_log(), errno, NUM_SPANS, and pris.
Referenced by complete_span_4(), and complete_span_5().
10065 { 10066 int which, span; 10067 char *ret = NULL; 10068 10069 if (pos != rpos) 10070 return ret; 10071 10072 for (which = span = 0; span < NUM_SPANS; span++) { 10073 if (pris[span].pri && ++which > state) { 10074 if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */ 10075 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 10076 } 10077 break; 10078 } 10079 } 10080 return ret; 10081 }
static int conf_add | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index, | |||
int | slavechannel | |||
) | [static] |
Definition at line 1587 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().
01588 { 01589 /* If the conference already exists, and we're already in it 01590 don't bother doing anything */ 01591 struct dahdi_confinfo zi; 01592 01593 memset(&zi, 0, sizeof(zi)); 01594 zi.chan = 0; 01595 01596 if (slavechannel > 0) { 01597 /* If we have only one slave, do a digital mon */ 01598 zi.confmode = DAHDI_CONF_DIGITALMON; 01599 zi.confno = slavechannel; 01600 } else { 01601 if (!index) { 01602 /* Real-side and pseudo-side both participate in conference */ 01603 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER | 01604 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 01605 } else 01606 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 01607 zi.confno = p->confno; 01608 } 01609 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode)) 01610 return 0; 01611 if (c->dfd < 0) 01612 return 0; 01613 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 01614 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno)); 01615 return -1; 01616 } 01617 if (slavechannel < 1) { 01618 p->confno = zi.confno; 01619 } 01620 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 01621 ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 01622 return 0; 01623 }
static int conf_del | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index | |||
) | [static] |
Definition at line 1636 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().
01637 { 01638 struct dahdi_confinfo zi; 01639 if (/* Can't delete if there's no dfd */ 01640 (c->dfd < 0) || 01641 /* Don't delete from the conference if it's not our conference */ 01642 !isourconf(p, c) 01643 /* Don't delete if we don't think it's conferenced at all (implied) */ 01644 ) return 0; 01645 memset(&zi, 0, sizeof(zi)); 01646 zi.chan = 0; 01647 zi.confno = 0; 01648 zi.confmode = 0; 01649 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 01650 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno)); 01651 return -1; 01652 } 01653 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 01654 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 01655 return 0; 01656 }
static int dahdi_action_dialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 11078 of file chan_dahdi.c.
References __action_dialoffhook(), and s.
11079 { 11080 return __action_dialoffhook(s, m, 0); 11081 }
static int dahdi_action_dndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10978 of file chan_dahdi.c.
References __action_dnd(), and s.
10979 { 10980 return __action_dnd(s, m, 0, 0); 10981 }
static int dahdi_action_dndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10968 of file chan_dahdi.c.
References __action_dnd(), and s.
10969 { 10970 return __action_dnd(s, m, 0, 1); 10971 }
static int dahdi_action_restart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 11157 of file chan_dahdi.c.
References __action_restart(), and s.
11158 { 11159 return __action_restart(s, m, 0); 11160 }
static int dahdi_action_showchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 11133 of file chan_dahdi.c.
References __action_showchannels(), and s.
11134 { 11135 return __action_showchannels(s, m, 0); 11136 }
static int dahdi_action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 11007 of file chan_dahdi.c.
References __action_transfer(), and s.
11008 { 11009 return __action_transfer(s, m, 0); 11010 }
static int dahdi_action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 11035 of file chan_dahdi.c.
References __action_transferhangup(), and s.
11036 { 11037 return __action_transferhangup(s, m, 0); 11038 }
static int dahdi_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3153 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_set_hook(), dahdi_train_ec(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::digital, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, 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::radio, dahdi_pvt::ringt, dahdi_pvt::sig, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::span, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and ast_channel::tech_pvt.
03154 { 03155 struct dahdi_pvt *p = ast->tech_pvt; 03156 int res = 0; 03157 int index; 03158 int oldstate = ast->_state; 03159 ast_setstate(ast, AST_STATE_UP); 03160 ast_mutex_lock(&p->lock); 03161 index = dahdi_get_index(ast, p, 0); 03162 if (index < 0) 03163 index = SUB_REAL; 03164 /* nothing to do if a radio channel */ 03165 if ((p->radio || (p->oprmode < 0))) { 03166 ast_mutex_unlock(&p->lock); 03167 return 0; 03168 } 03169 switch (p->sig) { 03170 case SIG_FXSLS: 03171 case SIG_FXSGS: 03172 case SIG_FXSKS: 03173 p->ringt = 0; 03174 /* Fall through */ 03175 case SIG_EM: 03176 case SIG_EM_E1: 03177 case SIG_EMWINK: 03178 case SIG_FEATD: 03179 case SIG_FEATDMF: 03180 case SIG_FEATDMF_TA: 03181 case SIG_E911: 03182 case SIG_FGC_CAMA: 03183 case SIG_FGC_CAMAMF: 03184 case SIG_FEATB: 03185 case SIG_SF: 03186 case SIG_SFWINK: 03187 case SIG_SF_FEATD: 03188 case SIG_SF_FEATDMF: 03189 case SIG_SF_FEATB: 03190 case SIG_FXOLS: 03191 case SIG_FXOGS: 03192 case SIG_FXOKS: 03193 /* Pick up the line */ 03194 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name); 03195 if (p->hanguponpolarityswitch) { 03196 gettimeofday(&p->polaritydelaytv, NULL); 03197 } 03198 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 03199 tone_zone_play_tone(p->subs[index].dfd, -1); 03200 p->dialing = 0; 03201 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) { 03202 if (oldstate == AST_STATE_RINGING) { 03203 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n"); 03204 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1); 03205 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03206 p->owner = p->subs[SUB_REAL].owner; 03207 } 03208 } 03209 if (p->sig & __DAHDI_SIG_FXS) { 03210 dahdi_enable_ec(p); 03211 dahdi_train_ec(p); 03212 } 03213 break; 03214 #ifdef HAVE_PRI 03215 case SIG_PRI: 03216 /* Send a pri acknowledge */ 03217 if (!pri_grab(p, p->pri)) { 03218 p->proceeding = 1; 03219 res = pri_answer(p->pri->pri, p->call, 0, !p->digital); 03220 pri_rel(p->pri); 03221 } else { 03222 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 03223 res = -1; 03224 } 03225 break; 03226 #endif 03227 case 0: 03228 ast_mutex_unlock(&p->lock); 03229 return 0; 03230 default: 03231 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel); 03232 res = -1; 03233 } 03234 ast_mutex_unlock(&p->lock); 03235 return res; 03236 }
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 3561 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.
03562 { 03563 struct ast_channel *who; 03564 struct dahdi_pvt *p0, *p1, *op0, *op1; 03565 struct dahdi_pvt *master = NULL, *slave = NULL; 03566 struct ast_frame *f; 03567 int inconf = 0; 03568 int nothingok = 1; 03569 int ofd0, ofd1; 03570 int oi0, oi1, i0 = -1, i1 = -1, t0, t1; 03571 int os0 = -1, os1 = -1; 03572 int priority = 0; 03573 struct ast_channel *oc0, *oc1; 03574 enum ast_bridge_result res; 03575 03576 #ifdef PRI_2BCT 03577 int triedtopribridge = 0; 03578 q931_call *q931c0 = NULL, *q931c1 = NULL; 03579 #endif 03580 03581 /* For now, don't attempt to native bridge if either channel needs DTMF detection. 03582 There is code below to handle it properly until DTMF is actually seen, 03583 but due to currently unresolved issues it's ignored... 03584 */ 03585 03586 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 03587 return AST_BRIDGE_FAILED_NOWARN; 03588 03589 ast_mutex_lock(&c0->lock); 03590 while (ast_mutex_trylock(&c1->lock)) { 03591 DEADLOCK_AVOIDANCE(&c0->lock); 03592 } 03593 03594 p0 = c0->tech_pvt; 03595 p1 = c1->tech_pvt; 03596 /* cant do pseudo-channels here */ 03597 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) { 03598 ast_mutex_unlock(&c0->lock); 03599 ast_mutex_unlock(&c1->lock); 03600 return AST_BRIDGE_FAILED_NOWARN; 03601 } 03602 03603 oi0 = dahdi_get_index(c0, p0, 0); 03604 oi1 = dahdi_get_index(c1, p1, 0); 03605 if ((oi0 < 0) || (oi1 < 0)) { 03606 ast_mutex_unlock(&c0->lock); 03607 ast_mutex_unlock(&c1->lock); 03608 return AST_BRIDGE_FAILED; 03609 } 03610 03611 op0 = p0 = c0->tech_pvt; 03612 op1 = p1 = c1->tech_pvt; 03613 ofd0 = c0->fds[0]; 03614 ofd1 = c1->fds[0]; 03615 oc0 = p0->owner; 03616 oc1 = p1->owner; 03617 03618 if (ast_mutex_trylock(&p0->lock)) { 03619 /* Don't block, due to potential for deadlock */ 03620 ast_mutex_unlock(&c0->lock); 03621 ast_mutex_unlock(&c1->lock); 03622 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 03623 return AST_BRIDGE_RETRY; 03624 } 03625 if (ast_mutex_trylock(&p1->lock)) { 03626 /* Don't block, due to potential for deadlock */ 03627 ast_mutex_unlock(&p0->lock); 03628 ast_mutex_unlock(&c0->lock); 03629 ast_mutex_unlock(&c1->lock); 03630 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 03631 return AST_BRIDGE_RETRY; 03632 } 03633 03634 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 03635 if (p0->owner && p1->owner) { 03636 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */ 03637 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) { 03638 master = p0; 03639 slave = p1; 03640 inconf = 1; 03641 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) { 03642 master = p1; 03643 slave = p0; 03644 inconf = 1; 03645 } else { 03646 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n"); 03647 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n", 03648 p0->channel, 03649 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 03650 p0->subs[SUB_REAL].inthreeway, p0->channel, 03651 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 03652 p1->subs[SUB_REAL].inthreeway); 03653 } 03654 nothingok = 0; 03655 } 03656 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) { 03657 if (p1->subs[SUB_THREEWAY].inthreeway) { 03658 master = p1; 03659 slave = p0; 03660 nothingok = 0; 03661 } 03662 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) { 03663 if (p0->subs[SUB_THREEWAY].inthreeway) { 03664 master = p0; 03665 slave = p1; 03666 nothingok = 0; 03667 } 03668 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) { 03669 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise, 03670 don't put us in anything */ 03671 if (p1->subs[SUB_CALLWAIT].inthreeway) { 03672 master = p1; 03673 slave = p0; 03674 nothingok = 0; 03675 } 03676 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) { 03677 /* Same as previous */ 03678 if (p0->subs[SUB_CALLWAIT].inthreeway) { 03679 master = p0; 03680 slave = p1; 03681 nothingok = 0; 03682 } 03683 } 03684 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n", 03685 master ? master->channel : 0, slave ? slave->channel : 0, nothingok); 03686 if (master && slave) { 03687 /* Stop any tones, or play ringtone as appropriate. If they're bridged 03688 in an active threeway call with a channel that is ringing, we should 03689 indicate ringing. */ 03690 if ((oi1 == SUB_THREEWAY) && 03691 p1->subs[SUB_THREEWAY].inthreeway && 03692 p1->subs[SUB_REAL].owner && 03693 p1->subs[SUB_REAL].inthreeway && 03694 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 03695 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name); 03696 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE); 03697 os1 = p1->subs[SUB_REAL].owner->_state; 03698 } else { 03699 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1); 03700 tone_zone_play_tone(p0->subs[oi0].dfd, -1); 03701 } 03702 if ((oi0 == SUB_THREEWAY) && 03703 p0->subs[SUB_THREEWAY].inthreeway && 03704 p0->subs[SUB_REAL].owner && 03705 p0->subs[SUB_REAL].inthreeway && 03706 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 03707 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name); 03708 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE); 03709 os0 = p0->subs[SUB_REAL].owner->_state; 03710 } else { 03711 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0); 03712 tone_zone_play_tone(p1->subs[oi0].dfd, -1); 03713 } 03714 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 03715 if (!p0->echocanbridged || !p1->echocanbridged) { 03716 /* Disable echo cancellation if appropriate */ 03717 dahdi_disable_ec(p0); 03718 dahdi_disable_ec(p1); 03719 } 03720 } 03721 dahdi_link(slave, master); 03722 master->inconference = inconf; 03723 } else if (!nothingok) 03724 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]); 03725 03726 update_conf(p0); 03727 update_conf(p1); 03728 t0 = p0->subs[SUB_REAL].inthreeway; 03729 t1 = p1->subs[SUB_REAL].inthreeway; 03730 03731 ast_mutex_unlock(&p0->lock); 03732 ast_mutex_unlock(&p1->lock); 03733 03734 ast_mutex_unlock(&c0->lock); 03735 ast_mutex_unlock(&c1->lock); 03736 03737 /* Native bridge failed */ 03738 if ((!master || !slave) && !nothingok) { 03739 dahdi_enable_ec(p0); 03740 dahdi_enable_ec(p1); 03741 return AST_BRIDGE_FAILED; 03742 } 03743 03744 if (option_verbose > 2) 03745 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name); 03746 03747 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 03748 disable_dtmf_detect(op0); 03749 03750 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 03751 disable_dtmf_detect(op1); 03752 03753 for (;;) { 03754 struct ast_channel *c0_priority[2] = {c0, c1}; 03755 struct ast_channel *c1_priority[2] = {c1, c0}; 03756 03757 /* Here's our main loop... Start by locking things, looking for private parts, 03758 and then balking if anything is wrong */ 03759 ast_mutex_lock(&c0->lock); 03760 while (ast_mutex_trylock(&c1->lock)) { 03761 DEADLOCK_AVOIDANCE(&c0->lock); 03762 } 03763 03764 p0 = c0->tech_pvt; 03765 p1 = c1->tech_pvt; 03766 03767 if (op0 == p0) 03768 i0 = dahdi_get_index(c0, p0, 1); 03769 if (op1 == p1) 03770 i1 = dahdi_get_index(c1, p1, 1); 03771 ast_mutex_unlock(&c0->lock); 03772 ast_mutex_unlock(&c1->lock); 03773 03774 if (!timeoutms || 03775 (op0 != p0) || 03776 (op1 != p1) || 03777 (ofd0 != c0->fds[0]) || 03778 (ofd1 != c1->fds[0]) || 03779 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 03780 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 03781 (oc0 != p0->owner) || 03782 (oc1 != p1->owner) || 03783 (t0 != p0->subs[SUB_REAL].inthreeway) || 03784 (t1 != p1->subs[SUB_REAL].inthreeway) || 03785 (oi0 != i0) || 03786 (oi1 != i1)) { 03787 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n", 03788 op0->channel, oi0, op1->channel, oi1); 03789 res = AST_BRIDGE_RETRY; 03790 goto return_from_bridge; 03791 } 03792 03793 #ifdef PRI_2BCT 03794 q931c0 = p0->call; 03795 q931c1 = p1->call; 03796 if (p0->transfer && p1->transfer 03797 && q931c0 && q931c1 03798 && !triedtopribridge) { 03799 pri_channel_bridge(q931c0, q931c1); 03800 triedtopribridge = 1; 03801 } 03802 #endif 03803 03804 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms); 03805 if (!who) { 03806 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 03807 continue; 03808 } 03809 f = ast_read(who); 03810 if (!f || (f->frametype == AST_FRAME_CONTROL)) { 03811 *fo = f; 03812 *rc = who; 03813 res = AST_BRIDGE_COMPLETE; 03814 goto return_from_bridge; 03815 } 03816 if (f->frametype == AST_FRAME_DTMF) { 03817 if ((who == c0) && p0->pulsedial) { 03818 ast_write(c1, f); 03819 } else if ((who == c1) && p1->pulsedial) { 03820 ast_write(c0, f); 03821 } else { 03822 *fo = f; 03823 *rc = who; 03824 res = AST_BRIDGE_COMPLETE; 03825 goto return_from_bridge; 03826 } 03827 } 03828 ast_frfree(f); 03829 03830 /* Swap who gets priority */ 03831 priority = !priority; 03832 } 03833 03834 return_from_bridge: 03835 if (op0 == p0) 03836 dahdi_enable_ec(p0); 03837 03838 if (op1 == p1) 03839 dahdi_enable_ec(p1); 03840 03841 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 03842 enable_dtmf_detect(op0); 03843 03844 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 03845 enable_dtmf_detect(op1); 03846 03847 dahdi_unlink(slave, master, 1); 03848 03849 return res; 03850 }
static int dahdi_call | ( | struct ast_channel * | ast, | |
char * | rdest, | |||
int | timeout | |||
) | [static] |
Definition at line 2136 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_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_WARNING, dahdi_pvt::logicalspan, MAX_CALLERID_SIZE, 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::radio, dahdi_pvt::rxgain, s, send_callerid(), dahdi_pvt::sendcalleridafter, set_actual_gain(), dahdi_pvt::sig, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::stripmsd, SUB_CALLWAIT, SUB_REAL, dahdi_pvt::subs, ast_channel::tech_pvt, ast_channel::transfercapability, dahdi_pvt::txgain, dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, VERBOSE_PREFIX_3, and dahdi_pvt::whichwink.
02137 { 02138 struct dahdi_pvt *p = ast->tech_pvt; 02139 int x, res, index,mysig; 02140 char *c, *n, *l; 02141 #ifdef HAVE_PRI 02142 char *s = NULL; 02143 #endif 02144 char dest[256]; /* must be same length as p->dialdest */ 02145 ast_mutex_lock(&p->lock); 02146 ast_copy_string(dest, rdest, sizeof(dest)); 02147 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest)); 02148 if ((ast->_state == AST_STATE_BUSY)) { 02149 p->subs[SUB_REAL].needbusy = 1; 02150 ast_mutex_unlock(&p->lock); 02151 return 0; 02152 } 02153 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 02154 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name); 02155 ast_mutex_unlock(&p->lock); 02156 return -1; 02157 } 02158 p->dialednone = 0; 02159 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ 02160 { 02161 /* Special pseudo -- automatically up */ 02162 ast_setstate(ast, AST_STATE_UP); 02163 ast_mutex_unlock(&p->lock); 02164 return 0; 02165 } 02166 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE; 02167 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 02168 if (res) 02169 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno)); 02170 p->outgoing = 1; 02171 02172 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02173 02174 mysig = p->sig; 02175 if (p->outsigmod > -1) 02176 mysig = p->outsigmod; 02177 02178 switch (mysig) { 02179 case SIG_FXOLS: 02180 case SIG_FXOGS: 02181 case SIG_FXOKS: 02182 if (p->owner == ast) { 02183 /* Normal ring, on hook */ 02184 02185 /* Don't send audio while on hook, until the call is answered */ 02186 p->dialing = 1; 02187 if (p->use_callerid) { 02188 /* Generate the Caller-ID spill if desired */ 02189 if (p->cidspill) { 02190 ast_log(LOG_WARNING, "cidspill already exists??\n"); 02191 free(p->cidspill); 02192 } 02193 p->callwaitcas = 0; 02194 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) { 02195 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p)); 02196 p->cidpos = 0; 02197 send_callerid(p); 02198 } 02199 } 02200 /* Choose proper cadence */ 02201 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { 02202 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) 02203 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); 02204 p->cidrings = cidrings[p->distinctivering - 1]; 02205 } else { 02206 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) 02207 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); 02208 p->cidrings = p->sendcalleridafter; 02209 } 02210 02211 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */ 02212 c = strchr(dest, '/'); 02213 if (c) 02214 c++; 02215 if (c && (strlen(c) < p->stripmsd)) { 02216 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02217 c = NULL; 02218 } 02219 if (c) { 02220 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02221 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c); 02222 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c); 02223 } else { 02224 p->dop.dialstr[0] = '\0'; 02225 } 02226 x = DAHDI_RING; 02227 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) { 02228 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno)); 02229 ast_mutex_unlock(&p->lock); 02230 return -1; 02231 } 02232 p->dialing = 1; 02233 } else { 02234 /* Call waiting call */ 02235 p->callwaitrings = 0; 02236 if (ast->cid.cid_num) 02237 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num)); 02238 else 02239 p->callwait_num[0] = '\0'; 02240 if (ast->cid.cid_name) 02241 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name)); 02242 else 02243 p->callwait_name[0] = '\0'; 02244 /* Call waiting tone instead */ 02245 if (dahdi_callwait(ast)) { 02246 ast_mutex_unlock(&p->lock); 02247 return -1; 02248 } 02249 /* Make ring-back */ 02250 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE)) 02251 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name); 02252 02253 } 02254 n = ast->cid.cid_name; 02255 l = ast->cid.cid_num; 02256 if (l) 02257 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num)); 02258 else 02259 p->lastcid_num[0] = '\0'; 02260 if (n) 02261 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name)); 02262 else 02263 p->lastcid_name[0] = '\0'; 02264 ast_setstate(ast, AST_STATE_RINGING); 02265 index = dahdi_get_index(ast, p, 0); 02266 if (index > -1) { 02267 p->subs[index].needringing = 1; 02268 } 02269 break; 02270 case SIG_FXSLS: 02271 case SIG_FXSGS: 02272 case SIG_FXSKS: 02273 case SIG_EMWINK: 02274 case SIG_EM: 02275 case SIG_EM_E1: 02276 case SIG_FEATD: 02277 case SIG_FEATDMF: 02278 case SIG_E911: 02279 case SIG_FGC_CAMA: 02280 case SIG_FGC_CAMAMF: 02281 case SIG_FEATB: 02282 case SIG_SFWINK: 02283 case SIG_SF: 02284 case SIG_SF_FEATD: 02285 case SIG_SF_FEATDMF: 02286 case SIG_FEATDMF_TA: 02287 case SIG_SF_FEATB: 02288 c = strchr(dest, '/'); 02289 if (c) 02290 c++; 02291 else 02292 c = ""; 02293 if (strlen(c) < p->stripmsd) { 02294 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02295 ast_mutex_unlock(&p->lock); 02296 return -1; 02297 } 02298 #ifdef HAVE_PRI 02299 /* Start the trunk, if not GR-303 */ 02300 if (!p->pri) { 02301 #endif 02302 x = DAHDI_START; 02303 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02304 if (res < 0) { 02305 if (errno != EINPROGRESS) { 02306 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 02307 ast_mutex_unlock(&p->lock); 02308 return -1; 02309 } 02310 } 02311 #ifdef HAVE_PRI 02312 } 02313 #endif 02314 ast_log(LOG_DEBUG, "Dialing '%s'\n", c); 02315 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02316 02317 c += p->stripmsd; 02318 02319 switch (mysig) { 02320 case SIG_FEATD: 02321 l = ast->cid.cid_num; 02322 if (l) 02323 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c); 02324 else 02325 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c); 02326 break; 02327 case SIG_FEATDMF: 02328 l = ast->cid.cid_num; 02329 if (l) 02330 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c); 02331 else 02332 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c); 02333 break; 02334 case SIG_FEATDMF_TA: 02335 { 02336 const char *cic, *ozz; 02337 02338 /* If you have to go through a Tandem Access point you need to use this */ 02339 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ"); 02340 if (!ozz) 02341 ozz = defaultozz; 02342 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC"); 02343 if (!cic) 02344 cic = defaultcic; 02345 if (!ozz || !cic) { 02346 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n"); 02347 ast_mutex_unlock(&p->lock); 02348 return -1; 02349 } 02350 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic); 02351 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c); 02352 p->whichwink = 0; 02353 } 02354 break; 02355 case SIG_E911: 02356 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr)); 02357 break; 02358 case SIG_FGC_CAMA: 02359 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c); 02360 break; 02361 case SIG_FGC_CAMAMF: 02362 case SIG_FEATB: 02363 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c); 02364 break; 02365 default: 02366 if (p->pulse) 02367 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c); 02368 else 02369 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c); 02370 break; 02371 } 02372 02373 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) { 02374 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 02375 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 02376 p->echorest[sizeof(p->echorest) - 1] = '\0'; 02377 p->echobreak = 1; 02378 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 02379 } else 02380 p->echobreak = 0; 02381 if (!res) { 02382 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 02383 int saveerr = errno; 02384 02385 x = DAHDI_ONHOOK; 02386 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02387 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 02388 ast_mutex_unlock(&p->lock); 02389 return -1; 02390 } 02391 } else 02392 ast_log(LOG_DEBUG, "Deferring dialing...\n"); 02393 p->dialing = 1; 02394 if (ast_strlen_zero(c)) 02395 p->dialednone = 1; 02396 ast_setstate(ast, AST_STATE_DIALING); 02397 break; 02398 case 0: 02399 /* Special pseudo -- automatically up*/ 02400 ast_setstate(ast, AST_STATE_UP); 02401 break; 02402 case SIG_PRI: 02403 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */ 02404 p->dialdest[0] = '\0'; 02405 break; 02406 default: 02407 ast_log(LOG_DEBUG, "not yet implemented\n"); 02408 ast_mutex_unlock(&p->lock); 02409 return -1; 02410 } 02411 #ifdef HAVE_PRI 02412 if (p->pri) { 02413 struct pri_sr *sr; 02414 #ifdef SUPPORT_USERUSER 02415 const char *useruser; 02416 #endif 02417 int pridialplan; 02418 int dp_strip; 02419 int prilocaldialplan; 02420 int ldp_strip; 02421 int exclusive; 02422 const char *rr_str; 02423 int redirect_reason; 02424 02425 c = strchr(dest, '/'); 02426 if (c) { 02427 c++; 02428 } else { 02429 c = ""; 02430 } 02431 02432 l = NULL; 02433 n = NULL; 02434 if (!p->hidecallerid) { 02435 l = ast->cid.cid_num; 02436 if (!p->hidecalleridname) { 02437 n = ast->cid.cid_name; 02438 } 02439 } 02440 02441 02442 if (strlen(c) < p->stripmsd) { 02443 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02444 ast_mutex_unlock(&p->lock); 02445 return -1; 02446 } 02447 if (mysig != SIG_FXSKS) { 02448 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02449 s = strchr(c + p->stripmsd, 'w'); 02450 if (s) { 02451 if (strlen(s) > 1) 02452 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s); 02453 else 02454 p->dop.dialstr[0] = '\0'; 02455 *s = '\0'; 02456 } else { 02457 p->dop.dialstr[0] = '\0'; 02458 } 02459 } 02460 if (pri_grab(p, p->pri)) { 02461 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 02462 ast_mutex_unlock(&p->lock); 02463 return -1; 02464 } 02465 if (!(p->call = pri_new_call(p->pri->pri))) { 02466 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel); 02467 pri_rel(p->pri); 02468 ast_mutex_unlock(&p->lock); 02469 return -1; 02470 } 02471 if (!(sr = pri_sr_new())) { 02472 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel); 02473 pri_destroycall(p->pri->pri, p->call); 02474 p->call = NULL; 02475 pri_rel(p->pri); 02476 ast_mutex_unlock(&p->lock); 02477 return -1; 02478 } 02479 if (p->bearer || (mysig == SIG_FXSKS)) { 02480 if (p->bearer) { 02481 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); 02482 p->bearer->call = p->call; 02483 } else 02484 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n"); 02485 pri_set_crv(p->pri->pri, p->call, p->channel, 0); 02486 } 02487 p->digital = IS_DIGITAL(ast->transfercapability); 02488 /* Add support for exclusive override */ 02489 if (p->priexclusive) 02490 exclusive = 1; 02491 else { 02492 /* otherwise, traditional behavior */ 02493 if (p->pri->nodetype == PRI_NETWORK) 02494 exclusive = 0; 02495 else 02496 exclusive = 1; 02497 } 02498 02499 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1); 02500 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 02501 (p->digital ? -1 : 02502 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW))); 02503 if (p->pri->facilityenable) 02504 pri_facility_enable(p->pri->pri); 02505 02506 if (option_verbose > 2) 02507 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability)); 02508 dp_strip = 0; 02509 pridialplan = p->pri->dialplan - 1; 02510 if (pridialplan == -2) { /* compute dynamically */ 02511 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 02512 dp_strip = strlen(p->pri->internationalprefix); 02513 pridialplan = PRI_INTERNATIONAL_ISDN; 02514 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 02515 dp_strip = strlen(p->pri->nationalprefix); 02516 pridialplan = PRI_NATIONAL_ISDN; 02517 } else { 02518 pridialplan = PRI_LOCAL_ISDN; 02519 } 02520 } 02521 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0); 02522 02523 ldp_strip = 0; 02524 prilocaldialplan = p->pri->localdialplan - 1; 02525 if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */ 02526 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 02527 ldp_strip = strlen(p->pri->internationalprefix); 02528 prilocaldialplan = PRI_INTERNATIONAL_ISDN; 02529 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 02530 ldp_strip = strlen(p->pri->nationalprefix); 02531 prilocaldialplan = PRI_NATIONAL_ISDN; 02532 } else { 02533 prilocaldialplan = PRI_LOCAL_ISDN; 02534 } 02535 } 02536 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan, 02537 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE)); 02538 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) { 02539 if (!strcasecmp(rr_str, "UNKNOWN")) 02540 redirect_reason = 0; 02541 else if (!strcasecmp(rr_str, "BUSY")) 02542 redirect_reason = 1; 02543 else if (!strcasecmp(rr_str, "NO_REPLY")) 02544 redirect_reason = 2; 02545 else if (!strcasecmp(rr_str, "UNCONDITIONAL")) 02546 redirect_reason = 15; 02547 else 02548 redirect_reason = PRI_REDIR_UNCONDITIONAL; 02549 } else 02550 redirect_reason = PRI_REDIR_UNCONDITIONAL; 02551 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason); 02552 02553 #ifdef SUPPORT_USERUSER 02554 /* User-user info */ 02555 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO"); 02556 02557 if (useruser) 02558 pri_sr_set_useruser(sr, useruser); 02559 #endif 02560 02561 if (pri_setup(p->pri->pri, p->call, sr)) { 02562 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 02563 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan)); 02564 pri_rel(p->pri); 02565 ast_mutex_unlock(&p->lock); 02566 pri_sr_free(sr); 02567 return -1; 02568 } 02569 pri_sr_free(sr); 02570 ast_setstate(ast, AST_STATE_DIALING); 02571 pri_rel(p->pri); 02572 } 02573 #endif 02574 ast_mutex_unlock(&p->lock); 02575 return 0; 02576 }
static int dahdi_callwait | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 2108 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().
02109 { 02110 struct dahdi_pvt *p = ast->tech_pvt; 02111 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 02112 if (p->cidspill) { 02113 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 02114 free(p->cidspill); 02115 } 02116 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 02117 return -1; 02118 save_conference(p); 02119 /* Silence */ 02120 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 02121 if (!p->callwaitrings && p->callwaitingcallerid) { 02122 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 02123 p->callwaitcas = 1; 02124 p->cidlen = 2400 + 680 + READ_SIZE * 4; 02125 } else { 02126 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 02127 p->callwaitcas = 0; 02128 p->cidlen = 2400 + READ_SIZE * 4; 02129 } 02130 p->cidpos = 0; 02131 send_callerid(p); 02132 02133 return 0; 02134 }
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 924 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().
00924 { 00925 /* recall that if a field is not included here it is initialized 00926 * to 0 or equivalent 00927 */ 00928 struct dahdi_chan_conf conf = { 00929 #ifdef HAVE_PRI 00930 .pri = { 00931 .nsf = PRI_NSF_NONE, 00932 .switchtype = PRI_SWITCH_NI2, 00933 .dialplan = PRI_NATIONAL_ISDN + 1, 00934 .localdialplan = PRI_NATIONAL_ISDN + 1, 00935 .nodetype = PRI_CPE, 00936 00937 .minunused = 2, 00938 .idleext = "", 00939 .idledial = "", 00940 .internationalprefix = "", 00941 .nationalprefix = "", 00942 .localprefix = "", 00943 .privateprefix = "", 00944 .unknownprefix = "", 00945 00946 .resetinterval = 3600 00947 }, 00948 #endif 00949 .chan = { 00950 .context = "default", 00951 .cid_num = "", 00952 .cid_name = "", 00953 .mohinterpret = "default", 00954 .mohsuggest = "", 00955 .transfertobusy = 1, 00956 00957 .cid_signalling = CID_SIG_BELL, 00958 .cid_start = CID_START_RING, 00959 .dahditrcallerid = 0, 00960 .use_callerid = 1, 00961 .sig = -1, 00962 .outsigmod = -1, 00963 00964 .tonezone = -1, 00965 00966 .echocancel = 1, 00967 00968 .busycount = 3, 00969 .busycompare = 0, 00970 .busytonelength = 0, 00971 .busyquietlength = 0, 00972 .busyfuzziness = 0, 00973 .silencethreshold = 0, 00974 00975 .accountcode = "", 00976 00977 .mailbox = "", 00978 00979 00980 .polarityonanswerdelay = 600, 00981 00982 .sendcalleridafter = DEFAULT_CIDRINGS, 00983 00984 .buf_policy = DAHDI_POLICY_IMMEDIATE, 00985 .buf_no = numbufs 00986 }, 00987 .timing = { 00988 .prewinktime = -1, 00989 .preflashtime = -1, 00990 .winktime = -1, 00991 .flashtime = -1, 00992 .starttime = -1, 00993 .rxwinktime = -1, 00994 .rxflashtime = -1, 00995 .debouncetime = -1 00996 }, 00997 .smdi_port = "/dev/ttyS0", 00998 }; 00999 01000 return conf; 01001 }
static void dahdi_close | ( | int | fd | ) | [static] |
Definition at line 1268 of file chan_dahdi.c.
Referenced by dahdi_close_pri_fd(), and dahdi_close_sub().
static void dahdi_close_pri_fd | ( | struct dahdi_pri * | pri, | |
int | fd_num | |||
) | [static] |
Definition at line 1281 of file chan_dahdi.c.
References dahdi_close(), and dahdi_pri::fds.
Referenced by __unload_module(), dahdi_restart(), and start_pri().
01282 { 01283 dahdi_close(pri->fds[fd_num]); 01284 pri->fds[fd_num] = -1; 01285 }
static void dahdi_close_sub | ( | struct dahdi_pvt * | chan_pvt, | |
int | sub_num | |||
) | [static] |
Definition at line 1274 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().
01275 { 01276 dahdi_close(chan_pvt->subs[sub_num].dfd); 01277 chan_pvt->subs[sub_num].dfd = -1; 01278 }
static int dahdi_confmute | ( | struct dahdi_pvt * | p, | |
int | muted | |||
) | [inline, static] |
Definition at line 1991 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().
01992 { 01993 int x, y, res; 01994 x = muted; 01995 if (p->sig == SIG_PRI) { 01996 y = 1; 01997 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y); 01998 if (res) 01999 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno)); 02000 } 02001 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x); 02002 if (res < 0) 02003 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno)); 02004 return res; 02005 }
static int dahdi_destroy_channel | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 10385 of file chan_dahdi.c.
References dahdi_destroy_channel_bynum(), and RESULT_SHOWUSAGE.
10386 { 10387 int channel; 10388 10389 if (argc != 4) 10390 return RESULT_SHOWUSAGE; 10391 10392 channel = atoi(argv[3]); 10393 10394 return dahdi_destroy_channel_bynum(channel); 10395 }
static int dahdi_destroy_channel_bynum | ( | int | channel | ) | [static] |
Definition at line 7041 of file chan_dahdi.c.
References ast_module_unref(), dahdi_pvt::channel, destroy_channel(), iflist, dahdi_pvt::next, dahdi_pvt::prev, RESULT_FAILURE, RESULT_SUCCESS, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_destroy_channel(), and handle_init_event().
07042 { 07043 struct dahdi_pvt *tmp = NULL; 07044 struct dahdi_pvt *prev = NULL; 07045 07046 tmp = iflist; 07047 while (tmp) { 07048 if (tmp->channel == channel) { 07049 int x = DAHDI_FLASH; 07050 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 */ 07051 destroy_channel(prev, tmp, 1); 07052 ast_module_unref(ast_module_info->self); 07053 return RESULT_SUCCESS; 07054 } 07055 prev = tmp; 07056 tmp = tmp->next; 07057 } 07058 return RESULT_FAILURE; 07059 }
static int dahdi_digit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 1365 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.
01366 { 01367 struct dahdi_pvt *pvt; 01368 int index; 01369 int dtmf = -1; 01370 01371 pvt = chan->tech_pvt; 01372 01373 ast_mutex_lock(&pvt->lock); 01374 01375 index = dahdi_get_index(chan, pvt, 0); 01376 01377 if ((index != SUB_REAL) || !pvt->owner) 01378 goto out; 01379 01380 #ifdef HAVE_PRI 01381 if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) { 01382 if (pvt->setup_ack) { 01383 if (!pri_grab(pvt, pvt->pri)) { 01384 pri_information(pvt->pri->pri, pvt->call, digit); 01385 pri_rel(pvt->pri); 01386 } else 01387 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span); 01388 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) { 01389 int res; 01390 ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit); 01391 res = strlen(pvt->dialdest); 01392 pvt->dialdest[res++] = digit; 01393 pvt->dialdest[res] = '\0'; 01394 } 01395 goto out; 01396 } 01397 #endif 01398 if ((dtmf = digit_to_dtmfindex(digit)) == -1) 01399 goto out; 01400 01401 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) { 01402 int res; 01403 struct dahdi_dialoperation zo = { 01404 .op = DAHDI_DIAL_OP_APPEND, 01405 .dialstr[0] = 'T', 01406 .dialstr[1] = digit, 01407 .dialstr[2] = 0, 01408 }; 01409 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo))) 01410 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno)); 01411 else 01412 pvt->dialing = 1; 01413 } else { 01414 ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit); 01415 pvt->dialing = 1; 01416 pvt->begindigit = digit; 01417 } 01418 01419 out: 01420 ast_mutex_unlock(&pvt->lock); 01421 01422 return 0; 01423 }
static int dahdi_digit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 1425 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.
01426 { 01427 struct dahdi_pvt *pvt; 01428 int res = 0; 01429 int index; 01430 int x; 01431 01432 pvt = chan->tech_pvt; 01433 01434 ast_mutex_lock(&pvt->lock); 01435 01436 index = dahdi_get_index(chan, pvt, 0); 01437 01438 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse) 01439 goto out; 01440 01441 #ifdef HAVE_PRI 01442 /* This means that the digit was already sent via PRI signalling */ 01443 if (pvt->sig == SIG_PRI && !pvt->begindigit) 01444 goto out; 01445 #endif 01446 01447 if (pvt->begindigit) { 01448 x = -1; 01449 ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit); 01450 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x); 01451 pvt->dialing = 0; 01452 pvt->begindigit = 0; 01453 } 01454 01455 out: 01456 ast_mutex_unlock(&pvt->lock); 01457 01458 return res; 01459 }
static void dahdi_disable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1822 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().
01823 { 01824 int x; 01825 int res; 01826 if (p->echocancel) { 01827 x = 0; 01828 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x); 01829 if (res) 01830 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno)); 01831 else if (option_debug) 01832 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel); 01833 } 01834 p->echocanon = 0; 01835 }
static void dahdi_enable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1772 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_pvt::digital, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, LOG_DEBUG, LOG_WARNING, option_debug, dahdi_pvt::sig, SIG_PRI, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), dahdi_answer(), dahdi_bridge(), dahdi_handle_event(), dahdi_setoption(), handle_init_event(), and ss_thread().
01773 { 01774 int x; 01775 int res; 01776 if (!p) 01777 return; 01778 if (p->echocanon) { 01779 ast_log(LOG_DEBUG, "Echo cancellation already on\n"); 01780 return; 01781 } 01782 if (p->digital) { 01783 ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n"); 01784 return; 01785 } 01786 if (p->echocancel) { 01787 if (p->sig == SIG_PRI) { 01788 x = 1; 01789 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x); 01790 if (res) 01791 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno)); 01792 } 01793 x = p->echocancel; 01794 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x); 01795 if (res) 01796 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno)); 01797 else { 01798 p->echocanon = 1; 01799 if (option_debug) 01800 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel); 01801 } 01802 } else if (option_debug) 01803 ast_log(LOG_DEBUG, "No echo cancellation requested\n"); 01804 }
static struct ast_frame * dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5067 of file chan_dahdi.c.
References __dahdi_exception(), ast_mutex_lock(), ast_mutex_unlock(), f, dahdi_pvt::lock, and ast_channel::tech_pvt.
05068 { 05069 struct dahdi_pvt *p = ast->tech_pvt; 05070 struct ast_frame *f; 05071 ast_mutex_lock(&p->lock); 05072 f = __dahdi_exception(ast); 05073 ast_mutex_unlock(&p->lock); 05074 return f; 05075 }
static int dahdi_fake_event | ( | struct dahdi_pvt * | p, | |
int | mode | |||
) | [static] |
Definition at line 10913 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().
10914 { 10915 if (p) { 10916 switch (mode) { 10917 case TRANSFER: 10918 p->fake_event = DAHDI_EVENT_WINKFLASH; 10919 break; 10920 case HANGUP: 10921 p->fake_event = DAHDI_EVENT_ONHOOK; 10922 break; 10923 default: 10924 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name); 10925 } 10926 } 10927 return 0; 10928 }
static int dahdi_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 3852 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.
03853 { 03854 struct dahdi_pvt *p = newchan->tech_pvt; 03855 int x; 03856 ast_mutex_lock(&p->lock); 03857 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name); 03858 if (p->owner == oldchan) { 03859 p->owner = newchan; 03860 } 03861 for (x = 0; x < 3; x++) 03862 if (p->subs[x].owner == oldchan) { 03863 if (!x) 03864 dahdi_unlink(NULL, p, 0); 03865 p->subs[x].owner = newchan; 03866 } 03867 if (newchan->_state == AST_STATE_RINGING) 03868 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0); 03869 update_conf(p); 03870 ast_mutex_unlock(&p->lock); 03871 return 0; 03872 }
static int dahdi_func_read | ( | struct ast_channel * | chan, | |
char * | function, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 3424 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.
03425 { 03426 struct dahdi_pvt *p = chan->tech_pvt; 03427 03428 if (!strcasecmp(data, "rxgain")) { 03429 ast_mutex_lock(&p->lock); 03430 snprintf(buf, len, "%f", p->rxgain); 03431 ast_mutex_unlock(&p->lock); 03432 } else if (!strcasecmp(data, "txgain")) { 03433 ast_mutex_lock(&p->lock); 03434 snprintf(buf, len, "%f", p->txgain); 03435 ast_mutex_unlock(&p->lock); 03436 } else { 03437 ast_copy_string(buf, "", len); 03438 } 03439 return 0; 03440 }
static int dahdi_get_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition at line 256 of file chan_dahdi.c.
Referenced by __dahdi_exception(), dahdi_handle_event(), and ss_thread().
00257 { 00258 int j; 00259 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) 00260 return -1; 00261 return j; 00262 }
static int dahdi_get_index | ( | struct ast_channel * | ast, | |
struct dahdi_pvt * | p, | |||
int | nullok | |||
) | [static] |
Definition at line 1117 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().
01118 { 01119 int res; 01120 if (p->subs[SUB_REAL].owner == ast) 01121 res = 0; 01122 else if (p->subs[SUB_CALLWAIT].owner == ast) 01123 res = 1; 01124 else if (p->subs[SUB_THREEWAY].owner == ast) 01125 res = 2; 01126 else { 01127 res = -1; 01128 if (!nullok) 01129 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n"); 01130 } 01131 return res; 01132 }
static void dahdi_handle_dtmfup | ( | struct ast_channel * | ast, | |
int | index, | |||
struct ast_frame ** | dest | |||
) | [static] |
Definition at line 4015 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().
04016 { 04017 struct dahdi_pvt *p = ast->tech_pvt; 04018 struct ast_frame *f = *dest; 04019 04020 if (option_debug) 04021 ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name); 04022 04023 if (p->confirmanswer) { 04024 if (option_debug) 04025 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name); 04026 /* Upon receiving a DTMF digit, consider this an answer confirmation instead 04027 of a DTMF digit */ 04028 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04029 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 04030 *dest = &p->subs[index].f; 04031 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */ 04032 p->confirmanswer = 0; 04033 } else if (p->callwaitcas) { 04034 if ((f->subclass == 'A') || (f->subclass == 'D')) { 04035 if (option_debug) 04036 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n"); 04037 if (p->cidspill) 04038 free(p->cidspill); 04039 send_cwcidspill(p); 04040 } 04041 if ((f->subclass != 'm') && (f->subclass != 'u')) 04042 p->callwaitcas = 0; 04043 p->subs[index].f.frametype = AST_FRAME_NULL; 04044 p->subs[index].f.subclass = 0; 04045 *dest = &p->subs[index].f; 04046 } else if (f->subclass == 'f') { 04047 /* Fax tone -- Handle and return NULL */ 04048 if ((p->callprogress & 0x6) && !p->faxhandled) { 04049 p->faxhandled = 1; 04050 if (strcmp(ast->exten, "fax")) { 04051 const char *target_context = S_OR(ast->macrocontext, ast->context); 04052 04053 /* We need to unlock 'ast' here because ast_exists_extension has the 04054 * potential to start autoservice on the channel. Such action is prone 04055 * to deadlock. 04056 */ 04057 ast_mutex_unlock(&p->lock); 04058 ast_channel_unlock(ast); 04059 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) { 04060 ast_channel_lock(ast); 04061 ast_mutex_lock(&p->lock); 04062 if (option_verbose > 2) 04063 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name); 04064 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 04065 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 04066 if (ast_async_goto(ast, target_context, "fax", 1)) 04067 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 04068 } else { 04069 ast_channel_lock(ast); 04070 ast_mutex_lock(&p->lock); 04071 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 04072 } 04073 } else if (option_debug) 04074 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n"); 04075 } else if (option_debug) 04076 ast_log(LOG_DEBUG, "Fax already handled\n"); 04077 dahdi_confmute(p, 0); 04078 p->subs[index].f.frametype = AST_FRAME_NULL; 04079 p->subs[index].f.subclass = 0; 04080 *dest = &p->subs[index].f; 04081 } else if (f->subclass == 'm') { 04082 /* Confmute request */ 04083 dahdi_confmute(p, 1); 04084 p->subs[index].f.frametype = AST_FRAME_NULL; 04085 p->subs[index].f.subclass = 0; 04086 *dest = &p->subs[index].f; 04087 } else if (f->subclass == 'u') { 04088 /* Unmute */ 04089 dahdi_confmute(p, 0); 04090 p->subs[index].f.frametype = AST_FRAME_NULL; 04091 p->subs[index].f.subclass = 0; 04092 *dest = &p->subs[index].f; 04093 } else 04094 dahdi_confmute(p, 0); 04095 }
static struct ast_frame* dahdi_handle_event | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 4117 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_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::radio, restore_conference(), ast_channel::rings, dahdi_pvt::ringt, dahdi_pvt::ringt_base, S_OR, ast_frame::samples, save_conference(), dahdi_pvt::sig, sig2str, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, ast_frame::src, ss_thread(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, ast_frame::subclass, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, dahdi_pvt::threewaycalling, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, unalloc_sub(), dahdi_pvt::unknown_alarm, update_conf(), VERBOSE_PREFIX_3, and dahdi_pvt::whichwink.
Referenced by __dahdi_exception().
04118 { 04119 int res, x; 04120 int index, mysig; 04121 char *c; 04122 struct dahdi_pvt *p = ast->tech_pvt; 04123 pthread_t threadid; 04124 pthread_attr_t attr; 04125 struct ast_channel *chan; 04126 struct ast_frame *f; 04127 04128 index = dahdi_get_index(ast, p, 0); 04129 mysig = p->sig; 04130 if (p->outsigmod > -1) 04131 mysig = p->outsigmod; 04132 p->subs[index].f.frametype = AST_FRAME_NULL; 04133 p->subs[index].f.subclass = 0; 04134 p->subs[index].f.datalen = 0; 04135 p->subs[index].f.samples = 0; 04136 p->subs[index].f.mallocd = 0; 04137 p->subs[index].f.offset = 0; 04138 p->subs[index].f.src = "dahdi_handle_event"; 04139 p->subs[index].f.data = NULL; 04140 f = &p->subs[index].f; 04141 04142 if (index < 0) 04143 return &p->subs[index].f; 04144 if (p->fake_event) { 04145 res = p->fake_event; 04146 p->fake_event = 0; 04147 } else 04148 res = dahdi_get_event(p->subs[index].dfd); 04149 04150 if (option_debug) 04151 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index); 04152 04153 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) { 04154 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0; 04155 04156 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff); 04157 #ifdef HAVE_PRI 04158 if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) { 04159 /* absorb event */ 04160 } else { 04161 #endif 04162 p->subs[index].f.frametype = AST_FRAME_DTMF_END; 04163 p->subs[index].f.subclass = res & 0xff; 04164 #ifdef HAVE_PRI 04165 } 04166 #endif 04167 dahdi_handle_dtmfup(ast, index, &f); 04168 return f; 04169 } 04170 04171 if (res & DAHDI_EVENT_DTMFDOWN) { 04172 if (option_debug) 04173 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff); 04174 /* Mute conference */ 04175 dahdi_confmute(p, 1); 04176 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN; 04177 p->subs[index].f.subclass = res & 0xff; 04178 return &p->subs[index].f; 04179 } 04180 04181 switch (res) { 04182 #ifdef DAHDI_EVENT_EC_DISABLED 04183 case DAHDI_EVENT_EC_DISABLED: 04184 if (option_verbose > 2) 04185 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel); 04186 p->echocanon = 0; 04187 break; 04188 #endif 04189 case DAHDI_EVENT_BITSCHANGED: 04190 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig)); 04191 case DAHDI_EVENT_PULSE_START: 04192 /* Stop tone if there's a pulse start and the PBX isn't started */ 04193 if (!ast->pbx) 04194 tone_zone_play_tone(p->subs[index].dfd, -1); 04195 break; 04196 case DAHDI_EVENT_DIALCOMPLETE: 04197 if (p->inalarm) break; 04198 if ((p->radio || (p->oprmode < 0))) break; 04199 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) { 04200 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno)); 04201 return NULL; 04202 } 04203 if (!x) { /* if not still dialing in driver */ 04204 dahdi_enable_ec(p); 04205 if (p->echobreak) { 04206 dahdi_train_ec(p); 04207 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); 04208 p->dop.op = DAHDI_DIAL_OP_REPLACE; 04209 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 04210 p->echobreak = 0; 04211 } else { 04212 p->dialing = 0; 04213 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) { 04214 /* if thru with dialing after offhook */ 04215 if (ast->_state == AST_STATE_DIALING_OFFHOOK) { 04216 ast_setstate(ast, AST_STATE_UP); 04217 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04218 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 04219 break; 04220 } else { /* if to state wait for offhook to dial rest */ 04221 /* we now wait for off hook */ 04222 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK); 04223 } 04224 } 04225 if (ast->_state == AST_STATE_DIALING) { 04226 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 04227 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n"); 04228 } 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)))) { 04229 ast_setstate(ast, AST_STATE_RINGING); 04230 } else if (!p->answeronpolarityswitch) { 04231 ast_setstate(ast, AST_STATE_UP); 04232 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04233 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 04234 /* If aops=0 and hops=1, this is necessary */ 04235 p->polarity = POLARITY_REV; 04236 } else { 04237 /* Start clean, so we can catch the change to REV polarity when party answers */ 04238 p->polarity = POLARITY_IDLE; 04239 } 04240 } 04241 } 04242 } 04243 break; 04244 case DAHDI_EVENT_ALARM: 04245 #ifdef HAVE_PRI 04246 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) { 04247 /* T309 is not enabled : hangup calls when alarm occurs */ 04248 if (p->call) { 04249 if (p->pri && p->pri->pri) { 04250 if (!pri_grab(p, p->pri)) { 04251 pri_hangup(p->pri->pri, p->call, -1); 04252 pri_destroycall(p->pri->pri, p->call); 04253 p->call = NULL; 04254 pri_rel(p->pri); 04255 } else 04256 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 04257 } else 04258 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n"); 04259 } 04260 if (p->owner) 04261 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 04262 } 04263 if (p->bearer) 04264 p->bearer->inalarm = 1; 04265 else 04266 #endif 04267 p->inalarm = 1; 04268 res = get_alarms(p); 04269 handle_alarms(p, res); 04270 #ifdef HAVE_LIBPRI 04271 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 04272 /* fall through intentionally */ 04273 } else { 04274 break; 04275 } 04276 #endif 04277 case DAHDI_EVENT_ONHOOK: 04278 if (p->radio) { 04279 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04280 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY; 04281 break; 04282 } 04283 if (p->oprmode < 0) 04284 { 04285 if (p->oprmode != -1) break; 04286 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 04287 { 04288 /* Make sure it starts ringing */ 04289 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 04290 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING); 04291 save_conference(p->oprpeer); 04292 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04293 } 04294 break; 04295 } 04296 switch (p->sig) { 04297 case SIG_FXOLS: 04298 case SIG_FXOGS: 04299 case SIG_FXOKS: 04300 p->onhooktime = time(NULL); 04301 p->msgstate = -1; 04302 /* Check for some special conditions regarding call waiting */ 04303 if (index == SUB_REAL) { 04304 /* The normal line was hung up */ 04305 if (p->subs[SUB_CALLWAIT].owner) { 04306 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */ 04307 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 04308 if (option_verbose > 2) 04309 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel); 04310 unalloc_sub(p, SUB_CALLWAIT); 04311 #if 0 04312 p->subs[index].needanswer = 0; 04313 p->subs[index].needringing = 0; 04314 #endif 04315 p->callwaitingrepeat = 0; 04316 p->cidcwexpire = 0; 04317 p->owner = NULL; 04318 /* Don't start streaming audio yet if the incoming call isn't up yet */ 04319 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP) 04320 p->dialing = 1; 04321 dahdi_ring_phone(p); 04322 } else if (p->subs[SUB_THREEWAY].owner) { 04323 unsigned int mssinceflash; 04324 /* Here we have to retain the lock on both the main channel, the 3-way channel, and 04325 the private structure -- not especially easy or clean */ 04326 while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) { 04327 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */ 04328 ast_mutex_unlock(&p->lock); 04329 DEADLOCK_AVOIDANCE(&ast->lock); 04330 /* We can grab ast and p in that order, without worry. We should make sure 04331 nothing seriously bad has happened though like some sort of bizarre double 04332 masquerade! */ 04333 ast_mutex_lock(&p->lock); 04334 if (p->owner != ast) { 04335 ast_log(LOG_WARNING, "This isn't good...\n"); 04336 return NULL; 04337 } 04338 } 04339 if (!p->subs[SUB_THREEWAY].owner) { 04340 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n"); 04341 return NULL; 04342 } 04343 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime); 04344 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash); 04345 if (mssinceflash < MIN_MS_SINCE_FLASH) { 04346 /* It hasn't been long enough since the last flashook. This is probably a bounce on 04347 hanging up. Hangup both channels now */ 04348 if (p->subs[SUB_THREEWAY].owner) 04349 ast_queue_hangup(p->subs[SUB_THREEWAY].owner); 04350 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04351 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel); 04352 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04353 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) { 04354 if (p->transfer) { 04355 /* In any case this isn't a threeway call anymore */ 04356 p->subs[SUB_REAL].inthreeway = 0; 04357 p->subs[SUB_THREEWAY].inthreeway = 0; 04358 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */ 04359 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) { 04360 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04361 /* Swap subs and dis-own channel */ 04362 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04363 p->owner = NULL; 04364 /* Ring the phone */ 04365 dahdi_ring_phone(p); 04366 } else { 04367 if ((res = attempt_transfer(p)) < 0) { 04368 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04369 if (p->subs[SUB_THREEWAY].owner) 04370 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04371 } else if (res) { 04372 /* Don't actually hang up at this point */ 04373 if (p->subs[SUB_THREEWAY].owner) 04374 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04375 break; 04376 } 04377 } 04378 } else { 04379 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04380 if (p->subs[SUB_THREEWAY].owner) 04381 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04382 } 04383 } else { 04384 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04385 /* Swap subs and dis-own channel */ 04386 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04387 p->owner = NULL; 04388 /* Ring the phone */ 04389 dahdi_ring_phone(p); 04390 } 04391 } 04392 } else { 04393 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index); 04394 } 04395 /* Fall through */ 04396 default: 04397 dahdi_disable_ec(p); 04398 return NULL; 04399 } 04400 break; 04401 case DAHDI_EVENT_RINGOFFHOOK: 04402 if (p->inalarm) break; 04403 if (p->oprmode < 0) 04404 { 04405 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 04406 { 04407 /* Make sure it stops ringing */ 04408 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 04409 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1); 04410 restore_conference(p->oprpeer); 04411 } 04412 break; 04413 } 04414 if (p->radio) 04415 { 04416 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04417 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY; 04418 break; 04419 } 04420 /* for E911, its supposed to wait for offhook then dial 04421 the second half of the dial string */ 04422 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) { 04423 c = strchr(p->dialdest, '/'); 04424 if (c) 04425 c++; 04426 else 04427 c = p->dialdest; 04428 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c); 04429 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr)); 04430 if (strlen(p->dop.dialstr) > 4) { 04431 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 04432 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 04433 p->echorest[sizeof(p->echorest) - 1] = '\0'; 04434 p->echobreak = 1; 04435 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 04436 } else 04437 p->echobreak = 0; 04438 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 04439 int saveerr = errno; 04440 04441 x = DAHDI_ONHOOK; 04442 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04443 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 04444 return NULL; 04445 } 04446 p->dialing = 1; 04447 return &p->subs[index].f; 04448 } 04449 switch (p->sig) { 04450 case SIG_FXOLS: 04451 case SIG_FXOGS: 04452 case SIG_FXOKS: 04453 switch (ast->_state) { 04454 case AST_STATE_RINGING: 04455 dahdi_enable_ec(p); 04456 dahdi_train_ec(p); 04457 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04458 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 04459 /* Make sure it stops ringing */ 04460 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 04461 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel); 04462 if (p->cidspill) { 04463 /* Cancel any running CallerID spill */ 04464 free(p->cidspill); 04465 p->cidspill = NULL; 04466 } 04467 p->dialing = 0; 04468 p->callwaitcas = 0; 04469 if (p->confirmanswer) { 04470 /* Ignore answer if "confirm answer" is enabled */ 04471 p->subs[index].f.frametype = AST_FRAME_NULL; 04472 p->subs[index].f.subclass = 0; 04473 } else if (!ast_strlen_zero(p->dop.dialstr)) { 04474 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ 04475 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 04476 if (res < 0) { 04477 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 04478 p->dop.dialstr[0] = '\0'; 04479 return NULL; 04480 } else { 04481 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr); 04482 p->subs[index].f.frametype = AST_FRAME_NULL; 04483 p->subs[index].f.subclass = 0; 04484 p->dialing = 1; 04485 } 04486 p->dop.dialstr[0] = '\0'; 04487 ast_setstate(ast, AST_STATE_DIALING); 04488 } else 04489 ast_setstate(ast, AST_STATE_UP); 04490 return &p->subs[index].f; 04491 case AST_STATE_DOWN: 04492 ast_setstate(ast, AST_STATE_RING); 04493 ast->rings = 1; 04494 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04495 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK; 04496 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel); 04497 return &p->subs[index].f; 04498 case AST_STATE_UP: 04499 /* Make sure it stops ringing */ 04500 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 04501 /* Okay -- probably call waiting*/ 04502 if (ast_bridged_channel(p->owner)) 04503 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 04504 p->subs[index].needunhold = 1; 04505 break; 04506 case AST_STATE_RESERVED: 04507 /* Start up dialtone */ 04508 if (has_voicemail(p)) 04509 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 04510 else 04511 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 04512 break; 04513 default: 04514 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state); 04515 } 04516 break; 04517 case SIG_FXSLS: 04518 case SIG_FXSGS: 04519 case SIG_FXSKS: 04520 if (ast->_state == AST_STATE_RING) { 04521 p->ringt = p->ringt_base; 04522 } 04523 04524 /* Fall through */ 04525 case SIG_EM: 04526 case SIG_EM_E1: 04527 case SIG_EMWINK: 04528 case SIG_FEATD: 04529 case SIG_FEATDMF: 04530 case SIG_FEATDMF_TA: 04531 case SIG_E911: 04532 case SIG_FGC_CAMA: 04533 case SIG_FGC_CAMAMF: 04534 case SIG_FEATB: 04535 case SIG_SF: 04536 case SIG_SFWINK: 04537 case SIG_SF_FEATD: 04538 case SIG_SF_FEATDMF: 04539 case SIG_SF_FEATB: 04540 if (ast->_state == AST_STATE_PRERING) 04541 ast_setstate(ast, AST_STATE_RING); 04542 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) { 04543 if (option_debug) 04544 ast_log(LOG_DEBUG, "Ring detected\n"); 04545 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04546 p->subs[index].f.subclass = AST_CONTROL_RING; 04547 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) { 04548 if (option_debug) 04549 ast_log(LOG_DEBUG, "Line answered\n"); 04550 if (p->confirmanswer) { 04551 p->subs[index].f.frametype = AST_FRAME_NULL; 04552 p->subs[index].f.subclass = 0; 04553 } else { 04554 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04555 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 04556 ast_setstate(ast, AST_STATE_UP); 04557 } 04558 } else if (ast->_state != AST_STATE_RING) 04559 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel); 04560 break; 04561 default: 04562 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 04563 } 04564 break; 04565 #ifdef DAHDI_EVENT_RINGBEGIN 04566 case DAHDI_EVENT_RINGBEGIN: 04567 switch (p->sig) { 04568 case SIG_FXSLS: 04569 case SIG_FXSGS: 04570 case SIG_FXSKS: 04571 if (ast->_state == AST_STATE_RING) { 04572 p->ringt = p->ringt_base; 04573 } 04574 break; 04575 } 04576 break; 04577 #endif 04578 case DAHDI_EVENT_RINGEROFF: 04579 if (p->inalarm) break; 04580 if ((p->radio || (p->oprmode < 0))) break; 04581 ast->rings++; 04582 if ((ast->rings > p->cidrings) && (p->cidspill)) { 04583 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n"); 04584 free(p->cidspill); 04585 p->cidspill = NULL; 04586 p->callwaitcas = 0; 04587 } 04588 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04589 p->subs[index].f.subclass = AST_CONTROL_RINGING; 04590 break; 04591 case DAHDI_EVENT_RINGERON: 04592 break; 04593 case DAHDI_EVENT_NOALARM: 04594 p->inalarm = 0; 04595 #ifdef HAVE_PRI 04596 /* Extremely unlikely but just in case */ 04597 if (p->bearer) 04598 p->bearer->inalarm = 0; 04599 #endif 04600 if (!p->unknown_alarm) { 04601 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 04602 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 04603 "Channel: %d\r\n", p->channel); 04604 } else { 04605 p->unknown_alarm = 0; 04606 } 04607 break; 04608 case DAHDI_EVENT_WINKFLASH: 04609 if (p->inalarm) break; 04610 if (p->radio) break; 04611 if (p->oprmode < 0) break; 04612 if (p->oprmode > 1) 04613 { 04614 struct dahdi_params par; 04615 04616 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1) 04617 { 04618 if (!par.rxisoffhook) 04619 { 04620 /* Make sure it stops ringing */ 04621 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 04622 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING); 04623 save_conference(p); 04624 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04625 } 04626 } 04627 break; 04628 } 04629 /* Remember last time we got a flash-hook */ 04630 gettimeofday(&p->flashtime, NULL); 04631 switch (mysig) { 04632 case SIG_FXOLS: 04633 case SIG_FXOGS: 04634 case SIG_FXOKS: 04635 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n", 04636 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 04637 p->callwaitcas = 0; 04638 04639 if (index != SUB_REAL) { 04640 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel); 04641 goto winkflashdone; 04642 } 04643 04644 if (p->subs[SUB_CALLWAIT].owner) { 04645 /* Swap to call-wait */ 04646 swap_subs(p, SUB_REAL, SUB_CALLWAIT); 04647 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 04648 p->owner = p->subs[SUB_REAL].owner; 04649 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name); 04650 if (p->owner->_state == AST_STATE_RINGING) { 04651 ast_setstate(p->owner, AST_STATE_UP); 04652 p->subs[SUB_REAL].needanswer = 1; 04653 } 04654 p->callwaitingrepeat = 0; 04655 p->cidcwexpire = 0; 04656 /* Start music on hold if appropriate */ 04657 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 04658 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 04659 S_OR(p->mohsuggest, NULL), 04660 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 04661 } 04662 p->subs[SUB_CALLWAIT].needhold = 1; 04663 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 04664 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD, 04665 S_OR(p->mohsuggest, NULL), 04666 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 04667 } 04668 p->subs[SUB_REAL].needunhold = 1; 04669 } else if (!p->subs[SUB_THREEWAY].owner) { 04670 if (!p->threewaycalling) { 04671 /* Just send a flash if no 3-way calling */ 04672 p->subs[SUB_REAL].needflash = 1; 04673 goto winkflashdone; 04674 } else if (!check_for_conference(p)) { 04675 char cid_num[256]; 04676 char cid_name[256]; 04677 04678 cid_num[0] = 0; 04679 cid_name[0] = 0; 04680 if (p->dahditrcallerid && p->owner) { 04681 if (p->owner->cid.cid_num) 04682 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num)); 04683 if (p->owner->cid.cid_name) 04684 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name)); 04685 } 04686 /* XXX This section needs much more error checking!!! XXX */ 04687 /* Start a 3-way call if feasible */ 04688 if (!((ast->pbx) || 04689 (ast->_state == AST_STATE_UP) || 04690 (ast->_state == AST_STATE_RING))) { 04691 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n"); 04692 goto winkflashdone; 04693 } 04694 if (alloc_sub(p, SUB_THREEWAY)) { 04695 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n"); 04696 goto winkflashdone; 04697 } 04698 /* Make new channel */ 04699 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0); 04700 if (p->dahditrcallerid) { 04701 if (!p->origcid_num) 04702 p->origcid_num = ast_strdup(p->cid_num); 04703 if (!p->origcid_name) 04704 p->origcid_name = ast_strdup(p->cid_name); 04705 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num)); 04706 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name)); 04707 } 04708 /* Swap things around between the three-way and real call */ 04709 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04710 /* Disable echo canceller for better dialing */ 04711 dahdi_disable_ec(p); 04712 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL); 04713 if (res) 04714 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel); 04715 p->owner = chan; 04716 pthread_attr_init(&attr); 04717 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 04718 if (!chan) { 04719 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel); 04720 } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 04721 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel); 04722 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 04723 dahdi_enable_ec(p); 04724 ast_hangup(chan); 04725 } else { 04726 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 04727 int way3bridge = 0, cdr3way = 0; 04728 04729 if (!other) { 04730 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 04731 } else 04732 way3bridge = 1; 04733 04734 if (p->subs[SUB_THREEWAY].owner->cdr) 04735 cdr3way = 1; 04736 04737 if (option_verbose > 2) 04738 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel); 04739 /* Start music on hold if appropriate */ 04740 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 04741 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 04742 S_OR(p->mohsuggest, NULL), 04743 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 04744 } 04745 p->subs[SUB_THREEWAY].needhold = 1; 04746 } 04747 pthread_attr_destroy(&attr); 04748 } 04749 } else { 04750 /* Already have a 3 way call */ 04751 if (p->subs[SUB_THREEWAY].inthreeway) { 04752 /* Call is already up, drop the last person */ 04753 if (option_debug) 04754 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel); 04755 /* If the primary call isn't answered yet, use it */ 04756 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) { 04757 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/ 04758 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04759 p->owner = p->subs[SUB_REAL].owner; 04760 } 04761 /* Drop the last call and stop the conference */ 04762 if (option_verbose > 2) 04763 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name); 04764 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04765 p->subs[SUB_REAL].inthreeway = 0; 04766 p->subs[SUB_THREEWAY].inthreeway = 0; 04767 } else { 04768 /* Lets see what we're up to */ 04769 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 04770 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) { 04771 int otherindex = SUB_THREEWAY; 04772 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 04773 int way3bridge = 0, cdr3way = 0; 04774 04775 if (!other) { 04776 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 04777 } else 04778 way3bridge = 1; 04779 04780 if (p->subs[SUB_THREEWAY].owner->cdr) 04781 cdr3way = 1; 04782 04783 if (option_verbose > 2) 04784 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); 04785 /* Put them in the threeway, and flip */ 04786 p->subs[SUB_THREEWAY].inthreeway = 1; 04787 p->subs[SUB_REAL].inthreeway = 1; 04788 if (ast->_state == AST_STATE_UP) { 04789 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04790 otherindex = SUB_REAL; 04791 } 04792 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner)) 04793 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD); 04794 p->subs[otherindex].needunhold = 1; 04795 p->owner = p->subs[SUB_REAL].owner; 04796 if (ast->_state == AST_STATE_RINGING) { 04797 ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n"); 04798 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04799 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 04800 } 04801 } else { 04802 if (option_verbose > 2) 04803 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name); 04804 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04805 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04806 p->owner = p->subs[SUB_REAL].owner; 04807 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner)) 04808 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 04809 p->subs[SUB_REAL].needunhold = 1; 04810 dahdi_enable_ec(p); 04811 } 04812 04813 } 04814 } 04815 winkflashdone: 04816 update_conf(p); 04817 break; 04818 case SIG_EM: 04819 case SIG_EM_E1: 04820 case SIG_EMWINK: 04821 case SIG_FEATD: 04822 case SIG_SF: 04823 case SIG_SFWINK: 04824 case SIG_SF_FEATD: 04825 case SIG_FXSLS: 04826 case SIG_FXSGS: 04827 if (p->dialing) 04828 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel); 04829 else 04830 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel); 04831 break; 04832 case SIG_FEATDMF_TA: 04833 switch (p->whichwink) { 04834 case 0: 04835 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 04836 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 04837 break; 04838 case 1: 04839 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr)); 04840 break; 04841 case 2: 04842 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n"); 04843 return NULL; 04844 } 04845 p->whichwink++; 04846 /* Fall through */ 04847 case SIG_FEATDMF: 04848 case SIG_E911: 04849 case SIG_FGC_CAMAMF: 04850 case SIG_FGC_CAMA: 04851 case SIG_FEATB: 04852 case SIG_SF_FEATDMF: 04853 case SIG_SF_FEATB: 04854 /* FGD MF *Must* wait for wink */ 04855 if (!ast_strlen_zero(p->dop.dialstr)) { 04856 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 04857 if (res < 0) { 04858 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 04859 p->dop.dialstr[0] = '\0'; 04860 return NULL; 04861 } else 04862 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); 04863 } 04864 p->dop.dialstr[0] = '\0'; 04865 break; 04866 default: 04867 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig); 04868 } 04869 break; 04870 case DAHDI_EVENT_HOOKCOMPLETE: 04871 if (p->inalarm) break; 04872 if ((p->radio || (p->oprmode < 0))) break; 04873 switch (mysig) { 04874 case SIG_FXSLS: /* only interesting for FXS */ 04875 case SIG_FXSGS: 04876 case SIG_FXSKS: 04877 case SIG_EM: 04878 case SIG_EM_E1: 04879 case SIG_EMWINK: 04880 case SIG_FEATD: 04881 case SIG_SF: 04882 case SIG_SFWINK: 04883 case SIG_SF_FEATD: 04884 if (!ast_strlen_zero(p->dop.dialstr)) { 04885 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 04886 if (res < 0) { 04887 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 04888 p->dop.dialstr[0] = '\0'; 04889 return NULL; 04890 } else 04891 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); 04892 } 04893 p->dop.dialstr[0] = '\0'; 04894 p->dop.op = DAHDI_DIAL_OP_REPLACE; 04895 break; 04896 case SIG_FEATDMF: 04897 case SIG_FEATDMF_TA: 04898 case SIG_E911: 04899 case SIG_FGC_CAMA: 04900 case SIG_FGC_CAMAMF: 04901 case SIG_FEATB: 04902 case SIG_SF_FEATDMF: 04903 case SIG_SF_FEATB: 04904 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel); 04905 break; 04906 default: 04907 break; 04908 } 04909 break; 04910 case DAHDI_EVENT_POLARITY: 04911 /* 04912 * If we get a Polarity Switch event, check to see 04913 * if we should change the polarity state and 04914 * mark the channel as UP or if this is an indication 04915 * of remote end disconnect. 04916 */ 04917 if (p->polarity == POLARITY_IDLE) { 04918 p->polarity = POLARITY_REV; 04919 if (p->answeronpolarityswitch && 04920 ((ast->_state == AST_STATE_DIALING) || 04921 (ast->_state == AST_STATE_RINGING))) { 04922 ast_log(LOG_DEBUG, "Answering on polarity switch!\n"); 04923 ast_setstate(p->owner, AST_STATE_UP); 04924 if (p->hanguponpolarityswitch) { 04925 gettimeofday(&p->polaritydelaytv, NULL); 04926 } 04927 } else 04928 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state); 04929 } 04930 /* Removed else statement from here as it was preventing hangups from ever happening*/ 04931 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */ 04932 if (p->hanguponpolarityswitch && 04933 (p->polarityonanswerdelay > 0) && 04934 (p->polarity == POLARITY_REV) && 04935 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) { 04936 /* Added log_debug information below to provide a better indication of what is going on */ 04937 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) ); 04938 04939 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) { 04940 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel); 04941 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 04942 p->polarity = POLARITY_IDLE; 04943 } else { 04944 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); 04945 } 04946 } else { 04947 p->polarity = POLARITY_IDLE; 04948 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state); 04949 } 04950 /* Added more log_debug information below to provide a better indication of what is going on */ 04951 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) ); 04952 break; 04953 default: 04954 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel); 04955 } 04956 return &p->subs[index].f; 04957 }
static int dahdi_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 2820 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_confmute(), dahdi_disable_ec(), dahdi_get_index(), dahdi_set_hook(), dahdi_setlinear(), dahdi_pvt::destroy, destroy_channel(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::didtdd, dahdi_pvt::digital, dahdi_pvt::distinctivering, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, dahdi_pvt::dtmfrelax, errno, dahdi_pvt::exten, dahdi_pvt::faxhandled, free, dahdi_pvt::guardtime, ast_channel::hangupcause, dahdi_pvt::hidecallerid, iflist, iflock, dahdi_pvt::ignoredtmf, dahdi_subchannel::inthreeway, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, 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::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_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().
02821 { 02822 int res; 02823 int index,x, law; 02824 /*static int restore_gains(struct dahdi_pvt *p);*/ 02825 struct dahdi_pvt *p = ast->tech_pvt; 02826 struct dahdi_pvt *tmp = NULL; 02827 struct dahdi_pvt *prev = NULL; 02828 struct dahdi_params par; 02829 02830 if (option_debug) 02831 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name); 02832 if (!ast->tech_pvt) { 02833 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 02834 return 0; 02835 } 02836 02837 ast_mutex_lock(&p->lock); 02838 02839 index = dahdi_get_index(ast, p, 1); 02840 02841 if (p->sig == SIG_PRI) { 02842 x = 1; 02843 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 02844 } 02845 02846 x = 0; 02847 dahdi_confmute(p, 0); 02848 restore_gains(p); 02849 if (p->origcid_num) { 02850 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num)); 02851 free(p->origcid_num); 02852 p->origcid_num = NULL; 02853 } 02854 if (p->origcid_name) { 02855 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name)); 02856 free(p->origcid_name); 02857 p->origcid_name = NULL; 02858 } 02859 if (p->dsp) 02860 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 02861 p->exten[0] = '\0'; 02862 02863 if (option_debug) 02864 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n", 02865 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 02866 p->ignoredtmf = 0; 02867 02868 if (index > -1) { 02869 /* Real channel, do some fixup */ 02870 p->subs[index].owner = NULL; 02871 p->subs[index].needanswer = 0; 02872 p->subs[index].needflash = 0; 02873 p->subs[index].needringing = 0; 02874 p->subs[index].needbusy = 0; 02875 p->subs[index].needcongestion = 0; 02876 p->subs[index].linear = 0; 02877 p->subs[index].needcallerid = 0; 02878 p->polarity = POLARITY_IDLE; 02879 dahdi_setlinear(p->subs[index].dfd, 0); 02880 if (index == SUB_REAL) { 02881 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) { 02882 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n"); 02883 if (p->subs[SUB_CALLWAIT].inthreeway) { 02884 /* We had flipped over to answer a callwait and now it's gone */ 02885 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n"); 02886 /* Move to the call-wait, but un-own us until they flip back. */ 02887 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 02888 unalloc_sub(p, SUB_CALLWAIT); 02889 p->owner = NULL; 02890 } else { 02891 /* The three way hung up, but we still have a call wait */ 02892 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n"); 02893 swap_subs(p, SUB_THREEWAY, SUB_REAL); 02894 unalloc_sub(p, SUB_THREEWAY); 02895 if (p->subs[SUB_REAL].inthreeway) { 02896 /* This was part of a three way call. Immediately make way for 02897 another call */ 02898 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n"); 02899 p->owner = p->subs[SUB_REAL].owner; 02900 } else { 02901 /* This call hasn't been completed yet... Set owner to NULL */ 02902 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n"); 02903 p->owner = NULL; 02904 } 02905 p->subs[SUB_REAL].inthreeway = 0; 02906 } 02907 } else if (p->subs[SUB_CALLWAIT].dfd > -1) { 02908 /* Move to the call-wait and switch back to them. */ 02909 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 02910 unalloc_sub(p, SUB_CALLWAIT); 02911 p->owner = p->subs[SUB_REAL].owner; 02912 if (p->owner->_state != AST_STATE_UP) 02913 p->subs[SUB_REAL].needanswer = 1; 02914 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 02915 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 02916 } else if (p->subs[SUB_THREEWAY].dfd > -1) { 02917 swap_subs(p, SUB_THREEWAY, SUB_REAL); 02918 unalloc_sub(p, SUB_THREEWAY); 02919 if (p->subs[SUB_REAL].inthreeway) { 02920 /* This was part of a three way call. Immediately make way for 02921 another call */ 02922 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n"); 02923 p->owner = p->subs[SUB_REAL].owner; 02924 } else { 02925 /* This call hasn't been completed yet... Set owner to NULL */ 02926 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n"); 02927 p->owner = NULL; 02928 } 02929 p->subs[SUB_REAL].inthreeway = 0; 02930 } 02931 } else if (index == SUB_CALLWAIT) { 02932 /* Ditch the holding callwait call, and immediately make it availabe */ 02933 if (p->subs[SUB_CALLWAIT].inthreeway) { 02934 /* This is actually part of a three way, placed on hold. Place the third part 02935 on music on hold now */ 02936 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 02937 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 02938 S_OR(p->mohsuggest, NULL), 02939 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 02940 } 02941 p->subs[SUB_THREEWAY].inthreeway = 0; 02942 /* Make it the call wait now */ 02943 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 02944 unalloc_sub(p, SUB_THREEWAY); 02945 } else 02946 unalloc_sub(p, SUB_CALLWAIT); 02947 } else if (index == SUB_THREEWAY) { 02948 if (p->subs[SUB_CALLWAIT].inthreeway) { 02949 /* The other party of the three way call is currently in a call-wait state. 02950 Start music on hold for them, and take the main guy out of the third call */ 02951 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 02952 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 02953 S_OR(p->mohsuggest, NULL), 02954 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 02955 } 02956 p->subs[SUB_CALLWAIT].inthreeway = 0; 02957 } 02958 p->subs[SUB_REAL].inthreeway = 0; 02959 /* If this was part of a three way call index, let us make 02960 another three way call */ 02961 unalloc_sub(p, SUB_THREEWAY); 02962 } else { 02963 /* This wasn't any sort of call, but how are we an index? */ 02964 ast_log(LOG_WARNING, "Index found but not any type of call?\n"); 02965 } 02966 } 02967 02968 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 02969 p->owner = NULL; 02970 p->ringt = 0; 02971 p->distinctivering = 0; 02972 p->confirmanswer = 0; 02973 p->cidrings = 1; 02974 p->outgoing = 0; 02975 p->digital = 0; 02976 p->faxhandled = 0; 02977 p->pulsedial = 0; 02978 p->onhooktime = time(NULL); 02979 #ifdef HAVE_PRI 02980 p->proceeding = 0; 02981 p->progress = 0; 02982 p->alerting = 0; 02983 p->setup_ack = 0; 02984 #endif 02985 if (p->dsp) { 02986 ast_dsp_free(p->dsp); 02987 p->dsp = NULL; 02988 } 02989 02990 law = DAHDI_LAW_DEFAULT; 02991 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 02992 if (res < 0) 02993 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 02994 /* Perform low level hangup if no owner left */ 02995 #ifdef HAVE_PRI 02996 if (p->pri) { 02997 #ifdef SUPPORT_USERUSER 02998 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO"); 02999 #endif 03000 03001 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */ 03002 if (p->call && (!p->bearer || (p->bearer->call == p->call))) { 03003 if (!pri_grab(p, p->pri)) { 03004 if (p->alreadyhungup) { 03005 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n"); 03006 03007 #ifdef SUPPORT_USERUSER 03008 pri_call_set_useruser(p->call, useruser); 03009 #endif 03010 03011 pri_hangup(p->pri->pri, p->call, -1); 03012 p->call = NULL; 03013 if (p->bearer) 03014 p->bearer->call = NULL; 03015 } else { 03016 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE"); 03017 int icause = ast->hangupcause ? ast->hangupcause : -1; 03018 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n"); 03019 03020 #ifdef SUPPORT_USERUSER 03021 pri_call_set_useruser(p->call, useruser); 03022 #endif 03023 03024 p->alreadyhungup = 1; 03025 if (p->bearer) 03026 p->bearer->alreadyhungup = 1; 03027 if (cause) { 03028 if (atoi(cause)) 03029 icause = atoi(cause); 03030 } 03031 pri_hangup(p->pri->pri, p->call, icause); 03032 } 03033 if (res < 0) 03034 ast_log(LOG_WARNING, "pri_disconnect failed\n"); 03035 pri_rel(p->pri); 03036 } else { 03037 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 03038 res = -1; 03039 } 03040 } else { 03041 if (p->bearer) 03042 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call); 03043 p->call = NULL; 03044 res = 0; 03045 } 03046 } 03047 #endif 03048 if (p->sig && (p->sig != SIG_PRI)) 03049 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 03050 if (res < 0) { 03051 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name); 03052 } 03053 switch (p->sig) { 03054 case SIG_FXOGS: 03055 case SIG_FXOLS: 03056 case SIG_FXOKS: 03057 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 03058 if (!res) { 03059 #if 0 03060 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook); 03061 #endif 03062 /* If they're off hook, try playing congestion */ 03063 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0)))) 03064 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 03065 else 03066 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03067 } 03068 break; 03069 case SIG_FXSGS: 03070 case SIG_FXSLS: 03071 case SIG_FXSKS: 03072 /* Make sure we're not made available for at least two seconds assuming 03073 we were actually used for an inbound or outbound call. */ 03074 if (ast->_state != AST_STATE_RESERVED) { 03075 time(&p->guardtime); 03076 p->guardtime += 2; 03077 } 03078 break; 03079 default: 03080 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03081 } 03082 if (p->cidspill) 03083 free(p->cidspill); 03084 if (p->sig) 03085 dahdi_disable_ec(p); 03086 x = 0; 03087 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); 03088 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0); 03089 p->didtdd = 0; 03090 p->cidspill = NULL; 03091 p->callwaitcas = 0; 03092 p->callwaiting = p->permcallwaiting; 03093 p->hidecallerid = p->permhidecallerid; 03094 p->dialing = 0; 03095 p->rdnis[0] = '\0'; 03096 update_conf(p); 03097 reset_conf(p); 03098 /* Restore data mode */ 03099 if (p->sig == SIG_PRI) { 03100 x = 0; 03101 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 03102 } 03103 #ifdef HAVE_PRI 03104 if (p->bearer) { 03105 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel); 03106 /* Free up the bearer channel as well, and 03107 don't use its file descriptor anymore */ 03108 update_conf(p->bearer); 03109 reset_conf(p->bearer); 03110 p->bearer->owner = NULL; 03111 p->bearer->realcall = NULL; 03112 p->bearer = NULL; 03113 p->subs[SUB_REAL].dfd = -1; 03114 p->pri = NULL; 03115 } 03116 #endif 03117 if (num_restart_pending == 0) 03118 restart_monitor(); 03119 } 03120 03121 p->callwaitingrepeat = 0; 03122 p->cidcwexpire = 0; 03123 p->oprmode = 0; 03124 ast->tech_pvt = NULL; 03125 ast_mutex_unlock(&p->lock); 03126 ast_module_unref(ast_module_info->self); 03127 if (option_verbose > 2) 03128 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name); 03129 03130 ast_mutex_lock(&iflock); 03131 03132 if (p->restartpending) { 03133 num_restart_pending--; 03134 } 03135 03136 tmp = iflist; 03137 prev = NULL; 03138 if (p->destroy) { 03139 while (tmp) { 03140 if (tmp == p) { 03141 destroy_channel(prev, tmp, 0); 03142 break; 03143 } else { 03144 prev = tmp; 03145 tmp = tmp->next; 03146 } 03147 } 03148 } 03149 ast_mutex_unlock(&iflock); 03150 return 0; 03151 }
static int dahdi_indicate | ( | struct ast_channel * | chan, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 5473 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::digital, dahdi_pvt::dop, errno, ast_channel::hangupcause, ISTRUNK, dahdi_pvt::lock, LOG_DEBUG, dahdi_pvt::mohinterpret, ast_channel::name, option_debug, 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.
05474 { 05475 struct dahdi_pvt *p = chan->tech_pvt; 05476 int res=-1; 05477 int index; 05478 int func = DAHDI_FLASH; 05479 ast_mutex_lock(&p->lock); 05480 index = dahdi_get_index(chan, p, 0); 05481 if (option_debug) 05482 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name); 05483 if (index == SUB_REAL) { 05484 switch (condition) { 05485 case AST_CONTROL_BUSY: 05486 #ifdef HAVE_PRI 05487 if (p->priindication_oob && p->sig == SIG_PRI) { 05488 chan->hangupcause = AST_CAUSE_USER_BUSY; 05489 chan->_softhangup |= AST_SOFTHANGUP_DEV; 05490 res = 0; 05491 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 05492 if (p->pri->pri) { 05493 if (!pri_grab(p, p->pri)) { 05494 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 05495 pri_rel(p->pri); 05496 } 05497 else 05498 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05499 } 05500 p->progress = 1; 05501 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY); 05502 } else 05503 #endif 05504 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY); 05505 break; 05506 case AST_CONTROL_RINGING: 05507 #ifdef HAVE_PRI 05508 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) { 05509 if (p->pri->pri) { 05510 if (!pri_grab(p, p->pri)) { 05511 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 05512 pri_rel(p->pri); 05513 } 05514 else 05515 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05516 } 05517 p->alerting = 1; 05518 } 05519 #endif 05520 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE); 05521 if (chan->_state != AST_STATE_UP) { 05522 if ((chan->_state != AST_STATE_RING) || 05523 ((p->sig != SIG_FXSKS) && 05524 (p->sig != SIG_FXSLS) && 05525 (p->sig != SIG_FXSGS))) 05526 ast_setstate(chan, AST_STATE_RINGING); 05527 } 05528 break; 05529 case AST_CONTROL_PROCEEDING: 05530 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name); 05531 #ifdef HAVE_PRI 05532 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { 05533 if (p->pri->pri) { 05534 if (!pri_grab(p, p->pri)) { 05535 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 05536 pri_rel(p->pri); 05537 } 05538 else 05539 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05540 } 05541 p->proceeding = 1; 05542 } 05543 #endif 05544 /* don't continue in ast_indicate */ 05545 res = 0; 05546 break; 05547 case AST_CONTROL_PROGRESS: 05548 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name); 05549 #ifdef HAVE_PRI 05550 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */ 05551 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 05552 if (p->pri->pri) { 05553 if (!pri_grab(p, p->pri)) { 05554 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 05555 pri_rel(p->pri); 05556 } 05557 else 05558 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05559 } 05560 p->progress = 1; 05561 } 05562 #endif 05563 /* don't continue in ast_indicate */ 05564 res = 0; 05565 break; 05566 case AST_CONTROL_CONGESTION: 05567 chan->hangupcause = AST_CAUSE_CONGESTION; 05568 #ifdef HAVE_PRI 05569 if (p->priindication_oob && p->sig == SIG_PRI) { 05570 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 05571 chan->_softhangup |= AST_SOFTHANGUP_DEV; 05572 res = 0; 05573 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 05574 if (p->pri) { 05575 if (!pri_grab(p, p->pri)) { 05576 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 05577 pri_rel(p->pri); 05578 } else 05579 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05580 } 05581 p->progress = 1; 05582 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 05583 } else 05584 #endif 05585 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 05586 break; 05587 case AST_CONTROL_HOLD: 05588 #ifdef HAVE_PRI 05589 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 05590 if (!pri_grab(p, p->pri)) { 05591 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD); 05592 pri_rel(p->pri); 05593 } else 05594 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05595 } else 05596 #endif 05597 ast_moh_start(chan, data, p->mohinterpret); 05598 break; 05599 case AST_CONTROL_UNHOLD: 05600 #ifdef HAVE_PRI 05601 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 05602 if (!pri_grab(p, p->pri)) { 05603 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL); 05604 pri_rel(p->pri); 05605 } else 05606 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05607 } else 05608 #endif 05609 ast_moh_stop(chan); 05610 break; 05611 case AST_CONTROL_RADIO_KEY: 05612 if (p->radio) 05613 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 05614 res = 0; 05615 break; 05616 case AST_CONTROL_RADIO_UNKEY: 05617 if (p->radio) 05618 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF); 05619 res = 0; 05620 break; 05621 case AST_CONTROL_FLASH: 05622 /* flash hookswitch */ 05623 if (ISTRUNK(p) && (p->sig != SIG_PRI)) { 05624 /* Clear out the dial buffer */ 05625 p->dop.dialstr[0] = '\0'; 05626 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 05627 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 05628 chan->name, strerror(errno)); 05629 } else 05630 res = 0; 05631 } else 05632 res = 0; 05633 break; 05634 case AST_CONTROL_SRCUPDATE: 05635 res = 0; 05636 break; 05637 case -1: 05638 res = tone_zone_play_tone(p->subs[index].dfd, -1); 05639 break; 05640 } 05641 } else 05642 res = 0; 05643 ast_mutex_unlock(&p->lock); 05644 return res; 05645 }
Definition at line 3499 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and master.
Referenced by dahdi_bridge().
03499 { 03500 int x; 03501 if (!slave || !master) { 03502 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n"); 03503 return; 03504 } 03505 for (x = 0; x < MAX_SLAVES; x++) { 03506 if (!master->slaves[x]) { 03507 master->slaves[x] = slave; 03508 break; 03509 } 03510 } 03511 if (x >= MAX_SLAVES) { 03512 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel); 03513 master->slaves[MAX_SLAVES - 1] = slave; 03514 } 03515 if (slave->master) 03516 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel); 03517 slave->master = master; 03518 03519 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x); 03520 }
static struct ast_channel * dahdi_new | ( | struct dahdi_pvt * | , | |
int | , | |||
int | , | |||
int | , | |||
int | , | |||
int | ||||
) | [static] |
Definition at line 5647 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_SLINEAR, AST_FORMAT_ULAW, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_random(), ast_safe_string_alloc(), AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_transfercapability2str(), dahdi_pvt::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, 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_request(), handle_init_event(), and register_translator().
05648 { 05649 struct ast_channel *tmp; 05650 int deflaw; 05651 int res; 05652 int x,y; 05653 int features; 05654 char *b2 = NULL; 05655 struct dahdi_params ps; 05656 char chanprefix[*dahdi_chan_name_len + 4]; 05657 05658 if (i->subs[index].owner) { 05659 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]); 05660 return NULL; 05661 } 05662 y = 1; 05663 do { 05664 if (b2) 05665 free(b2); 05666 #ifdef HAVE_PRI 05667 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS))) 05668 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y); 05669 else 05670 #endif 05671 if (i->channel == CHAN_PSEUDO) 05672 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random()); 05673 else 05674 b2 = ast_safe_string_alloc("%d-%d", i->channel, y); 05675 for (x = 0; x < 3; x++) { 05676 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6))) 05677 break; 05678 } 05679 y++; 05680 } while (x < 3); 05681 strcpy(chanprefix, dahdi_chan_name); 05682 strcat(chanprefix, "/%s"); 05683 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2); 05684 if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */ 05685 free(b2); 05686 if (!tmp) 05687 return NULL; 05688 tmp->tech = chan_tech; 05689 ps.channo = i->channel; 05690 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps); 05691 if (res) { 05692 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno)); 05693 ps.curlaw = DAHDI_LAW_MULAW; 05694 } 05695 if (ps.curlaw == DAHDI_LAW_ALAW) 05696 deflaw = AST_FORMAT_ALAW; 05697 else 05698 deflaw = AST_FORMAT_ULAW; 05699 if (law) { 05700 if (law == DAHDI_LAW_ALAW) 05701 deflaw = AST_FORMAT_ALAW; 05702 else 05703 deflaw = AST_FORMAT_ULAW; 05704 } 05705 tmp->fds[0] = i->subs[index].dfd; 05706 tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw; 05707 /* Start out assuming ulaw since it's smaller :) */ 05708 tmp->rawreadformat = deflaw; 05709 tmp->readformat = deflaw; 05710 tmp->rawwriteformat = deflaw; 05711 tmp->writeformat = deflaw; 05712 i->subs[index].linear = 0; 05713 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear); 05714 features = 0; 05715 if (index == SUB_REAL) { 05716 if (i->busydetect && CANBUSYDETECT(i)) 05717 features |= DSP_FEATURE_BUSY_DETECT; 05718 if ((i->callprogress & 1) && CANPROGRESSDETECT(i)) 05719 features |= DSP_FEATURE_CALL_PROGRESS; 05720 if ((!i->outgoing && (i->callprogress & 4)) || 05721 (i->outgoing && (i->callprogress & 2))) { 05722 features |= DSP_FEATURE_FAX_DETECT; 05723 } 05724 #ifdef DAHDI_TONEDETECT 05725 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 05726 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) { 05727 #endif 05728 i->hardwaredtmf = 0; 05729 features |= DSP_FEATURE_DTMF_DETECT; 05730 #ifdef DAHDI_TONEDETECT 05731 } else if (NEED_MFDETECT(i)) { 05732 i->hardwaredtmf = 1; 05733 features |= DSP_FEATURE_DTMF_DETECT; 05734 } 05735 #endif 05736 } 05737 if (features) { 05738 if (i->dsp) { 05739 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name); 05740 } else { 05741 if (i->channel != CHAN_PSEUDO) 05742 i->dsp = ast_dsp_new(); 05743 else 05744 i->dsp = NULL; 05745 if (i->dsp) { 05746 i->dsp_features = features; 05747 #ifdef HAVE_PRI 05748 /* We cannot do progress detection until receives PROGRESS message */ 05749 if (i->outgoing && (i->sig == SIG_PRI)) { 05750 /* Remember requested DSP features, don't treat 05751 talking as ANSWER */ 05752 i->dsp_features = features & ~DSP_PROGRESS_TALK; 05753 features = 0; 05754 } 05755 #endif 05756 ast_dsp_set_features(i->dsp, features); 05757 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax); 05758 if (!ast_strlen_zero(progzone)) 05759 ast_dsp_set_call_progress_zone(i->dsp, progzone); 05760 if (i->busydetect && CANBUSYDETECT(i)) { 05761 if(i->silencethreshold > 0) 05762 ast_dsp_set_threshold(i->dsp, i->silencethreshold); 05763 ast_dsp_set_busy_count(i->dsp, i->busycount); 05764 if(i->busytonelength > 0) 05765 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness); 05766 if((i->busytonelength == i->busyquietlength) && i->busycompare) 05767 ast_dsp_set_busy_compare(i->dsp, i->busycompare); 05768 } 05769 } 05770 } 05771 } 05772 05773 if (state == AST_STATE_RING) 05774 tmp->rings = 1; 05775 tmp->tech_pvt = i; 05776 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) { 05777 /* Only FXO signalled stuff can be picked up */ 05778 tmp->callgroup = i->callgroup; 05779 tmp->pickupgroup = i->pickupgroup; 05780 } 05781 if (!ast_strlen_zero(i->language)) 05782 ast_string_field_set(tmp, language, i->language); 05783 if (!i->owner) 05784 i->owner = tmp; 05785 if (!ast_strlen_zero(i->accountcode)) 05786 ast_string_field_set(tmp, accountcode, i->accountcode); 05787 if (i->amaflags) 05788 tmp->amaflags = i->amaflags; 05789 i->subs[index].owner = tmp; 05790 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 05791 ast_string_field_set(tmp, call_forward, i->call_forward); 05792 /* If we've been told "no ADSI" then enforce it */ 05793 if (!i->adsi) 05794 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 05795 if (!ast_strlen_zero(i->exten)) 05796 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 05797 if (!ast_strlen_zero(i->rdnis)) 05798 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 05799 if (!ast_strlen_zero(i->dnid)) 05800 tmp->cid.cid_dnid = ast_strdup(i->dnid); 05801 05802 /* Don't use ast_set_callerid() here because it will 05803 * generate a needless NewCallerID event */ 05804 #ifdef PRI_ANI 05805 if (!ast_strlen_zero(i->cid_ani)) 05806 tmp->cid.cid_ani = ast_strdup(i->cid_ani); 05807 else 05808 tmp->cid.cid_ani = ast_strdup(i->cid_num); 05809 #else 05810 tmp->cid.cid_ani = ast_strdup(i->cid_num); 05811 #endif 05812 tmp->cid.cid_pres = i->callingpres; 05813 tmp->cid.cid_ton = i->cid_ton; 05814 #ifdef HAVE_PRI 05815 tmp->transfercapability = transfercapability; 05816 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability)); 05817 if (transfercapability & PRI_TRANS_CAP_DIGITAL) 05818 i->digital = 1; 05819 /* Assume calls are not idle calls unless we're told differently */ 05820 i->isidlecall = 0; 05821 i->alreadyhungup = 0; 05822 #endif 05823 /* clear the fake event in case we posted one before we had ast_channel */ 05824 i->fake_event = 0; 05825 /* Assure there is no confmute on this channel */ 05826 dahdi_confmute(i, 0); 05827 /* Configure the new channel jb */ 05828 ast_jb_configure(tmp, &global_jbconf); 05829 if (startpbx) { 05830 if (ast_pbx_start(tmp)) { 05831 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 05832 ast_hangup(tmp); 05833 i->owner = NULL; 05834 return NULL; 05835 } 05836 } 05837 05838 ast_module_ref(ast_module_info->self); 05839 05840 return tmp; 05841 }
static int dahdi_open | ( | char * | fn | ) | [static] |
Definition at line 1221 of file chan_dahdi.c.
References ast_log(), DAHDI_FILE_CHANNEL, errno, LOG_WARNING, and READ_SIZE.
Referenced by alloc_sub(), chandup(), and mkintf().
01222 { 01223 int fd; 01224 int isnum; 01225 int chan = 0; 01226 int bs; 01227 int x; 01228 isnum = 1; 01229 for (x = 0; x < strlen(fn); x++) { 01230 if (!isdigit(fn[x])) { 01231 isnum = 0; 01232 break; 01233 } 01234 } 01235 if (isnum) { 01236 chan = atoi(fn); 01237 if (chan < 1) { 01238 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn); 01239 return -1; 01240 } 01241 fn = DAHDI_FILE_CHANNEL; 01242 } 01243 fd = open(fn, O_RDWR | O_NONBLOCK); 01244 if (fd < 0) { 01245 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno)); 01246 return -1; 01247 } 01248 if (chan) { 01249 if (ioctl(fd, DAHDI_SPECIFY, &chan)) { 01250 x = errno; 01251 close(fd); 01252 errno = x; 01253 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno)); 01254 return -1; 01255 } 01256 } 01257 bs = READ_SIZE; 01258 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) { 01259 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno)); 01260 x = errno; 01261 close(fd); 01262 errno = x; 01263 return -1; 01264 } 01265 return fd; 01266 }
static void dahdi_pri_error | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 8738 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().
08739 { 08740 int x, y; 08741 int dchan = -1, span = -1; 08742 int dchancount = 0; 08743 08744 if (pri) { 08745 for (x = 0; x < NUM_SPANS; x++) { 08746 for (y = 0; y < NUM_DCHANS; y++) { 08747 if (pris[x].dchans[y]) 08748 dchancount++; 08749 08750 if (pris[x].dchans[y] == pri) 08751 dchan = y; 08752 } 08753 if (dchan >= 0) { 08754 span = x; 08755 break; 08756 } 08757 dchancount = 0; 08758 } 08759 if ((dchan >= 0) && (span >= 0)) { 08760 if (dchancount > 1) 08761 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s); 08762 else 08763 ast_log(LOG_ERROR, "%s", s); 08764 } else 08765 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n"); 08766 } else 08767 ast_log(LOG_ERROR, "%s", s); 08768 08769 ast_mutex_lock(&pridebugfdlock); 08770 08771 if (pridebugfd >= 0) { 08772 if (write(pridebugfd, s, strlen(s)) < 0) { 08773 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 08774 } 08775 } 08776 08777 ast_mutex_unlock(&pridebugfdlock); 08778 }
static void dahdi_pri_message | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 8696 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().
08697 { 08698 int x, y; 08699 int dchan = -1, span = -1; 08700 int dchancount = 0; 08701 08702 if (pri) { 08703 for (x = 0; x < NUM_SPANS; x++) { 08704 for (y = 0; y < NUM_DCHANS; y++) { 08705 if (pris[x].dchans[y]) 08706 dchancount++; 08707 08708 if (pris[x].dchans[y] == pri) 08709 dchan = y; 08710 } 08711 if (dchan >= 0) { 08712 span = x; 08713 break; 08714 } 08715 dchancount = 0; 08716 } 08717 if ((dchan >= 0) && (span >= 0)) { 08718 if (dchancount > 1) 08719 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s); 08720 else 08721 ast_verbose("%s", s); 08722 } else 08723 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n"); 08724 } else 08725 ast_verbose("%s", s); 08726 08727 ast_mutex_lock(&pridebugfdlock); 08728 08729 if (pridebugfd >= 0) { 08730 if (write(pridebugfd, s, strlen(s)) < 0) { 08731 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 08732 } 08733 } 08734 08735 ast_mutex_unlock(&pridebugfdlock); 08736 }
static void dahdi_queue_frame | ( | struct dahdi_pvt * | p, | |
struct ast_frame * | f, | |||
struct dahdi_pri * | pri | |||
) | [static] |
Definition at line 1163 of file chan_dahdi.c.
References ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_frame(), DEADLOCK_AVOIDANCE, and f.
Referenced by __action_dialoffhook().
01167 { 01168 /* We must unlock the PRI to avoid the possibility of a deadlock */ 01169 #ifdef HAVE_PRI 01170 if (pri) 01171 ast_mutex_unlock(&pri->lock); 01172 #endif 01173 for (;;) { 01174 if (p->owner) { 01175 if (ast_mutex_trylock(&p->owner->lock)) { 01176 DEADLOCK_AVOIDANCE(&p->lock); 01177 } else { 01178 ast_queue_frame(p->owner, f); 01179 ast_mutex_unlock(&p->owner->lock); 01180 break; 01181 } 01182 } else 01183 break; 01184 } 01185 #ifdef HAVE_PRI 01186 if (pri) 01187 ast_mutex_lock(&pri->lock); 01188 #endif 01189 }
static struct ast_frame * dahdi_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5077 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_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, 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::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.
05078 { 05079 struct dahdi_pvt *p = ast->tech_pvt; 05080 int res; 05081 int index; 05082 void *readbuf; 05083 struct ast_frame *f; 05084 05085 while (ast_mutex_trylock(&p->lock)) { 05086 DEADLOCK_AVOIDANCE(&ast->lock); 05087 } 05088 05089 index = dahdi_get_index(ast, p, 0); 05090 05091 /* Hang up if we don't really exist */ 05092 if (index < 0) { 05093 ast_log(LOG_WARNING, "We dont exist?\n"); 05094 ast_mutex_unlock(&p->lock); 05095 return NULL; 05096 } 05097 05098 if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL; 05099 05100 p->subs[index].f.frametype = AST_FRAME_NULL; 05101 p->subs[index].f.datalen = 0; 05102 p->subs[index].f.samples = 0; 05103 p->subs[index].f.mallocd = 0; 05104 p->subs[index].f.offset = 0; 05105 p->subs[index].f.subclass = 0; 05106 p->subs[index].f.delivery = ast_tv(0,0); 05107 p->subs[index].f.src = "dahdi_read"; 05108 p->subs[index].f.data = NULL; 05109 05110 /* make sure it sends initial key state as first frame */ 05111 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio)) 05112 { 05113 struct dahdi_params ps; 05114 05115 ps.channo = p->channel; 05116 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 05117 ast_mutex_unlock(&p->lock); 05118 return NULL; 05119 } 05120 p->firstradio = 1; 05121 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05122 if (ps.rxisoffhook) 05123 { 05124 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY; 05125 } 05126 else 05127 { 05128 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY; 05129 } 05130 ast_mutex_unlock(&p->lock); 05131 return &p->subs[index].f; 05132 } 05133 if (p->ringt == 1) { 05134 ast_mutex_unlock(&p->lock); 05135 return NULL; 05136 } 05137 else if (p->ringt > 0) 05138 p->ringt--; 05139 05140 if (p->subs[index].needringing) { 05141 /* Send ringing frame if requested */ 05142 p->subs[index].needringing = 0; 05143 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05144 p->subs[index].f.subclass = AST_CONTROL_RINGING; 05145 ast_setstate(ast, AST_STATE_RINGING); 05146 ast_mutex_unlock(&p->lock); 05147 return &p->subs[index].f; 05148 } 05149 05150 if (p->subs[index].needbusy) { 05151 /* Send busy frame if requested */ 05152 p->subs[index].needbusy = 0; 05153 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05154 p->subs[index].f.subclass = AST_CONTROL_BUSY; 05155 ast_mutex_unlock(&p->lock); 05156 return &p->subs[index].f; 05157 } 05158 05159 if (p->subs[index].needcongestion) { 05160 /* Send congestion frame if requested */ 05161 p->subs[index].needcongestion = 0; 05162 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05163 p->subs[index].f.subclass = AST_CONTROL_CONGESTION; 05164 ast_mutex_unlock(&p->lock); 05165 return &p->subs[index].f; 05166 } 05167 05168 if (p->subs[index].needcallerid) { 05169 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL), 05170 S_OR(p->lastcid_name, NULL), 05171 S_OR(p->lastcid_num, NULL) 05172 ); 05173 p->subs[index].needcallerid = 0; 05174 } 05175 05176 if (p->subs[index].needanswer) { 05177 /* Send answer frame if requested */ 05178 p->subs[index].needanswer = 0; 05179 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05180 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05181 ast_mutex_unlock(&p->lock); 05182 return &p->subs[index].f; 05183 } 05184 05185 if (p->subs[index].needflash) { 05186 /* Send answer frame if requested */ 05187 p->subs[index].needflash = 0; 05188 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05189 p->subs[index].f.subclass = AST_CONTROL_FLASH; 05190 ast_mutex_unlock(&p->lock); 05191 return &p->subs[index].f; 05192 } 05193 05194 if (p->subs[index].needhold) { 05195 /* Send answer frame if requested */ 05196 p->subs[index].needhold = 0; 05197 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05198 p->subs[index].f.subclass = AST_CONTROL_HOLD; 05199 ast_mutex_unlock(&p->lock); 05200 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name); 05201 return &p->subs[index].f; 05202 } 05203 05204 if (p->subs[index].needunhold) { 05205 /* Send answer frame if requested */ 05206 p->subs[index].needunhold = 0; 05207 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05208 p->subs[index].f.subclass = AST_CONTROL_UNHOLD; 05209 ast_mutex_unlock(&p->lock); 05210 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name); 05211 return &p->subs[index].f; 05212 } 05213 05214 if (ast->rawreadformat == AST_FORMAT_SLINEAR) { 05215 if (!p->subs[index].linear) { 05216 p->subs[index].linear = 1; 05217 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 05218 if (res) 05219 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index); 05220 } 05221 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) || 05222 (ast->rawreadformat == AST_FORMAT_ALAW)) { 05223 if (p->subs[index].linear) { 05224 p->subs[index].linear = 0; 05225 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 05226 if (res) 05227 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index); 05228 } 05229 } else { 05230 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat)); 05231 ast_mutex_unlock(&p->lock); 05232 return NULL; 05233 } 05234 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET; 05235 CHECK_BLOCKING(ast); 05236 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE); 05237 ast_clear_flag(ast, AST_FLAG_BLOCKING); 05238 /* Check for hangup */ 05239 if (res < 0) { 05240 f = NULL; 05241 if (res == -1) { 05242 if (errno == EAGAIN) { 05243 /* Return "NULL" frame if there is nobody there */ 05244 ast_mutex_unlock(&p->lock); 05245 return &p->subs[index].f; 05246 } else if (errno == ELAST) { 05247 f = __dahdi_exception(ast); 05248 } else 05249 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno)); 05250 } 05251 ast_mutex_unlock(&p->lock); 05252 return f; 05253 } 05254 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) { 05255 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE); 05256 f = __dahdi_exception(ast); 05257 ast_mutex_unlock(&p->lock); 05258 return f; 05259 } 05260 if (p->tdd) { /* if in TDD mode, see if we receive that */ 05261 int c; 05262 05263 c = tdd_feed(p->tdd,readbuf,READ_SIZE); 05264 if (c < 0) { 05265 ast_log(LOG_DEBUG,"tdd_feed failed\n"); 05266 ast_mutex_unlock(&p->lock); 05267 return NULL; 05268 } 05269 if (c) { /* if a char to return */ 05270 p->subs[index].f.subclass = 0; 05271 p->subs[index].f.frametype = AST_FRAME_TEXT; 05272 p->subs[index].f.mallocd = 0; 05273 p->subs[index].f.offset = AST_FRIENDLY_OFFSET; 05274 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET; 05275 p->subs[index].f.datalen = 1; 05276 *((char *) p->subs[index].f.data) = c; 05277 ast_mutex_unlock(&p->lock); 05278 return &p->subs[index].f; 05279 } 05280 } 05281 /* Ensure the CW timer decrements only on a single subchannel */ 05282 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) { 05283 p->callwaitingrepeat--; 05284 } 05285 if (p->cidcwexpire) 05286 p->cidcwexpire--; 05287 /* Repeat callwaiting */ 05288 if (p->callwaitingrepeat == 1) { 05289 p->callwaitrings++; 05290 dahdi_callwait(ast); 05291 } 05292 /* Expire CID/CW */ 05293 if (p->cidcwexpire == 1) { 05294 if (option_verbose > 2) 05295 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n"); 05296 restore_conference(p); 05297 } 05298 if (p->subs[index].linear) { 05299 p->subs[index].f.datalen = READ_SIZE * 2; 05300 } else 05301 p->subs[index].f.datalen = READ_SIZE; 05302 05303 /* Handle CallerID Transmission */ 05304 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) { 05305 send_callerid(p); 05306 } 05307 05308 p->subs[index].f.frametype = AST_FRAME_VOICE; 05309 p->subs[index].f.subclass = ast->rawreadformat; 05310 p->subs[index].f.samples = READ_SIZE; 05311 p->subs[index].f.mallocd = 0; 05312 p->subs[index].f.offset = AST_FRIENDLY_OFFSET; 05313 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]); 05314 #if 0 05315 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name); 05316 #endif 05317 if (p->dialing || /* Transmitting something */ 05318 (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */ 05319 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */ 05320 ) { 05321 /* Whoops, we're still dialing, or in a state where we shouldn't transmit.... 05322 don't send anything */ 05323 p->subs[index].f.frametype = AST_FRAME_NULL; 05324 p->subs[index].f.subclass = 0; 05325 p->subs[index].f.samples = 0; 05326 p->subs[index].f.mallocd = 0; 05327 p->subs[index].f.offset = 0; 05328 p->subs[index].f.data = NULL; 05329 p->subs[index].f.datalen= 0; 05330 } 05331 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) { 05332 /* Perform busy detection. etc on the dahdi line */ 05333 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f); 05334 if (f) { 05335 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) { 05336 if ((ast->_state == AST_STATE_UP) && !p->outgoing) { 05337 /* Treat this as a "hangup" instead of a "busy" on the assumption that 05338 a busy */ 05339 f = NULL; 05340 } 05341 } else if (f->frametype == AST_FRAME_DTMF) { 05342 #ifdef HAVE_PRI 05343 if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) { 05344 /* Don't accept in-band DTMF when in overlap dial mode */ 05345 f->frametype = AST_FRAME_NULL; 05346 f->subclass = 0; 05347 } 05348 #endif 05349 /* DSP clears us of being pulse */ 05350 p->pulsedial = 0; 05351 } 05352 } 05353 } else 05354 f = &p->subs[index].f; 05355 05356 if (f && (f->frametype == AST_FRAME_DTMF)) 05357 dahdi_handle_dtmfup(ast, index, &f); 05358 05359 /* If we have a fake_event, trigger exception to handle it */ 05360 if (p->fake_event) 05361 ast_set_flag(ast, AST_FLAG_EXCEPTION); 05362 05363 ast_mutex_unlock(&p->lock); 05364 return f; 05365 }
static struct ast_channel * dahdi_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 8277 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_pri::lock, lock, LOG_DEBUG, LOG_NOTICE, 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().
08278 { 08279 ast_group_t groupmatch = 0; 08280 int channelmatch = -1; 08281 int roundrobin = 0; 08282 int callwait = 0; 08283 int busy = 0; 08284 struct dahdi_pvt *p; 08285 struct ast_channel *tmp = NULL; 08286 char *dest=NULL; 08287 int x; 08288 char *s; 08289 char opt=0; 08290 int res=0, y=0; 08291 int backwards = 0; 08292 #ifdef HAVE_PRI 08293 int crv; 08294 int bearer = -1; 08295 int trunkgroup; 08296 struct dahdi_pri *pri=NULL; 08297 #endif 08298 struct dahdi_pvt *exit, *start, *end; 08299 ast_mutex_t *lock; 08300 int channelmatched = 0; 08301 int groupmatched = 0; 08302 08303 /* 08304 * data is ---v 08305 * Dial(DAHDI/pseudo[/extension]) 08306 * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension]) 08307 * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension]) 08308 * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension]) 08309 * 08310 * g - channel group allocation search forward 08311 * G - channel group allocation search backward 08312 * r - channel group allocation round robin search forward 08313 * R - channel group allocation round robin search backward 08314 * 08315 * c - Wait for DTMF digit to confirm answer 08316 * r<cadance#> - Set distintive ring cadance number 08317 * d - Force bearer capability for ISDN call to digital. 08318 */ 08319 08320 /* Assume we're locking the iflock */ 08321 lock = &iflock; 08322 start = iflist; 08323 end = ifend; 08324 if (data) { 08325 dest = ast_strdupa((char *)data); 08326 } else { 08327 ast_log(LOG_WARNING, "Channel requested with no data\n"); 08328 return NULL; 08329 } 08330 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') { 08331 /* Retrieve the group number */ 08332 char *stringp; 08333 08334 stringp = dest + 1; 08335 s = strsep(&stringp, "/"); 08336 if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) { 08337 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data); 08338 return NULL; 08339 } 08340 groupmatch = ((ast_group_t) 1 << x); 08341 if (toupper(dest[0]) == 'G') { 08342 if (dest[0] == 'G') { 08343 backwards = 1; 08344 p = ifend; 08345 } else 08346 p = iflist; 08347 } else { 08348 if (dest[0] == 'R') { 08349 backwards = 1; 08350 p = round_robin[x]?round_robin[x]->prev:ifend; 08351 if (!p) 08352 p = ifend; 08353 } else { 08354 p = round_robin[x]?round_robin[x]->next:iflist; 08355 if (!p) 08356 p = iflist; 08357 } 08358 roundrobin = 1; 08359 } 08360 } else { 08361 char *stringp; 08362 08363 stringp = dest; 08364 s = strsep(&stringp, "/"); 08365 p = iflist; 08366 if (!strcasecmp(s, "pseudo")) { 08367 /* Special case for pseudo */ 08368 x = CHAN_PSEUDO; 08369 channelmatch = x; 08370 } 08371 #ifdef HAVE_PRI 08372 else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) { 08373 if ((trunkgroup < 1) || (crv < 1)) { 08374 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data); 08375 return NULL; 08376 } 08377 res--; 08378 for (x = 0; x < NUM_SPANS; x++) { 08379 if (pris[x].trunkgroup == trunkgroup) { 08380 pri = pris + x; 08381 lock = &pri->lock; 08382 start = pri->crvs; 08383 end = pri->crvend; 08384 break; 08385 } 08386 } 08387 if (!pri) { 08388 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup); 08389 return NULL; 08390 } 08391 channelmatch = crv; 08392 p = pris[x].crvs; 08393 } 08394 #endif 08395 else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) { 08396 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data); 08397 return NULL; 08398 } else { 08399 channelmatch = x; 08400 } 08401 } 08402 /* Search for an unowned channel */ 08403 ast_mutex_lock(lock); 08404 exit = p; 08405 while (p && !tmp) { 08406 if (roundrobin) 08407 round_robin[x] = p; 08408 #if 0 08409 ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch); 08410 #endif 08411 08412 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) { 08413 if (option_debug) 08414 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel); 08415 if (p->inalarm) 08416 goto next; 08417 08418 callwait = (p->owner != NULL); 08419 #ifdef HAVE_PRI 08420 if (pri && (p->subs[SUB_REAL].dfd < 0)) { 08421 if (p->sig != SIG_FXSKS) { 08422 /* Gotta find an actual channel to use for this 08423 CRV if this isn't a callwait */ 08424 bearer = pri_find_empty_chan(pri, 0); 08425 if (bearer < 0) { 08426 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv); 08427 p = NULL; 08428 break; 08429 } 08430 pri_assign_bearer(p, pri, pri->pvts[bearer]); 08431 } else { 08432 if (alloc_sub(p, 0)) { 08433 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n"); 08434 p = NULL; 08435 break; 08436 } else 08437 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n"); 08438 p->pri = pri; 08439 } 08440 } 08441 #endif 08442 if (p->channel == CHAN_PSEUDO) { 08443 p = chandup(p); 08444 if (!p) { 08445 break; 08446 } 08447 } 08448 if (p->owner) { 08449 if (alloc_sub(p, SUB_CALLWAIT)) { 08450 p = NULL; 08451 break; 08452 } 08453 } 08454 p->outgoing = 1; 08455 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0); 08456 #ifdef HAVE_PRI 08457 if (p->bearer) { 08458 /* Log owner to bearer channel, too */ 08459 p->bearer->owner = tmp; 08460 } 08461 #endif 08462 /* Make special notes */ 08463 if (res > 1) { 08464 if (opt == 'c') { 08465 /* Confirm answer */ 08466 p->confirmanswer = 1; 08467 } else if (opt == 'r') { 08468 /* Distinctive ring */ 08469 if (res < 3) 08470 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data); 08471 else 08472 p->distinctivering = y; 08473 } else if (opt == 'd') { 08474 /* If this is an ISDN call, make it digital */ 08475 p->digital = 1; 08476 if (tmp) 08477 tmp->transfercapability = AST_TRANS_CAP_DIGITAL; 08478 } else { 08479 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data); 08480 } 08481 } 08482 /* Note if the call is a call waiting call */ 08483 if (tmp && callwait) 08484 tmp->cdrflags |= AST_CDR_CALLWAIT; 08485 break; 08486 } 08487 next: 08488 if (backwards) { 08489 p = p->prev; 08490 if (!p) 08491 p = end; 08492 } else { 08493 p = p->next; 08494 if (!p) 08495 p = start; 08496 } 08497 /* stop when you roll to the one that we started from */ 08498 if (p == exit) 08499 break; 08500 } 08501 ast_mutex_unlock(lock); 08502 restart_monitor(); 08503 if (callwait) 08504 *cause = AST_CAUSE_BUSY; 08505 else if (!tmp) { 08506 if (channelmatched) { 08507 if (busy) 08508 *cause = AST_CAUSE_BUSY; 08509 } else if (groupmatched) { 08510 *cause = AST_CAUSE_CONGESTION; 08511 } 08512 } 08513 08514 return tmp; 08515 }
static int dahdi_restart | ( | void | ) | [static] |
Definition at line 10426 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, lock, master, monlock, dahdi_pvt::next, NUM_SPANS, option_debug, option_verbose, dahdi_pvt::owner, pris, restart_lock, setup_dahdi(), ss_thread_lock, and dahdi_pvt::subs.
Referenced by __action_restart(), and dahdi_restart_cmd().
10427 { 10428 #if defined(HAVE_PRI) 10429 int i, j; 10430 #endif 10431 int cancel_code; 10432 struct dahdi_pvt *p; 10433 10434 ast_mutex_lock(&restart_lock); 10435 10436 if (option_verbose) 10437 ast_verbose("Destroying channels and reloading DAHDI configuration.\n"); 10438 dahdi_softhangup_all(); 10439 if (option_verbose > 3) 10440 ast_verbose("Initial softhangup of all DAHDI channels complete.\n"); 10441 10442 #if defined(HAVE_PRI) 10443 for (i = 0; i < NUM_SPANS; i++) { 10444 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) { 10445 cancel_code = pthread_cancel(pris[i].master); 10446 pthread_kill(pris[i].master, SIGURG); 10447 if (option_debug > 3) 10448 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code); 10449 pthread_join(pris[i].master, NULL); 10450 if (option_debug > 3) 10451 ast_verbose("Joined thread of span %d\n", i); 10452 } 10453 } 10454 #endif 10455 10456 ast_mutex_lock(&monlock); 10457 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 10458 cancel_code = pthread_cancel(monitor_thread); 10459 pthread_kill(monitor_thread, SIGURG); 10460 if (option_debug > 3) 10461 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code); 10462 pthread_join(monitor_thread, NULL); 10463 if (option_debug > 3) 10464 ast_verbose("Joined monitor thread\n"); 10465 } 10466 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */ 10467 10468 ast_mutex_lock(&ss_thread_lock); 10469 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */ 10470 int x = DAHDI_FLASH; 10471 if (option_debug > 2) 10472 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count); 10473 10474 for (p = iflist; p; p = p->next) { 10475 if (p->owner) 10476 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 */ 10477 } 10478 ast_cond_wait(&ss_thread_complete, &ss_thread_lock); 10479 } 10480 10481 /* ensure any created channels before monitor threads were stopped are hungup */ 10482 dahdi_softhangup_all(); 10483 if (option_verbose > 3) 10484 ast_verbose("Final softhangup of all DAHDI channels complete.\n"); 10485 destroy_all_channels(); 10486 if (option_debug) 10487 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels()); 10488 10489 ast_mutex_unlock(&monlock); 10490 10491 #ifdef HAVE_PRI 10492 for (i = 0; i < NUM_SPANS; i++) { 10493 for (j = 0; j < NUM_DCHANS; j++) 10494 dahdi_close_pri_fd(&(pris[i]), j); 10495 } 10496 10497 memset(pris, 0, sizeof(pris)); 10498 for (i = 0; i < NUM_SPANS; i++) { 10499 ast_mutex_init(&pris[i].lock); 10500 pris[i].offset = -1; 10501 pris[i].master = AST_PTHREADT_NULL; 10502 for (j = 0; j < NUM_DCHANS; j++) 10503 pris[i].fds[j] = -1; 10504 } 10505 pri_set_error(dahdi_pri_error); 10506 pri_set_message(dahdi_pri_message); 10507 #endif 10508 10509 if (setup_dahdi(2) != 0) { 10510 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n"); 10511 ast_mutex_unlock(&ss_thread_lock); 10512 return 1; 10513 } 10514 ast_mutex_unlock(&ss_thread_lock); 10515 ast_mutex_unlock(&restart_lock); 10516 return 0; 10517 }
static int dahdi_restart_cmd | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 10519 of file chan_dahdi.c.
References dahdi_restart(), RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
10520 { 10521 if (argc != 2) { 10522 return RESULT_SHOWUSAGE; 10523 } 10524 10525 if (dahdi_restart() != 0) 10526 return RESULT_FAILURE; 10527 return RESULT_SUCCESS; 10528 }
static int dahdi_ring_phone | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3874 of file chan_dahdi.c.
References ast_log(), errno, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), and dahdi_handle_event().
03875 { 03876 int x; 03877 int res; 03878 /* Make sure our transmit state is on hook */ 03879 x = 0; 03880 x = DAHDI_ONHOOK; 03881 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 03882 do { 03883 x = DAHDI_RING; 03884 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 03885 if (res) { 03886 switch (errno) { 03887 case EBUSY: 03888 case EINTR: 03889 /* Wait just in case */ 03890 usleep(10000); 03891 continue; 03892 case EINPROGRESS: 03893 res = 0; 03894 break; 03895 default: 03896 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno)); 03897 res = 0; 03898 } 03899 } 03900 } while (res); 03901 return res; 03902 }
static int dahdi_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 2730 of file chan_dahdi.c.
References send_keypad_facility_exec().
Referenced by load_module().
02731 { 02732 return send_keypad_facility_exec(chan, data); 02733 }
static int dahdi_sendtext | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 12240 of file chan_dahdi.c.
References ASCII_BYTES_PER_CHAR, ast_check_hangup(), ast_free, AST_LAW, ast_log(), ast_malloc, dahdi_pvt::channel, dahdi_get_index(), dahdi_subchannel::dfd, END_SILENCE_LEN, errno, pollfd::events, pollfd::fd, free, HEADER_LEN, HEADER_MS, len(), LOG_ERROR, dahdi_pvt::mate, option_debug, poll(), POLLOUT, PUT_CLID, PUT_CLID_MARKMS, READ_SIZE, pollfd::revents, dahdi_pvt::subs, dahdi_pvt::tdd, TDD_BYTES_PER_CHAR, tdd_generate(), ast_channel::tech_pvt, and TRAILER_MS.
12241 { 12242 #define END_SILENCE_LEN 400 12243 #define HEADER_MS 50 12244 #define TRAILER_MS 5 12245 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) 12246 #define ASCII_BYTES_PER_CHAR 80 12247 12248 unsigned char *buf,*mybuf; 12249 struct dahdi_pvt *p = c->tech_pvt; 12250 struct pollfd fds[1]; 12251 int size,res,fd,len,x; 12252 int bytes=0; 12253 /* Initial carrier (imaginary) */ 12254 float cr = 1.0; 12255 float ci = 0.0; 12256 float scont = 0.0; 12257 int index; 12258 12259 index = dahdi_get_index(c, p, 0); 12260 if (index < 0) { 12261 ast_log(LOG_WARNING, "Huh? I don't exist?\n"); 12262 return -1; 12263 } 12264 if (!text[0]) return(0); /* if nothing to send, dont */ 12265 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */ 12266 if (p->mate) 12267 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN); 12268 else 12269 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN); 12270 if (!buf) 12271 return -1; 12272 mybuf = buf; 12273 if (p->mate) { 12274 int codec = AST_LAW(p); 12275 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */ 12276 PUT_CLID_MARKMS; 12277 } 12278 /* Put actual message */ 12279 for (x = 0; text[x]; x++) { 12280 PUT_CLID(text[x]); 12281 } 12282 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */ 12283 PUT_CLID_MARKMS; 12284 } 12285 len = bytes; 12286 buf = mybuf; 12287 } else { 12288 len = tdd_generate(p->tdd, buf, text); 12289 if (len < 1) { 12290 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text)); 12291 free(mybuf); 12292 return -1; 12293 } 12294 } 12295 memset(buf + len, 0x7f, END_SILENCE_LEN); 12296 len += END_SILENCE_LEN; 12297 fd = p->subs[index].dfd; 12298 while (len) { 12299 if (ast_check_hangup(c)) { 12300 free(mybuf); 12301 return -1; 12302 } 12303 size = len; 12304 if (size > READ_SIZE) 12305 size = READ_SIZE; 12306 fds[0].fd = fd; 12307 fds[0].events = POLLOUT | POLLPRI; 12308 fds[0].revents = 0; 12309 res = poll(fds, 1, -1); 12310 if (!res) { 12311 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel); 12312 continue; 12313 } 12314 /* if got exception */ 12315 if (fds[0].revents & POLLPRI) { 12316 ast_free(mybuf); 12317 return -1; 12318 } 12319 if (!(fds[0].revents & POLLOUT)) { 12320 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel); 12321 continue; 12322 } 12323 res = write(fd, buf, size); 12324 if (res != size) { 12325 if (res == -1) { 12326 free(mybuf); 12327 return -1; 12328 } 12329 if (option_debug) 12330 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 12331 break; 12332 } 12333 len -= size; 12334 buf += size; 12335 } 12336 free(mybuf); 12337 return(0); 12338 }
static int dahdi_set_hook | ( | int | fd, | |
int | hs | |||
) | [inline, static] |
Definition at line 1974 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().
01975 { 01976 int x, res; 01977 01978 x = hs; 01979 res = ioctl(fd, DAHDI_HOOK, &x); 01980 01981 if (res < 0) { 01982 if (errno == EINPROGRESS) 01983 return 0; 01984 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno)); 01985 /* will expectedly fail if phone is off hook during operation, such as during a restart */ 01986 } 01987 01988 return res; 01989 }
static int dahdi_setlaw | ( | int | dfd, | |
int | law | |||
) | [static] |
Definition at line 8863 of file chan_dahdi.c.
08864 { 08865 int res; 08866 res = ioctl(dfd, DAHDI_SETLAW, &law); 08867 if (res) 08868 return res; 08869 return 0; 08870 }
static int dahdi_setlinear | ( | int | dfd, | |
int | linear | |||
) | [static] |
Definition at line 1288 of file chan_dahdi.c.
Referenced by dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_write(), send_callerid(), and ss_thread().
01289 { 01290 int res; 01291 res = ioctl(dfd, DAHDI_SETLINEAR, &linear); 01292 if (res) 01293 return res; 01294 return 0; 01295 }
static int dahdi_setoption | ( | struct ast_channel * | chan, | |
int | option, | |||
void * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 3238 of file chan_dahdi.c.
References ast_check_hangup(), ast_dsp_digitmode(), ast_log(), AST_OPTION_AUDIO_MODE, AST_OPTION_ECHOCAN, AST_OPTION_OPRMODE, AST_OPTION_RELAXDTMF, AST_OPTION_RXGAIN, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, AST_OPTION_TXGAIN, ast_tdd_gen_ecdisa(), dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_subchannel::dfd, dahdi_pvt::didtdd, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, errno, pollfd::events, pollfd::fd, dahdi_pvt::law, len(), LOG_DEBUG, LOG_WARNING, dahdi_pvt::mate, oprmode::mode, ast_channel::name, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, option_debug, oprmode::peer, poll(), POLLOUT, POLLPRI, READ_SIZE, pollfd::revents, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_free(), tdd_new(), ast_channel::tech_pvt, and dahdi_pvt::txgain.
03239 { 03240 char *cp; 03241 signed char *scp; 03242 int x; 03243 int index; 03244 struct dahdi_pvt *p = chan->tech_pvt, *pp; 03245 struct oprmode *oprmode; 03246 03247 03248 /* all supported options require data */ 03249 if (!data || (datalen < 1)) { 03250 errno = EINVAL; 03251 return -1; 03252 } 03253 03254 switch (option) { 03255 case AST_OPTION_TXGAIN: 03256 scp = (signed char *) data; 03257 index = dahdi_get_index(chan, p, 0); 03258 if (index < 0) { 03259 ast_log(LOG_WARNING, "No index in TXGAIN?\n"); 03260 return -1; 03261 } 03262 if (option_debug) 03263 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp); 03264 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law); 03265 case AST_OPTION_RXGAIN: 03266 scp = (signed char *) data; 03267 index = dahdi_get_index(chan, p, 0); 03268 if (index < 0) { 03269 ast_log(LOG_WARNING, "No index in RXGAIN?\n"); 03270 return -1; 03271 } 03272 if (option_debug) 03273 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp); 03274 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law); 03275 case AST_OPTION_TONE_VERIFY: 03276 if (!p->dsp) 03277 break; 03278 cp = (char *) data; 03279 switch (*cp) { 03280 case 1: 03281 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name); 03282 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */ 03283 break; 03284 case 2: 03285 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name); 03286 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */ 03287 break; 03288 default: 03289 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name); 03290 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */ 03291 break; 03292 } 03293 break; 03294 case AST_OPTION_TDD: 03295 /* turn on or off TDD */ 03296 cp = (char *) data; 03297 p->mate = 0; 03298 if (!*cp) { /* turn it off */ 03299 if (option_debug) 03300 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name); 03301 if (p->tdd) 03302 tdd_free(p->tdd); 03303 p->tdd = 0; 03304 break; 03305 } 03306 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n", 03307 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name); 03308 dahdi_disable_ec(p); 03309 /* otherwise, turn it on */ 03310 if (!p->didtdd) { /* if havent done it yet */ 03311 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */ 03312 unsigned char *buf; 03313 int size, res, fd, len; 03314 struct pollfd fds[1]; 03315 03316 buf = mybuf; 03317 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */ 03318 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */ 03319 len = 40000; 03320 index = dahdi_get_index(chan, p, 0); 03321 if (index < 0) { 03322 ast_log(LOG_WARNING, "No index in TDD?\n"); 03323 return -1; 03324 } 03325 fd = p->subs[index].dfd; 03326 while (len) { 03327 if (ast_check_hangup(chan)) 03328 return -1; 03329 size = len; 03330 if (size > READ_SIZE) 03331 size = READ_SIZE; 03332 fds[0].fd = fd; 03333 fds[0].events = POLLPRI | POLLOUT; 03334 fds[0].revents = 0; 03335 res = poll(fds, 1, -1); 03336 if (!res) { 03337 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel); 03338 continue; 03339 } 03340 /* if got exception */ 03341 if (fds[0].revents & POLLPRI) 03342 return -1; 03343 if (!(fds[0].revents & POLLOUT)) { 03344 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel); 03345 continue; 03346 } 03347 res = write(fd, buf, size); 03348 if (res != size) { 03349 if (res == -1) return -1; 03350 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 03351 break; 03352 } 03353 len -= size; 03354 buf += size; 03355 } 03356 p->didtdd = 1; /* set to have done it now */ 03357 } 03358 if (*cp == 2) { /* Mate mode */ 03359 if (p->tdd) 03360 tdd_free(p->tdd); 03361 p->tdd = 0; 03362 p->mate = 1; 03363 break; 03364 } 03365 if (!p->tdd) { /* if we dont have one yet */ 03366 p->tdd = tdd_new(); /* allocate one */ 03367 } 03368 break; 03369 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */ 03370 if (!p->dsp) 03371 break; 03372 cp = (char *) data; 03373 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n", 03374 *cp ? "ON" : "OFF", (int) *cp, chan->name); 03375 p->dtmfrelax = 0; 03376 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 03377 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 03378 break; 03379 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */ 03380 cp = (char *) data; 03381 if (!*cp) { 03382 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name); 03383 x = 0; 03384 dahdi_disable_ec(p); 03385 } else { 03386 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name); 03387 x = 1; 03388 } 03389 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1) 03390 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno)); 03391 break; 03392 case AST_OPTION_OPRMODE: /* Operator services mode */ 03393 oprmode = (struct oprmode *) data; 03394 pp = oprmode->peer->tech_pvt; 03395 p->oprmode = pp->oprmode = 0; 03396 /* setup peers */ 03397 p->oprpeer = pp; 03398 pp->oprpeer = p; 03399 /* setup modes, if any */ 03400 if (oprmode->mode) 03401 { 03402 pp->oprmode = oprmode->mode; 03403 p->oprmode = -oprmode->mode; 03404 } 03405 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n", 03406 oprmode->mode, chan->name,oprmode->peer->name);; 03407 break; 03408 case AST_OPTION_ECHOCAN: 03409 cp = (char *) data; 03410 if (*cp) { 03411 ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name); 03412 dahdi_enable_ec(p); 03413 } else { 03414 ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name); 03415 dahdi_disable_ec(p); 03416 } 03417 break; 03418 } 03419 errno = 0; 03420 03421 return 0; 03422 }
static int dahdi_show_channel | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 10591 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, 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::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.
10592 { 10593 int channel; 10594 struct dahdi_pvt *tmp = NULL; 10595 struct dahdi_confinfo ci; 10596 struct dahdi_params ps; 10597 int x; 10598 ast_mutex_t *lock; 10599 struct dahdi_pvt *start; 10600 #ifdef HAVE_PRI 10601 char *c; 10602 int trunkgroup; 10603 struct dahdi_pri *pri=NULL; 10604 #endif 10605 10606 lock = &iflock; 10607 start = iflist; 10608 10609 if (argc != 4) 10610 return RESULT_SHOWUSAGE; 10611 #ifdef HAVE_PRI 10612 if ((c = strchr(argv[3], ':'))) { 10613 if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2) 10614 return RESULT_SHOWUSAGE; 10615 if ((trunkgroup < 1) || (channel < 1)) 10616 return RESULT_SHOWUSAGE; 10617 for (x = 0; x < NUM_SPANS; x++) { 10618 if (pris[x].trunkgroup == trunkgroup) { 10619 pri = pris + x; 10620 break; 10621 } 10622 } 10623 if (pri) { 10624 start = pri->crvs; 10625 lock = &pri->lock; 10626 } else { 10627 ast_cli(fd, "No such trunk group %d\n", trunkgroup); 10628 return RESULT_FAILURE; 10629 } 10630 } else 10631 #endif 10632 channel = atoi(argv[3]); 10633 10634 ast_mutex_lock(lock); 10635 tmp = start; 10636 while (tmp) { 10637 if (tmp->channel == channel) { 10638 #ifdef HAVE_PRI 10639 if (pri) 10640 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel); 10641 else 10642 #endif 10643 ast_cli(fd, "Channel: %d\n", tmp->channel); 10644 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd); 10645 ast_cli(fd, "Span: %d\n", tmp->span); 10646 ast_cli(fd, "Extension: %s\n", tmp->exten); 10647 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no"); 10648 ast_cli(fd, "Context: %s\n", tmp->context); 10649 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num); 10650 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton); 10651 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name); 10652 ast_cli(fd, "Destroy: %d\n", tmp->destroy); 10653 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm); 10654 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig)); 10655 ast_cli(fd, "Radio: %d\n", tmp->radio); 10656 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>"); 10657 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)" : ""); 10658 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)" : ""); 10659 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)" : ""); 10660 ast_cli(fd, "Confno: %d\n", tmp->confno); 10661 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno); 10662 ast_cli(fd, "Real in conference: %d\n", tmp->inconference); 10663 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no"); 10664 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no"); 10665 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas); 10666 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown"); 10667 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no"); 10668 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no"); 10669 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF"); 10670 if (tmp->master) 10671 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel); 10672 for (x = 0; x < MAX_SLAVES; x++) { 10673 if (tmp->slaves[x]) 10674 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel); 10675 } 10676 #ifdef HAVE_PRI 10677 if (tmp->pri) { 10678 ast_cli(fd, "PRI Flags: "); 10679 if (tmp->resetting) 10680 ast_cli(fd, "Resetting "); 10681 if (tmp->call) 10682 ast_cli(fd, "Call "); 10683 if (tmp->bearer) 10684 ast_cli(fd, "Bearer "); 10685 ast_cli(fd, "\n"); 10686 if (tmp->logicalspan) 10687 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan); 10688 else 10689 ast_cli(fd, "PRI Logical Span: Implicit\n"); 10690 } 10691 10692 #endif 10693 memset(&ci, 0, sizeof(ci)); 10694 ps.channo = tmp->channel; 10695 if (tmp->subs[SUB_REAL].dfd > -1) { 10696 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 10697 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode); 10698 } 10699 #ifdef DAHDI_GETCONFMUTE 10700 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) { 10701 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No"); 10702 } 10703 #endif 10704 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 10705 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno)); 10706 } else { 10707 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook"); 10708 } 10709 } 10710 if (ISTRUNK(tmp)) { 10711 ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no"); 10712 if (!ast_strlen_zero(progzone)) 10713 ast_cli(fd, "Progress Zone: %s\n", progzone); 10714 ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no"); 10715 if(tmp->busydetect) { 10716 ast_cli(fd, "Busy Count: %d\n", tmp->busycount); 10717 if(tmp->busytonelength > 0) { 10718 ast_cli(fd, "Busy Pattern:\n"); 10719 ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength); 10720 if (tmp->busyquietlength > 0) 10721 ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength); 10722 else 10723 ast_cli(fd, " -- Detect Tone Only\n"); 10724 if(tmp->busyfuzziness > 0) 10725 ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness); 10726 } 10727 } 10728 } 10729 ast_mutex_unlock(lock); 10730 return RESULT_SUCCESS; 10731 } 10732 tmp = tmp->next; 10733 } 10734 10735 ast_cli(fd, "Unable to find given channel %d\n", channel); 10736 ast_mutex_unlock(lock); 10737 return RESULT_FAILURE; 10738 }
static int dahdi_show_channels | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 10530 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.
10531 { 10532 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" 10533 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" 10534 struct dahdi_pvt *tmp = NULL; 10535 char tmps[20] = ""; 10536 ast_mutex_t *lock; 10537 struct dahdi_pvt *start; 10538 #ifdef HAVE_PRI 10539 int trunkgroup; 10540 struct dahdi_pri *pri = NULL; 10541 int x; 10542 #endif 10543 10544 lock = &iflock; 10545 start = iflist; 10546 10547 #ifdef HAVE_PRI 10548 if (argc == 4) { 10549 if ((trunkgroup = atoi(argv[3])) < 1) 10550 return RESULT_SHOWUSAGE; 10551 for (x = 0; x < NUM_SPANS; x++) { 10552 if (pris[x].trunkgroup == trunkgroup) { 10553 pri = pris + x; 10554 break; 10555 } 10556 } 10557 if (pri) { 10558 start = pri->crvs; 10559 lock = &pri->lock; 10560 } else { 10561 ast_cli(fd, "No such trunk group %d\n", trunkgroup); 10562 return RESULT_FAILURE; 10563 } 10564 } else 10565 #endif 10566 if (argc != 3) 10567 return RESULT_SHOWUSAGE; 10568 10569 ast_mutex_lock(lock); 10570 #ifdef HAVE_PRI 10571 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret"); 10572 #else 10573 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret"); 10574 #endif 10575 10576 tmp = start; 10577 while (tmp) { 10578 if (tmp->channel > 0) { 10579 snprintf(tmps, sizeof(tmps), "%d", tmp->channel); 10580 } else 10581 ast_copy_string(tmps, "pseudo", sizeof(tmps)); 10582 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret); 10583 tmp = tmp->next; 10584 } 10585 ast_mutex_unlock(lock); 10586 return RESULT_SUCCESS; 10587 #undef FORMAT 10588 #undef FORMAT2 10589 }
static int dahdi_show_status | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10771 of file chan_dahdi.c.
References alarms, ast_cli(), ast_log(), DAHDI_FILE_CTL, errno, FORMAT, FORMAT2, RESULT_FAILURE, and dahdi_pri::span.
10771 { 10772 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n" 10773 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n" 10774 10775 int span; 10776 int res; 10777 char alarms[50]; 10778 10779 int ctl; 10780 struct dahdi_spaninfo s; 10781 10782 if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) { 10783 ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno)); 10784 ast_cli(fd, "No " DAHDI_NAME " interface found.\n"); 10785 return RESULT_FAILURE; 10786 } 10787 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4"); 10788 10789 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 10790 s.spanno = span; 10791 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 10792 if (res) { 10793 continue; 10794 } 10795 alarms[0] = '\0'; 10796 if (s.alarms > 0) { 10797 if (s.alarms & DAHDI_ALARM_BLUE) 10798 strcat(alarms, "BLU/"); 10799 if (s.alarms & DAHDI_ALARM_YELLOW) 10800 strcat(alarms, "YEL/"); 10801 if (s.alarms & DAHDI_ALARM_RED) 10802 strcat(alarms, "RED/"); 10803 if (s.alarms & DAHDI_ALARM_LOOPBACK) 10804 strcat(alarms, "LB/"); 10805 if (s.alarms & DAHDI_ALARM_RECOVER) 10806 strcat(alarms, "REC/"); 10807 if (s.alarms & DAHDI_ALARM_NOTOPEN) 10808 strcat(alarms, "NOP/"); 10809 if (!strlen(alarms)) 10810 strcat(alarms, "UUU/"); 10811 if (strlen(alarms)) { 10812 /* Strip trailing / */ 10813 alarms[strlen(alarms) - 1] = '\0'; 10814 } 10815 } else { 10816 if (s.numchans) 10817 strcpy(alarms, "OK"); 10818 else 10819 strcpy(alarms, "UNCONFIGURED"); 10820 } 10821 10822 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count); 10823 } 10824 close(ctl); 10825 10826 return RESULT_SUCCESS; 10827 #undef FORMAT 10828 #undef FORMAT2 10829 }
static char* dahdi_sig2str | ( | int | sig | ) | [static] |
Definition at line 1525 of file chan_dahdi.c.
References SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, and SIG_SFWINK.
01526 { 01527 static char buf[256]; 01528 switch (sig) { 01529 case SIG_EM: 01530 return "E & M Immediate"; 01531 case SIG_EMWINK: 01532 return "E & M Wink"; 01533 case SIG_EM_E1: 01534 return "E & M E1"; 01535 case SIG_FEATD: 01536 return "Feature Group D (DTMF)"; 01537 case SIG_FEATDMF: 01538 return "Feature Group D (MF)"; 01539 case SIG_FEATDMF_TA: 01540 return "Feature Groud D (MF) Tandem Access"; 01541 case SIG_FEATB: 01542 return "Feature Group B (MF)"; 01543 case SIG_E911: 01544 return "E911 (MF)"; 01545 case SIG_FGC_CAMA: 01546 return "FGC/CAMA (Dialpulse)"; 01547 case SIG_FGC_CAMAMF: 01548 return "FGC/CAMA (MF)"; 01549 case SIG_FXSLS: 01550 return "FXS Loopstart"; 01551 case SIG_FXSGS: 01552 return "FXS Groundstart"; 01553 case SIG_FXSKS: 01554 return "FXS Kewlstart"; 01555 case SIG_FXOLS: 01556 return "FXO Loopstart"; 01557 case SIG_FXOGS: 01558 return "FXO Groundstart"; 01559 case SIG_FXOKS: 01560 return "FXO Kewlstart"; 01561 case SIG_PRI: 01562 return "ISDN PRI"; 01563 case SIG_SF: 01564 return "SF (Tone) Immediate"; 01565 case SIG_SFWINK: 01566 return "SF (Tone) Wink"; 01567 case SIG_SF_FEATD: 01568 return "SF (Tone) with Feature Group D (DTMF)"; 01569 case SIG_SF_FEATDMF: 01570 return "SF (Tone) with Feature Group D (MF)"; 01571 case SIG_SF_FEATB: 01572 return "SF (Tone) with Feature Group B (MF)"; 01573 case SIG_GR303FXOKS: 01574 return "GR-303 with FXOKS"; 01575 case SIG_GR303FXSKS: 01576 return "GR-303 with FXSKS"; 01577 case 0: 01578 return "Pseudo"; 01579 default: 01580 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig); 01581 return buf; 01582 } 01583 }
static void dahdi_softhangup_all | ( | void | ) | [static] |
Definition at line 10397 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().
10398 { 10399 struct dahdi_pvt *p; 10400 retry: 10401 ast_mutex_lock(&iflock); 10402 for (p = iflist; p; p = p->next) { 10403 ast_mutex_lock(&p->lock); 10404 if (p->owner && !p->restartpending) { 10405 if (ast_channel_trylock(p->owner)) { 10406 if (option_debug > 2) 10407 ast_verbose("Avoiding deadlock\n"); 10408 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */ 10409 ast_mutex_unlock(&p->lock); 10410 ast_mutex_unlock(&iflock); 10411 goto retry; 10412 } 10413 if (option_debug > 2) 10414 ast_verbose("Softhanging up on %s\n", p->owner->name); 10415 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT); 10416 p->restartpending = 1; 10417 num_restart_pending++; 10418 ast_channel_unlock(p->owner); 10419 } 10420 ast_mutex_unlock(&p->lock); 10421 } 10422 ast_mutex_unlock(&iflock); 10423 }
static void dahdi_train_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1806 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().
01807 { 01808 int x; 01809 int res; 01810 if (p && p->echocancel && p->echotraining) { 01811 x = p->echotraining; 01812 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x); 01813 if (res) 01814 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno)); 01815 else { 01816 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel); 01817 } 01818 } else 01819 ast_log(LOG_DEBUG, "No echo training requested\n"); 01820 }
static void dahdi_unlink | ( | struct dahdi_pvt * | slave, | |
struct dahdi_pvt * | master, | |||
int | needlock | |||
) | [static] |
Definition at line 3443 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().
03444 { 03445 /* Unlink a specific slave or all slaves/masters from a given master */ 03446 int x; 03447 int hasslaves; 03448 if (!master) 03449 return; 03450 if (needlock) { 03451 ast_mutex_lock(&master->lock); 03452 if (slave) { 03453 while (ast_mutex_trylock(&slave->lock)) { 03454 DEADLOCK_AVOIDANCE(&master->lock); 03455 } 03456 } 03457 } 03458 hasslaves = 0; 03459 for (x = 0; x < MAX_SLAVES; x++) { 03460 if (master->slaves[x]) { 03461 if (!slave || (master->slaves[x] == slave)) { 03462 /* Take slave out of the conference */ 03463 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel); 03464 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL); 03465 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL); 03466 master->slaves[x]->master = NULL; 03467 master->slaves[x] = NULL; 03468 } else 03469 hasslaves = 1; 03470 } 03471 if (!hasslaves) 03472 master->inconference = 0; 03473 } 03474 if (!slave) { 03475 if (master->master) { 03476 /* Take master out of the conference */ 03477 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL); 03478 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL); 03479 hasslaves = 0; 03480 for (x = 0; x < MAX_SLAVES; x++) { 03481 if (master->master->slaves[x] == master) 03482 master->master->slaves[x] = NULL; 03483 else if (master->master->slaves[x]) 03484 hasslaves = 1; 03485 } 03486 if (!hasslaves) 03487 master->master->inconference = 0; 03488 } 03489 master->master = NULL; 03490 } 03491 update_conf(master); 03492 if (needlock) { 03493 if (slave) 03494 ast_mutex_unlock(&slave->lock); 03495 ast_mutex_unlock(&master->lock); 03496 } 03497 }
static int dahdi_wait_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition at line 265 of file chan_dahdi.c.
Referenced by ss_thread().
00266 { 00267 int i, j = 0; 00268 i = DAHDI_IOMUX_SIGEVENT; 00269 if (ioctl(fd, DAHDI_IOMUX, &i) == -1) 00270 return -1; 00271 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) 00272 return -1; 00273 return j; 00274 }
static int dahdi_wink | ( | struct dahdi_pvt * | p, | |
int | index | |||
) | [static] |
Definition at line 5863 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by ss_thread().
05864 { 05865 int j; 05866 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK); 05867 for (;;) 05868 { 05869 /* set bits of interest */ 05870 j = DAHDI_IOMUX_SIGEVENT; 05871 /* wait for some happening */ 05872 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1); 05873 /* exit loop if we have it */ 05874 if (j & DAHDI_IOMUX_SIGEVENT) break; 05875 } 05876 /* get the event info */ 05877 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1); 05878 return 0; 05879 }
static int dahdi_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 5390 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.
05391 { 05392 struct dahdi_pvt *p = ast->tech_pvt; 05393 int res; 05394 int index; 05395 index = dahdi_get_index(ast, p, 0); 05396 if (index < 0) { 05397 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name); 05398 return -1; 05399 } 05400 05401 #if 0 05402 #ifdef HAVE_PRI 05403 ast_mutex_lock(&p->lock); 05404 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { 05405 if (p->pri->pri) { 05406 if (!pri_grab(p, p->pri)) { 05407 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 05408 pri_rel(p->pri); 05409 } else 05410 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05411 } 05412 p->proceeding=1; 05413 } 05414 ast_mutex_unlock(&p->lock); 05415 #endif 05416 #endif 05417 /* Write a frame of (presumably voice) data */ 05418 if (frame->frametype != AST_FRAME_VOICE) { 05419 if (frame->frametype != AST_FRAME_IMAGE) 05420 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); 05421 return 0; 05422 } 05423 if ((frame->subclass != AST_FORMAT_SLINEAR) && 05424 (frame->subclass != AST_FORMAT_ULAW) && 05425 (frame->subclass != AST_FORMAT_ALAW)) { 05426 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass); 05427 return -1; 05428 } 05429 if (p->dialing) { 05430 if (option_debug) 05431 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name); 05432 return 0; 05433 } 05434 if (!p->owner) { 05435 if (option_debug) 05436 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name); 05437 return 0; 05438 } 05439 if (p->cidspill) { 05440 if (option_debug) 05441 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n"); 05442 return 0; 05443 } 05444 /* Return if it's not valid data */ 05445 if (!frame->data || !frame->datalen) 05446 return 0; 05447 05448 if (frame->subclass == AST_FORMAT_SLINEAR) { 05449 if (!p->subs[index].linear) { 05450 p->subs[index].linear = 1; 05451 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 05452 if (res) 05453 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel); 05454 } 05455 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1); 05456 } else { 05457 /* x-law already */ 05458 if (p->subs[index].linear) { 05459 p->subs[index].linear = 0; 05460 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 05461 if (res) 05462 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel); 05463 } 05464 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0); 05465 } 05466 if (res < 0) { 05467 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 05468 return -1; 05469 } 05470 return 0; 05471 }
static void destroy_all_channels | ( | void | ) | [static] |
Definition at line 2646 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().
02647 { 02648 int x; 02649 struct dahdi_pvt *p, *pl; 02650 02651 while (num_restart_pending) { 02652 usleep(1); 02653 } 02654 02655 ast_mutex_lock(&iflock); 02656 /* Destroy all the interfaces and free their memory */ 02657 p = iflist; 02658 while (p) { 02659 /* Free any callerid */ 02660 if (p->cidspill) 02661 ast_free(p->cidspill); 02662 pl = p; 02663 p = p->next; 02664 x = pl->channel; 02665 /* Free associated memory */ 02666 if (pl) 02667 destroy_dahdi_pvt(&pl); 02668 if (option_verbose > 2) 02669 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x); 02670 } 02671 iflist = NULL; 02672 ifcount = 0; 02673 ast_mutex_unlock(&iflock); 02674 }
Definition at line 2596 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().
02597 { 02598 int owned = 0; 02599 int i = 0; 02600 02601 if (!now) { 02602 if (cur->owner) { 02603 owned = 1; 02604 } 02605 02606 for (i = 0; i < 3; i++) { 02607 if (cur->subs[i].owner) { 02608 owned = 1; 02609 } 02610 } 02611 if (!owned) { 02612 if (prev) { 02613 prev->next = cur->next; 02614 if (prev->next) 02615 prev->next->prev = prev; 02616 else 02617 ifend = prev; 02618 } else { 02619 iflist = cur->next; 02620 if (iflist) 02621 iflist->prev = NULL; 02622 else 02623 ifend = NULL; 02624 } 02625 destroy_dahdi_pvt(&cur); 02626 } 02627 } else { 02628 if (prev) { 02629 prev->next = cur->next; 02630 if (prev->next) 02631 prev->next->prev = prev; 02632 else 02633 ifend = prev; 02634 } else { 02635 iflist = cur->next; 02636 if (iflist) 02637 iflist->prev = NULL; 02638 else 02639 ifend = NULL; 02640 } 02641 destroy_dahdi_pvt(&cur); 02642 } 02643 return 0; 02644 }
static void destroy_dahdi_pvt | ( | struct dahdi_pvt ** | pvt | ) | [static] |
Definition at line 2578 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().
02579 { 02580 struct dahdi_pvt *p = *pvt; 02581 /* Remove channel from the list */ 02582 if (p->prev) 02583 p->prev->next = p->next; 02584 if (p->next) 02585 p->next->prev = p->prev; 02586 if (p->use_smdi) 02587 ast_smdi_interface_unref(p->smdi_iface); 02588 ast_mutex_destroy(&p->lock); 02589 dahdi_close_sub(p, SUB_REAL); 02590 if (p->owner) 02591 p->owner->tech_pvt = NULL; 02592 free(p); 02593 *pvt = NULL; 02594 }
static char* dialplan2str | ( | int | dialplan | ) | [static] |
Definition at line 1516 of file chan_dahdi.c.
Referenced by dahdi_call(), and mkintf().
01517 { 01518 if (dialplan == -1) { 01519 return("Dynamically set dialplan in ISDN"); 01520 } 01521 return (pri_plan2str(dialplan)); 01522 }
static int digit_to_dtmfindex | ( | char | digit | ) | [static] |
Definition at line 1349 of file chan_dahdi.c.
Referenced by dahdi_digit_begin().
01350 { 01351 if (isdigit(digit)) 01352 return DAHDI_TONE_DTMF_BASE + (digit - '0'); 01353 else if (digit >= 'A' && digit <= 'D') 01354 return DAHDI_TONE_DTMF_A + (digit - 'A'); 01355 else if (digit >= 'a' && digit <= 'd') 01356 return DAHDI_TONE_DTMF_A + (digit - 'a'); 01357 else if (digit == '*') 01358 return DAHDI_TONE_DTMF_s; 01359 else if (digit == '#') 01360 return DAHDI_TONE_DTMF_p; 01361 else 01362 return -1; 01363 }
static void disable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3522 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().
03523 { 03524 #ifdef DAHDI_TONEDETECT 03525 int val; 03526 #endif 03527 03528 p->ignoredtmf = 1; 03529 03530 #ifdef DAHDI_TONEDETECT 03531 val = 0; 03532 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 03533 #endif 03534 if (!p->hardwaredtmf && p->dsp) { 03535 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT; 03536 ast_dsp_set_features(p->dsp, p->dsp_features); 03537 } 03538 }
static void* do_idle_thread | ( | void * | vchan | ) | [static] |
Definition at line 8641 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().
08642 { 08643 struct ast_channel *chan = vchan; 08644 struct dahdi_pvt *pvt = chan->tech_pvt; 08645 struct ast_frame *f; 08646 char ex[80]; 08647 /* Wait up to 30 seconds for an answer */ 08648 int newms, ms = 30000; 08649 if (option_verbose > 2) 08650 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name); 08651 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial); 08652 if (ast_call(chan, ex, 0)) { 08653 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex); 08654 ast_hangup(chan); 08655 return NULL; 08656 } 08657 while ((newms = ast_waitfor(chan, ms)) > 0) { 08658 f = ast_read(chan); 08659 if (!f) { 08660 /* Got hangup */ 08661 break; 08662 } 08663 if (f->frametype == AST_FRAME_CONTROL) { 08664 switch (f->subclass) { 08665 case AST_CONTROL_ANSWER: 08666 /* Launch the PBX */ 08667 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten)); 08668 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context)); 08669 chan->priority = 1; 08670 if (option_verbose > 3) 08671 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context); 08672 ast_pbx_run(chan); 08673 /* It's already hungup, return immediately */ 08674 return NULL; 08675 case AST_CONTROL_BUSY: 08676 if (option_verbose > 3) 08677 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name); 08678 break; 08679 case AST_CONTROL_CONGESTION: 08680 if (option_verbose > 3) 08681 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name); 08682 break; 08683 }; 08684 } 08685 ast_frfree(f); 08686 ms = newms; 08687 } 08688 /* Hangup the channel since nothing happend */ 08689 ast_hangup(chan); 08690 return NULL; 08691 }
static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 7269 of file chan_dahdi.c.
References ast_calloc, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::cidspill, pollfd::events, pollfd::fd, free, iflist, iflock, last, LOG_DEBUG, dahdi_pvt::next, dahdi_pvt::owner, POLLIN, POLLPRI, dahdi_pvt::radio, pollfd::revents, dahdi_pvt::sig, SUB_REAL, and dahdi_pvt::subs.
Referenced by restart_monitor().
07270 { 07271 int count, res, res2, spoint, pollres=0; 07272 struct dahdi_pvt *i; 07273 struct dahdi_pvt *last = NULL; 07274 time_t thispass = 0, lastpass = 0; 07275 int found; 07276 char buf[1024]; 07277 struct pollfd *pfds=NULL; 07278 int lastalloc = -1; 07279 /* This thread monitors all the frame relay interfaces which are not yet in use 07280 (and thus do not have a separate thread) indefinitely */ 07281 /* From here on out, we die whenever asked */ 07282 #if 0 07283 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 07284 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 07285 return NULL; 07286 } 07287 ast_log(LOG_DEBUG, "Monitor starting...\n"); 07288 #endif 07289 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 07290 07291 for (;;) { 07292 /* Lock the interface list */ 07293 ast_mutex_lock(&iflock); 07294 if (!pfds || (lastalloc != ifcount)) { 07295 if (pfds) { 07296 free(pfds); 07297 pfds = NULL; 07298 } 07299 if (ifcount) { 07300 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) { 07301 ast_mutex_unlock(&iflock); 07302 return NULL; 07303 } 07304 } 07305 lastalloc = ifcount; 07306 } 07307 /* Build the stuff we're going to poll on, that is the socket of every 07308 dahdi_pvt that does not have an associated owner channel */ 07309 count = 0; 07310 i = iflist; 07311 while (i) { 07312 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) { 07313 if (!i->owner && !i->subs[SUB_REAL].owner) { 07314 /* This needs to be watched, as it lacks an owner */ 07315 pfds[count].fd = i->subs[SUB_REAL].dfd; 07316 pfds[count].events = POLLPRI; 07317 pfds[count].revents = 0; 07318 /* Message waiting or r2 channels also get watched for reading */ 07319 if (i->cidspill) 07320 pfds[count].events |= POLLIN; 07321 count++; 07322 } 07323 } 07324 i = i->next; 07325 } 07326 /* Okay, now that we know what to do, release the interface lock */ 07327 ast_mutex_unlock(&iflock); 07328 07329 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 07330 pthread_testcancel(); 07331 /* Wait at least a second for something to happen */ 07332 res = poll(pfds, count, 1000); 07333 pthread_testcancel(); 07334 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 07335 07336 /* Okay, poll has finished. Let's see what happened. */ 07337 if (res < 0) { 07338 if ((errno != EAGAIN) && (errno != EINTR)) 07339 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno)); 07340 continue; 07341 } 07342 /* Alright, lock the interface list again, and let's look and see what has 07343 happened */ 07344 ast_mutex_lock(&iflock); 07345 found = 0; 07346 spoint = 0; 07347 lastpass = thispass; 07348 thispass = time(NULL); 07349 i = iflist; 07350 while (i) { 07351 if (thispass != lastpass) { 07352 if (!found && ((i == last) || ((i == iflist) && !last))) { 07353 last = i; 07354 if (last) { 07355 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) && 07356 (last->sig & __DAHDI_SIG_FXO)) { 07357 res = ast_app_has_voicemail(last->mailbox, NULL); 07358 if (last->msgstate != res) { 07359 int x; 07360 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel); 07361 x = DAHDI_FLUSH_BOTH; 07362 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 07363 if (res2) 07364 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno)); 07365 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) { 07366 /* Turn on on hook transfer for 4 seconds */ 07367 x = 4000; 07368 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x); 07369 last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last)); 07370 last->cidpos = 0; 07371 last->msgstate = res; 07372 last->onhooktime = thispass; 07373 } 07374 found ++; 07375 } 07376 } 07377 last = last->next; 07378 } 07379 } 07380 } 07381 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) { 07382 if (i->radio && !i->owner) 07383 { 07384 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 07385 if (res) 07386 { 07387 if (option_debug) 07388 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel); 07389 /* Don't hold iflock while handling init events */ 07390 ast_mutex_unlock(&iflock); 07391 handle_init_event(i, res); 07392 ast_mutex_lock(&iflock); 07393 } 07394 i = i->next; 07395 continue; 07396 } 07397 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint); 07398 if (pollres & POLLIN) { 07399 if (i->owner || i->subs[SUB_REAL].owner) { 07400 #ifdef HAVE_PRI 07401 if (!i->pri) 07402 #endif 07403 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd); 07404 i = i->next; 07405 continue; 07406 } 07407 if (!i->cidspill) { 07408 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd); 07409 i = i->next; 07410 continue; 07411 } 07412 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf)); 07413 if (res > 0) { 07414 /* We read some number of bytes. Write an equal amount of data */ 07415 if (res > i->cidlen - i->cidpos) 07416 res = i->cidlen - i->cidpos; 07417 res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res); 07418 if (res2 > 0) { 07419 i->cidpos += res2; 07420 if (i->cidpos >= i->cidlen) { 07421 free(i->cidspill); 07422 i->cidspill = 0; 07423 i->cidpos = 0; 07424 i->cidlen = 0; 07425 } 07426 } else { 07427 ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno)); 07428 i->msgstate = -1; 07429 } 07430 } else { 07431 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno)); 07432 } 07433 } 07434 if (pollres & POLLPRI) { 07435 if (i->owner || i->subs[SUB_REAL].owner) { 07436 #ifdef HAVE_PRI 07437 if (!i->pri) 07438 #endif 07439 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd); 07440 i = i->next; 07441 continue; 07442 } 07443 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 07444 if (option_debug) 07445 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel); 07446 /* Don't hold iflock while handling init events */ 07447 ast_mutex_unlock(&iflock); 07448 handle_init_event(i, res); 07449 ast_mutex_lock(&iflock); 07450 } 07451 } 07452 i=i->next; 07453 } 07454 ast_mutex_unlock(&iflock); 07455 } 07456 /* Never reached */ 07457 return NULL; 07458 07459 }
static void enable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3540 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().
03541 { 03542 #ifdef DAHDI_TONEDETECT 03543 int val; 03544 #endif 03545 03546 if (p->channel == CHAN_PSEUDO) 03547 return; 03548 03549 p->ignoredtmf = 0; 03550 03551 #ifdef DAHDI_TONEDETECT 03552 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 03553 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 03554 #endif 03555 if (!p->hardwaredtmf && p->dsp) { 03556 p->dsp_features |= DSP_FEATURE_DTMF_DETECT; 03557 ast_dsp_set_features(p->dsp, p->dsp_features); 03558 } 03559 }
static char* event2str | ( | int | event | ) | [static] |
Definition at line 1506 of file chan_dahdi.c.
Referenced by __dahdi_exception(), dahdi_handle_event(), and ss_thread().
01507 { 01508 static char buf[256]; 01509 if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1)) 01510 return events[event]; 01511 sprintf(buf, "Event %d", event); /* safe */ 01512 return buf; 01513 }
static void fill_rxgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 1871 of file chan_dahdi.c.
References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_rxgain().
01872 { 01873 int j; 01874 int k; 01875 float linear_gain = pow(10.0, gain / 20.0); 01876 01877 switch (law) { 01878 case DAHDI_LAW_ALAW: 01879 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) { 01880 if (gain) { 01881 k = (int) (((float) AST_ALAW(j)) * linear_gain); 01882 if (k > 32767) k = 32767; 01883 if (k < -32767) k = -32767; 01884 g->rxgain[j] = AST_LIN2A(k); 01885 } else { 01886 g->rxgain[j] = j; 01887 } 01888 } 01889 break; 01890 case DAHDI_LAW_MULAW: 01891 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) { 01892 if (gain) { 01893 k = (int) (((float) AST_MULAW(j)) * linear_gain); 01894 if (k > 32767) k = 32767; 01895 if (k < -32767) k = -32767; 01896 g->rxgain[j] = AST_LIN2MU(k); 01897 } else { 01898 g->rxgain[j] = j; 01899 } 01900 } 01901 break; 01902 } 01903 }
static void fill_txgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 1837 of file chan_dahdi.c.
References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_txgain().
01838 { 01839 int j; 01840 int k; 01841 float linear_gain = pow(10.0, gain / 20.0); 01842 01843 switch (law) { 01844 case DAHDI_LAW_ALAW: 01845 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) { 01846 if (gain) { 01847 k = (int) (((float) AST_ALAW(j)) * linear_gain); 01848 if (k > 32767) k = 32767; 01849 if (k < -32767) k = -32767; 01850 g->txgain[j] = AST_LIN2A(k); 01851 } else { 01852 g->txgain[j] = j; 01853 } 01854 } 01855 break; 01856 case DAHDI_LAW_MULAW: 01857 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) { 01858 if (gain) { 01859 k = (int) (((float) AST_MULAW(j)) * linear_gain); 01860 if (k > 32767) k = 32767; 01861 if (k < -32767) k = -32767; 01862 g->txgain[j] = AST_LIN2MU(k); 01863 } else { 01864 g->txgain[j] = j; 01865 } 01866 } 01867 break; 01868 } 01869 }
static struct dahdi_pvt* find_channel | ( | int | channel | ) | [static] |
Definition at line 10929 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().
10930 { 10931 struct dahdi_pvt *p = iflist; 10932 while (p) { 10933 if (p->channel == channel) { 10934 break; 10935 } 10936 p = p->next; 10937 } 10938 return p; 10939 }
static int get_alarms | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3982 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, errno, dahdi_pvt::span, SUB_REAL, and dahdi_pvt::subs.
Referenced by __action_showchannels(), dahdi_handle_event(), and handle_init_event().
03983 { 03984 int res; 03985 struct dahdi_spaninfo zi; 03986 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS) 03987 /* 03988 * The conditional compilation is needed only in asterisk-1.4 for 03989 * backward compatibility with old zaptel drivers that don't have 03990 * a DAHDI_PARAMS.chan_alarms field. 03991 */ 03992 struct dahdi_params params; 03993 #endif 03994 03995 memset(&zi, 0, sizeof(zi)); 03996 zi.spanno = p->span; 03997 03998 /* First check for span alarms */ 03999 if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) { 04000 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno)); 04001 return 0; 04002 } 04003 if (zi.alarms != DAHDI_ALARM_NONE) 04004 return zi.alarms; 04005 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS) 04006 /* No alarms on the span. Check for channel alarms. */ 04007 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0) 04008 return params.chan_alarms; 04009 /* ioctl failed */ 04010 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel); 04011 #endif 04012 return DAHDI_ALARM_NONE; 04013 }
static void handle_alarms | ( | struct dahdi_pvt * | p, | |
int | alarms | |||
) | [static] |
Definition at line 4097 of file chan_dahdi.c.
References alarm2str(), ast_log(), dahdi_pvt::channel, EVENT_FLAG_SYSTEM, manager_event(), and dahdi_pvt::unknown_alarm.
Referenced by dahdi_handle_event(), and handle_init_event().
04098 { 04099 const char *alarm_str = alarm2str(alarms); 04100 04101 /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code 04102 * doesn't know what to do with it. Don't confuse users with log messages. */ 04103 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) { 04104 p->unknown_alarm = 1; 04105 return; 04106 } else { 04107 p->unknown_alarm = 0; 04108 } 04109 04110 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); 04111 manager_event(EVENT_FLAG_SYSTEM, "Alarm", 04112 "Alarm: %s\r\n" 04113 "Channel: %d\r\n", 04114 alarm_str, p->channel); 04115 }
static int handle_dahdi_show_cadences | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10744 of file chan_dahdi.c.
References ast_cli(), COLOR_BLACK, COLOR_GREEN, COLOR_MAGENTA, and term_color().
10745 { 10746 int i, j; 10747 for (i = 0; i < num_cadence; i++) { 10748 char output[1024]; 10749 char tmp[16], tmp2[64]; 10750 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1); 10751 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output)); 10752 10753 for (j = 0; j < 16; j++) { 10754 if (cadences[i].ringcadence[j] == 0) 10755 break; 10756 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]); 10757 if (cidrings[i] * 2 - 1 == j) 10758 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1); 10759 else 10760 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1); 10761 if (j != 0) 10762 strncat(output, ",", sizeof(output) - strlen(output) - 1); 10763 strncat(output, tmp2, sizeof(output) - strlen(output) - 1); 10764 } 10765 ast_cli(fd,"%s\n",output); 10766 } 10767 return 0; 10768 }
static int handle_init_event | ( | struct dahdi_pvt * | i, | |
int | event | |||
) | [static] |
Definition at line 7061 of file chan_dahdi.c.
References ast_hangup(), ast_log(), ast_pthread_create, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, ast_verbose(), dahdi_pvt::channel, dahdi_pvt::cid_start, CID_START_POLARITY, dahdi_pvt::cidspill, dahdi_destroy_channel_bynum(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_new(), dahdi_set_hook(), errno, EVENT_FLAG_SYSTEM, free, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::immediate, dahdi_pvt::inalarm, LOG_NOTICE, manager_event(), dahdi_pvt::polarity, POLARITY_REV, dahdi_pvt::radio, dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, sig2str, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, ss_thread(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::unknown_alarm, and VERBOSE_PREFIX_2.
07062 { 07063 int res; 07064 pthread_t threadid; 07065 pthread_attr_t attr; 07066 struct ast_channel *chan; 07067 pthread_attr_init(&attr); 07068 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 07069 /* Handle an event on a given channel for the monitor thread. */ 07070 switch (event) { 07071 case DAHDI_EVENT_NONE: 07072 case DAHDI_EVENT_BITSCHANGED: 07073 break; 07074 case DAHDI_EVENT_WINKFLASH: 07075 case DAHDI_EVENT_RINGOFFHOOK: 07076 if (i->inalarm) break; 07077 if (i->radio) break; 07078 /* Got a ring/answer. What kind of channel are we? */ 07079 switch (i->sig) { 07080 case SIG_FXOLS: 07081 case SIG_FXOGS: 07082 case SIG_FXOKS: 07083 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07084 if (res && (errno == EBUSY)) 07085 break; 07086 if (i->cidspill) { 07087 /* Cancel VMWI spill */ 07088 free(i->cidspill); 07089 i->cidspill = NULL; 07090 } 07091 if (i->immediate) { 07092 dahdi_enable_ec(i); 07093 /* The channel is immediately up. Start right away */ 07094 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 07095 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0); 07096 if (!chan) { 07097 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel); 07098 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07099 if (res < 0) 07100 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 07101 } 07102 } else { 07103 /* Check for callerid, digits, etc */ 07104 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0); 07105 if (chan) { 07106 if (has_voicemail(i)) 07107 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 07108 else 07109 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 07110 if (res < 0) 07111 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel); 07112 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 07113 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 07114 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07115 if (res < 0) 07116 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 07117 ast_hangup(chan); 07118 } 07119 } else 07120 ast_log(LOG_WARNING, "Unable to create channel\n"); 07121 } 07122 break; 07123 case SIG_FXSLS: 07124 case SIG_FXSGS: 07125 case SIG_FXSKS: 07126 i->ringt = i->ringt_base; 07127 /* Fall through */ 07128 case SIG_EMWINK: 07129 case SIG_FEATD: 07130 case SIG_FEATDMF: 07131 case SIG_FEATDMF_TA: 07132 case SIG_E911: 07133 case SIG_FGC_CAMA: 07134 case SIG_FGC_CAMAMF: 07135 case SIG_FEATB: 07136 case SIG_EM: 07137 case SIG_EM_E1: 07138 case SIG_SFWINK: 07139 case SIG_SF_FEATD: 07140 case SIG_SF_FEATDMF: 07141 case SIG_SF_FEATB: 07142 case SIG_SF: 07143 /* Check for callerid, digits, etc */ 07144 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0); 07145 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 07146 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 07147 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07148 if (res < 0) 07149 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 07150 ast_hangup(chan); 07151 } else if (!chan) { 07152 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 07153 } 07154 break; 07155 default: 07156 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 07157 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07158 if (res < 0) 07159 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 07160 return -1; 07161 } 07162 break; 07163 case DAHDI_EVENT_NOALARM: 07164 i->inalarm = 0; 07165 if (!i->unknown_alarm) { 07166 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel); 07167 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 07168 "Channel: %d\r\n", i->channel); 07169 } else { 07170 i->unknown_alarm = 0; 07171 } 07172 break; 07173 case DAHDI_EVENT_ALARM: 07174 i->inalarm = 1; 07175 res = get_alarms(i); 07176 handle_alarms(i, res); 07177 /* fall thru intentionally */ 07178 case DAHDI_EVENT_ONHOOK: 07179 if (i->radio) 07180 break; 07181 /* Back on hook. Hang up. */ 07182 switch (i->sig) { 07183 case SIG_FXOLS: 07184 case SIG_FXOGS: 07185 case SIG_FEATD: 07186 case SIG_FEATDMF: 07187 case SIG_FEATDMF_TA: 07188 case SIG_E911: 07189 case SIG_FGC_CAMA: 07190 case SIG_FGC_CAMAMF: 07191 case SIG_FEATB: 07192 case SIG_EM: 07193 case SIG_EM_E1: 07194 case SIG_EMWINK: 07195 case SIG_SF_FEATD: 07196 case SIG_SF_FEATDMF: 07197 case SIG_SF_FEATB: 07198 case SIG_SF: 07199 case SIG_SFWINK: 07200 case SIG_FXSLS: 07201 case SIG_FXSGS: 07202 case SIG_FXSKS: 07203 case SIG_GR303FXSKS: 07204 dahdi_disable_ec(i); 07205 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 07206 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 07207 break; 07208 case SIG_GR303FXOKS: 07209 case SIG_FXOKS: 07210 dahdi_disable_ec(i); 07211 /* Diddle the battery for the zhone */ 07212 #ifdef ZHONE_HACK 07213 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07214 usleep(1); 07215 #endif 07216 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 07217 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 07218 break; 07219 case SIG_PRI: 07220 dahdi_disable_ec(i); 07221 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 07222 break; 07223 default: 07224 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 07225 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 07226 return -1; 07227 } 07228 break; 07229 case DAHDI_EVENT_POLARITY: 07230 switch (i->sig) { 07231 case SIG_FXSLS: 07232 case SIG_FXSKS: 07233 case SIG_FXSGS: 07234 /* We have already got a PR before the channel was 07235 created, but it wasn't handled. We need polarity 07236 to be REV for remote hangup detection to work. 07237 At least in Spain */ 07238 if (i->hanguponpolarityswitch) 07239 i->polarity = POLARITY_REV; 07240 07241 if (i->cid_start == CID_START_POLARITY) { 07242 i->polarity = POLARITY_REV; 07243 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity " 07244 "CID detection on channel %d\n", 07245 i->channel); 07246 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 07247 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 07248 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 07249 } 07250 } 07251 break; 07252 default: 07253 ast_log(LOG_WARNING, "handle_init_event detected " 07254 "polarity reversal on non-FXO (SIG_FXS) " 07255 "interface %d\n", i->channel); 07256 } 07257 break; 07258 case DAHDI_EVENT_REMOVED: /* destroy channel */ 07259 ast_log(LOG_NOTICE, 07260 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 07261 i->channel); 07262 dahdi_destroy_channel_bynum(i->channel); 07263 break; 07264 } 07265 pthread_attr_destroy(&attr); 07266 return 0; 07267 }
static int handle_pri_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10140 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
10141 { 10142 int span; 10143 int x; 10144 if (argc < 4) { 10145 return RESULT_SHOWUSAGE; 10146 } 10147 span = atoi(argv[3]); 10148 if ((span < 1) || (span > NUM_SPANS)) { 10149 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS); 10150 return RESULT_SUCCESS; 10151 } 10152 if (!pris[span-1].pri) { 10153 ast_cli(fd, "No PRI running on span %d\n", span); 10154 return RESULT_SUCCESS; 10155 } 10156 for (x = 0; x < NUM_DCHANS; x++) { 10157 if (pris[span-1].dchans[x]) 10158 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 10159 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 10160 PRI_DEBUG_Q921_STATE); 10161 } 10162 ast_cli(fd, "Enabled debugging on span %d\n", span); 10163 return RESULT_SUCCESS; 10164 }
static int handle_pri_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10168 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
10169 { 10170 int span; 10171 int x; 10172 if (argc < 5) 10173 return RESULT_SHOWUSAGE; 10174 span = atoi(argv[4]); 10175 if ((span < 1) || (span > NUM_SPANS)) { 10176 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS); 10177 return RESULT_SUCCESS; 10178 } 10179 if (!pris[span-1].pri) { 10180 ast_cli(fd, "No PRI running on span %d\n", span); 10181 return RESULT_SUCCESS; 10182 } 10183 for (x = 0; x < NUM_DCHANS; x++) { 10184 if (pris[span-1].dchans[x]) 10185 pri_set_debug(pris[span-1].dchans[x], 0); 10186 } 10187 ast_cli(fd, "Disabled debugging on span %d\n", span); 10188 return RESULT_SUCCESS; 10189 }
static int handle_pri_really_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10191 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
10192 { 10193 int span; 10194 int x; 10195 if (argc < 5) 10196 return RESULT_SHOWUSAGE; 10197 span = atoi(argv[4]); 10198 if ((span < 1) || (span > NUM_SPANS)) { 10199 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS); 10200 return RESULT_SUCCESS; 10201 } 10202 if (!pris[span-1].pri) { 10203 ast_cli(fd, "No PRI running on span %d\n", span); 10204 return RESULT_SUCCESS; 10205 } 10206 for (x = 0; x < NUM_DCHANS; x++) { 10207 if (pris[span-1].dchans[x]) 10208 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 10209 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 10210 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE); 10211 } 10212 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span); 10213 return RESULT_SUCCESS; 10214 }
static int handle_pri_set_debug_file | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 10093 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.
10094 { 10095 int myfd; 10096 10097 if (!strncasecmp(argv[1], "set", 3)) { 10098 if (argc < 5) 10099 return RESULT_SHOWUSAGE; 10100 10101 if (ast_strlen_zero(argv[4])) 10102 return RESULT_SHOWUSAGE; 10103 10104 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600); 10105 if (myfd < 0) { 10106 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]); 10107 return RESULT_SUCCESS; 10108 } 10109 10110 ast_mutex_lock(&pridebugfdlock); 10111 10112 if (pridebugfd >= 0) 10113 close(pridebugfd); 10114 10115 pridebugfd = myfd; 10116 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename)); 10117 10118 ast_mutex_unlock(&pridebugfdlock); 10119 10120 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]); 10121 } else { 10122 /* Assume it is unset */ 10123 ast_mutex_lock(&pridebugfdlock); 10124 close(pridebugfd); 10125 pridebugfd = -1; 10126 ast_cli(fd, "PRI debug output to file disabled\n"); 10127 ast_mutex_unlock(&pridebugfdlock); 10128 } 10129 10130 return RESULT_SUCCESS; 10131 }
static int handle_pri_show_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10297 of file chan_dahdi.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), debug, NUM_SPANS, pridebugfdlock, pris, and RESULT_SUCCESS.
10298 { 10299 int x; 10300 int span; 10301 int count=0; 10302 int debug=0; 10303 10304 for (span = 0; span < NUM_SPANS; span++) { 10305 if (pris[span].pri) { 10306 for (x = 0; x < NUM_DCHANS; x++) { 10307 debug = 0; 10308 if (pris[span].dchans[x]) { 10309 debug = pri_get_debug(pris[span].dchans[x]); 10310 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" ); 10311 count++; 10312 } 10313 } 10314 } 10315 10316 } 10317 ast_mutex_lock(&pridebugfdlock); 10318 if (pridebugfd >= 0) 10319 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename); 10320 ast_mutex_unlock(&pridebugfdlock); 10321 10322 if (!count) 10323 ast_cli(fd, "No debug set or no PRI running\n"); 10324 return RESULT_SUCCESS; 10325 }
static int handle_pri_show_span | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10258 of file chan_dahdi.c.
References ast_cli(), build_status(), free, NUM_SPANS, pri_order(), pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
10259 { 10260 int span; 10261 int x; 10262 char status[256]; 10263 if (argc < 4) 10264 return RESULT_SHOWUSAGE; 10265 span = atoi(argv[3]); 10266 if ((span < 1) || (span > NUM_SPANS)) { 10267 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS); 10268 return RESULT_SUCCESS; 10269 } 10270 if (!pris[span-1].pri) { 10271 ast_cli(fd, "No PRI running on span %d\n", span); 10272 return RESULT_SUCCESS; 10273 } 10274 for (x = 0; x < NUM_DCHANS; x++) { 10275 if (pris[span-1].dchannels[x]) { 10276 #ifdef PRI_DUMP_INFO_STR 10277 char *info_str = NULL; 10278 #endif 10279 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]); 10280 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri); 10281 ast_cli(fd, "Status: %s\n", status); 10282 #ifdef PRI_DUMP_INFO_STR 10283 info_str = pri_dump_info_str(pris[span-1].pri); 10284 if (info_str) { 10285 ast_cli(fd, "%s", info_str); 10286 free(info_str); 10287 } 10288 #else 10289 pri_dump_info(pris[span-1].pri); 10290 #endif 10291 ast_cli(fd, "\n"); 10292 } 10293 } 10294 return RESULT_SUCCESS; 10295 }
static int handle_pri_show_spans | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10237 of file chan_dahdi.c.
References ast_cli(), build_status(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
10238 { 10239 int span; 10240 int x; 10241 char status[256]; 10242 if (argc != 3) 10243 return RESULT_SHOWUSAGE; 10244 10245 for (span = 0; span < NUM_SPANS; span++) { 10246 if (pris[span].pri) { 10247 for (x = 0; x < NUM_DCHANS; x++) { 10248 if (pris[span].dchannels[x]) { 10249 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri); 10250 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status); 10251 } 10252 } 10253 } 10254 } 10255 return RESULT_SUCCESS; 10256 }
static int handle_pri_version | ( | int | fd, | |
int | agc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10134 of file chan_dahdi.c.
References ast_cli(), and RESULT_SUCCESS.
10134 { 10135 ast_cli(fd, "libpri version: %s\n", pri_get_version()); 10136 return RESULT_SUCCESS; 10137 }
static int has_voicemail | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2069 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().
02070 { 02071 02072 return ast_app_has_voicemail(p->mailbox, NULL); 02073 }
static int isourconf | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c | |||
) | [static] |
Definition at line 1625 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::confno, and dahdi_subchannel::curconf.
Referenced by conf_del().
01626 { 01627 /* If they're listening to our channel, they're ours */ 01628 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON)) 01629 return 1; 01630 /* If they're a talker on our (allocated) conference, they're ours */ 01631 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER)) 01632 return 1; 01633 return 0; 01634 }
Definition at line 1658 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().
01659 { 01660 int x; 01661 int useslavenative; 01662 struct dahdi_pvt *slave = NULL; 01663 /* Start out optimistic */ 01664 useslavenative = 1; 01665 /* Update conference state in a stateless fashion */ 01666 for (x = 0; x < 3; x++) { 01667 /* Any three-way calling makes slave native mode *definitely* out 01668 of the question */ 01669 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) 01670 useslavenative = 0; 01671 } 01672 /* If we don't have any 3-way calls, check to see if we have 01673 precisely one slave */ 01674 if (useslavenative) { 01675 for (x = 0; x < MAX_SLAVES; x++) { 01676 if (p->slaves[x]) { 01677 if (slave) { 01678 /* Whoops already have a slave! No 01679 slave native and stop right away */ 01680 slave = NULL; 01681 useslavenative = 0; 01682 break; 01683 } else { 01684 /* We have one slave so far */ 01685 slave = p->slaves[x]; 01686 } 01687 } 01688 } 01689 } 01690 /* If no slave, slave native definitely out */ 01691 if (!slave) 01692 useslavenative = 0; 01693 else if (slave->law != p->law) { 01694 useslavenative = 0; 01695 slave = NULL; 01696 } 01697 if (out) 01698 *out = slave; 01699 return useslavenative; 01700 }
static int load_module | ( | void | ) | [static] |
Definition at line 12183 of file chan_dahdi.c.
References __unload_module(), ast_channel_register(), ast_cli_register_multiple(), ast_cond_init(), ast_log(), AST_MODULE_LOAD_DECLINE, ast_mutex_init(), AST_PTHREADT_NULL, ast_register_application(), ast_string_field_init, ast_string_field_set, CHAN_DAHDI_PLUS_ZAP_MODE, chan_tech, dahdi_chan_mode, dahdi_cli, dahdi_pri_cli, dahdi_pri_error(), dahdi_pri_message(), dahdi_send_keypad_facility_exec(), dahdi_tech, inuse, local_astman_register, lock, LOG_ERROR, name, NUM_SPANS, pris, round_robin, setup_dahdi(), ast_channel_tech::type, zap_send_keypad_facility_exec(), and zap_tech.
12184 { 12185 int res; 12186 12187 #ifdef HAVE_PRI 12188 int y,i; 12189 memset(pris, 0, sizeof(pris)); 12190 for (y = 0; y < NUM_SPANS; y++) { 12191 ast_mutex_init(&pris[y].lock); 12192 pris[y].offset = -1; 12193 pris[y].master = AST_PTHREADT_NULL; 12194 for (i = 0; i < NUM_DCHANS; i++) 12195 pris[y].fds[i] = -1; 12196 } 12197 pri_set_error(dahdi_pri_error); 12198 pri_set_message(dahdi_pri_message); 12199 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 12200 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec, 12201 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip); 12202 } 12203 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec, 12204 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip); 12205 #endif 12206 if ((res = setup_dahdi(0))) { 12207 return AST_MODULE_LOAD_DECLINE; 12208 } 12209 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 12210 chan_tech = &dahdi_tech; 12211 } else { 12212 chan_tech = &zap_tech; 12213 } 12214 if (ast_channel_register(chan_tech)) { 12215 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type); 12216 __unload_module(); 12217 return -1; 12218 } 12219 #ifdef HAVE_PRI 12220 ast_string_field_init(&inuse, 16); 12221 ast_string_field_set(&inuse, name, "GR-303InUse"); 12222 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry)); 12223 #endif 12224 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 12225 12226 memset(round_robin, 0, sizeof(round_robin)); 12227 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel"); 12228 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel"); 12229 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook"); 12230 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON"); 12231 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF"); 12232 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels"); 12233 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)"); 12234 12235 ast_cond_init(&ss_thread_complete, NULL); 12236 12237 return res; 12238 }
static struct dahdi_pvt* mkintf | ( | int | channel, | |
const struct dahdi_chan_conf * | conf, | |||
struct dahdi_pri * | pri, | |||
int | reloading | |||
) | [static] |
Definition at line 7615 of file chan_dahdi.c.
References ast_calloc, ast_copy_string(), ast_log(), ast_mutex_init(), ast_strlen_zero(), dahdi_chan_conf::chan, CHAN_PSEUDO, dahdi_pri::crvend, dahdi_pri::crvs, dahdi_open(), destroy_dahdi_pvt(), dahdi_pri::dialplan, dialplan2str(), errno, dahdi_pri::facilityenable, free, dahdi_pri::idledial, dahdi_pri::idleext, iflist, dahdi_pri::inbanddisconnect, dahdi_pri::internationalprefix, dahdi_pri::localdialplan, dahdi_pri::localprefix, LOG_ERROR, MAX_CHANNELS, dahdi_pri::minidle, dahdi_pri::minunused, dahdi_pri::nationalprefix, dahdi_pvt::next, dahdi_pri::nodetype, dahdi_pri::nsf, NUM_DCHANS, NUM_SPANS, dahdi_pri::numchans, offset, dahdi_pri::overlapdial, dahdi_pvt::prev, dahdi_chan_conf::pri, pri_resolve_span(), dahdi_pri::prilogicalspan, pris, dahdi_pri::privateprefix, dahdi_pri::pvts, dahdi_pri::resetinterval, dahdi_pvt::sig, sig2str, SIG_FXOKS, SIG_FXSKS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SUB_REAL, dahdi_pri::switchtype, and dahdi_pri::unknownprefix.
Referenced by build_channels().
07616 { 07617 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */ 07618 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL; 07619 char fn[80]; 07620 #if 1 07621 struct dahdi_bufferinfo bi; 07622 #endif 07623 int res; 07624 int span=0; 07625 int here = 0; 07626 int x; 07627 struct dahdi_pvt **wlist; 07628 struct dahdi_pvt **wend; 07629 struct dahdi_params p; 07630 07631 wlist = &iflist; 07632 wend = &ifend; 07633 07634 #ifdef HAVE_PRI 07635 if (pri) { 07636 wlist = &pri->crvs; 07637 wend = &pri->crvend; 07638 } 07639 #endif 07640 07641 tmp2 = *wlist; 07642 prev = NULL; 07643 07644 while (tmp2) { 07645 if (!tmp2->destroy) { 07646 if (tmp2->channel == channel) { 07647 tmp = tmp2; 07648 here = 1; 07649 break; 07650 } 07651 if (tmp2->channel > channel) { 07652 break; 07653 } 07654 } 07655 prev = tmp2; 07656 tmp2 = tmp2->next; 07657 } 07658 07659 if (!here && reloading != 1) { 07660 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { 07661 if (tmp) 07662 free(tmp); 07663 return NULL; 07664 } 07665 ast_mutex_init(&tmp->lock); 07666 ifcount++; 07667 for (x = 0; x < 3; x++) 07668 tmp->subs[x].dfd = -1; 07669 tmp->channel = channel; 07670 } 07671 07672 if (tmp) { 07673 int chan_sig = conf->chan.sig; 07674 if (!here) { 07675 if ((channel != CHAN_PSEUDO) && !pri) { 07676 int count = 0; 07677 snprintf(fn, sizeof(fn), "%d", channel); 07678 /* Open non-blocking */ 07679 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 07680 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 */ 07681 usleep(1); 07682 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 07683 count++; 07684 } 07685 /* Allocate a DAHDI structure */ 07686 if (tmp->subs[SUB_REAL].dfd < 0) { 07687 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); 07688 destroy_dahdi_pvt(&tmp); 07689 return NULL; 07690 } 07691 memset(&p, 0, sizeof(p)); 07692 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 07693 if (res < 0) { 07694 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno)); 07695 destroy_dahdi_pvt(&tmp); 07696 return NULL; 07697 } 07698 if (p.sigtype != (conf->chan.sig & 0x3ffff)) { 07699 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)); 07700 destroy_dahdi_pvt(&tmp); 07701 return NULL; 07702 } 07703 tmp->law = p.curlaw; 07704 tmp->span = p.spanno; 07705 span = p.spanno - 1; 07706 } else { 07707 if (channel == CHAN_PSEUDO) 07708 chan_sig = 0; 07709 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) { 07710 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n"); 07711 return NULL; 07712 } 07713 } 07714 #ifdef HAVE_PRI 07715 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) { 07716 int offset; 07717 int myswitchtype; 07718 int matchesdchan; 07719 int x,y; 07720 offset = 0; 07721 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) { 07722 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 07723 destroy_dahdi_pvt(&tmp); 07724 return NULL; 07725 } 07726 if (span >= NUM_SPANS) { 07727 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span); 07728 destroy_dahdi_pvt(&tmp); 07729 return NULL; 07730 } else { 07731 struct dahdi_spaninfo si; 07732 si.spanno = 0; 07733 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) { 07734 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); 07735 destroy_dahdi_pvt(&tmp); 07736 return NULL; 07737 } 07738 /* Store the logical span first based upon the real span */ 07739 tmp->logicalspan = pris[span].prilogicalspan; 07740 pri_resolve_span(&span, channel, (channel - p.chanpos), &si); 07741 if (span < 0) { 07742 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel); 07743 destroy_dahdi_pvt(&tmp); 07744 return NULL; 07745 } 07746 if (chan_sig == SIG_PRI) 07747 myswitchtype = conf->pri.switchtype; 07748 else 07749 myswitchtype = PRI_SWITCH_GR303_TMC; 07750 /* Make sure this isn't a d-channel */ 07751 matchesdchan=0; 07752 for (x = 0; x < NUM_SPANS; x++) { 07753 for (y = 0; y < NUM_DCHANS; y++) { 07754 if (pris[x].dchannels[y] == tmp->channel) { 07755 matchesdchan = 1; 07756 break; 07757 } 07758 } 07759 } 07760 offset = p.chanpos; 07761 if (!matchesdchan) { 07762 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) { 07763 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype)); 07764 destroy_dahdi_pvt(&tmp); 07765 return NULL; 07766 } 07767 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) { 07768 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype)); 07769 destroy_dahdi_pvt(&tmp); 07770 return NULL; 07771 } 07772 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) { 07773 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan)); 07774 destroy_dahdi_pvt(&tmp); 07775 return NULL; 07776 } 07777 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) { 07778 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial); 07779 destroy_dahdi_pvt(&tmp); 07780 return NULL; 07781 } 07782 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) { 07783 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext); 07784 destroy_dahdi_pvt(&tmp); 07785 return NULL; 07786 } 07787 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) { 07788 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused); 07789 destroy_dahdi_pvt(&tmp); 07790 return NULL; 07791 } 07792 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) { 07793 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle); 07794 destroy_dahdi_pvt(&tmp); 07795 return NULL; 07796 } 07797 if (pris[span].numchans >= MAX_CHANNELS) { 07798 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, 07799 pris[span].trunkgroup); 07800 destroy_dahdi_pvt(&tmp); 07801 return NULL; 07802 } 07803 pris[span].nodetype = conf->pri.nodetype; 07804 pris[span].switchtype = myswitchtype; 07805 pris[span].nsf = conf->pri.nsf; 07806 pris[span].dialplan = conf->pri.dialplan; 07807 pris[span].localdialplan = conf->pri.localdialplan; 07808 pris[span].pvts[pris[span].numchans++] = tmp; 07809 pris[span].minunused = conf->pri.minunused; 07810 pris[span].minidle = conf->pri.minidle; 07811 pris[span].overlapdial = conf->pri.overlapdial; 07812 #ifdef HAVE_PRI_INBANDDISCONNECT 07813 pris[span].inbanddisconnect = conf->pri.inbanddisconnect; 07814 #endif 07815 pris[span].facilityenable = conf->pri.facilityenable; 07816 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial)); 07817 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext)); 07818 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix)); 07819 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix)); 07820 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix)); 07821 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix)); 07822 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix)); 07823 pris[span].resetinterval = conf->pri.resetinterval; 07824 07825 tmp->pri = &pris[span]; 07826 tmp->prioffset = offset; 07827 tmp->call = NULL; 07828 } else { 07829 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset); 07830 destroy_dahdi_pvt(&tmp); 07831 return NULL; 07832 } 07833 } 07834 } else { 07835 tmp->prioffset = 0; 07836 } 07837 #endif 07838 } else { 07839 chan_sig = tmp->sig; 07840 memset(&p, 0, sizeof(p)); 07841 if (tmp->subs[SUB_REAL].dfd > -1) 07842 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 07843 } 07844 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */ 07845 switch (chan_sig) { 07846 case SIG_FXSKS: 07847 case SIG_FXSLS: 07848 case SIG_EM: 07849 case SIG_EM_E1: 07850 case SIG_EMWINK: 07851 case SIG_FEATD: 07852 case SIG_FEATDMF: 07853 case SIG_FEATDMF_TA: 07854 case SIG_FEATB: 07855 case SIG_E911: 07856 case SIG_SF: 07857 case SIG_SFWINK: 07858 case SIG_FGC_CAMA: 07859 case SIG_FGC_CAMAMF: 07860 case SIG_SF_FEATD: 07861 case SIG_SF_FEATDMF: 07862 case SIG_SF_FEATB: 07863 p.starttime = 250; 07864 break; 07865 } 07866 07867 if (tmp->radio) { 07868 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */ 07869 p.channo = channel; 07870 p.rxwinktime = 1; 07871 p.rxflashtime = 1; 07872 p.starttime = 1; 07873 p.debouncetime = 5; 07874 } 07875 if (!tmp->radio) { 07876 p.channo = channel; 07877 /* Override timing settings based on config file */ 07878 if (conf->timing.prewinktime >= 0) 07879 p.prewinktime = conf->timing.prewinktime; 07880 if (conf->timing.preflashtime >= 0) 07881 p.preflashtime = conf->timing.preflashtime; 07882 if (conf->timing.winktime >= 0) 07883 p.winktime = conf->timing.winktime; 07884 if (conf->timing.flashtime >= 0) 07885 p.flashtime = conf->timing.flashtime; 07886 if (conf->timing.starttime >= 0) 07887 p.starttime = conf->timing.starttime; 07888 if (conf->timing.rxwinktime >= 0) 07889 p.rxwinktime = conf->timing.rxwinktime; 07890 if (conf->timing.rxflashtime >= 0) 07891 p.rxflashtime = conf->timing.rxflashtime; 07892 if (conf->timing.debouncetime >= 0) 07893 p.debouncetime = conf->timing.debouncetime; 07894 } 07895 07896 /* dont set parms on a pseudo-channel (or CRV) */ 07897 if (tmp->subs[SUB_REAL].dfd >= 0) 07898 { 07899 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p); 07900 if (res < 0) { 07901 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno)); 07902 destroy_dahdi_pvt(&tmp); 07903 return NULL; 07904 } 07905 } 07906 #if 1 07907 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) { 07908 memset(&bi, 0, sizeof(bi)); 07909 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 07910 if (!res) { 07911 bi.txbufpolicy = conf->chan.buf_policy; 07912 bi.rxbufpolicy = conf->chan.buf_policy; 07913 bi.numbufs = conf->chan.buf_no; 07914 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 07915 if (res < 0) { 07916 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno)); 07917 } 07918 } else 07919 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno)); 07920 } 07921 #endif 07922 tmp->immediate = conf->chan.immediate; 07923 tmp->transfertobusy = conf->chan.transfertobusy; 07924 tmp->sig = chan_sig; 07925 tmp->outsigmod = conf->chan.outsigmod; 07926 tmp->ringt_base = ringt_base; 07927 tmp->firstradio = 0; 07928 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS)) 07929 tmp->permcallwaiting = conf->chan.callwaiting; 07930 else 07931 tmp->permcallwaiting = 0; 07932 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */ 07933 tmp->destroy = 0; 07934 tmp->drings = drings; 07935 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection; 07936 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid; 07937 tmp->threewaycalling = conf->chan.threewaycalling; 07938 tmp->adsi = conf->chan.adsi; 07939 tmp->use_smdi = conf->chan.use_smdi; 07940 tmp->permhidecallerid = conf->chan.hidecallerid; 07941 tmp->callreturn = conf->chan.callreturn; 07942 tmp->echocancel = conf->chan.echocancel; 07943 tmp->echotraining = conf->chan.echotraining; 07944 tmp->pulse = conf->chan.pulse; 07945 if (tmp->echocancel) 07946 tmp->echocanbridged = conf->chan.echocanbridged; 07947 else { 07948 if (conf->chan.echocanbridged) 07949 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n"); 07950 tmp->echocanbridged = 0; 07951 } 07952 tmp->busydetect = conf->chan.busydetect; 07953 tmp->busycount = conf->chan.busycount; 07954 tmp->busycompare = conf->chan.busycompare; 07955 tmp->busytonelength = conf->chan.busytonelength; 07956 tmp->busyquietlength = conf->chan.busyquietlength; 07957 tmp->busyfuzziness = conf->chan.busyfuzziness; 07958 tmp->silencethreshold = conf->chan.silencethreshold; 07959 tmp->callprogress = conf->chan.callprogress; 07960 tmp->cancallforward = conf->chan.cancallforward; 07961 tmp->dtmfrelax = conf->chan.dtmfrelax; 07962 tmp->callwaiting = tmp->permcallwaiting; 07963 tmp->hidecallerid = tmp->permhidecallerid; 07964 tmp->channel = channel; 07965 tmp->stripmsd = conf->chan.stripmsd; 07966 tmp->use_callerid = conf->chan.use_callerid; 07967 tmp->cid_signalling = conf->chan.cid_signalling; 07968 tmp->cid_start = conf->chan.cid_start; 07969 tmp->dahditrcallerid = conf->chan.dahditrcallerid; 07970 tmp->restrictcid = conf->chan.restrictcid; 07971 tmp->use_callingpres = conf->chan.use_callingpres; 07972 tmp->priindication_oob = conf->chan.priindication_oob; 07973 tmp->priexclusive = conf->chan.priexclusive; 07974 if (tmp->usedistinctiveringdetection) { 07975 if (!tmp->use_callerid) { 07976 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n"); 07977 tmp->use_callerid = 1; 07978 } 07979 } 07980 07981 if (tmp->cid_signalling == CID_SIG_SMDI) { 07982 if (!tmp->use_smdi) { 07983 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n"); 07984 tmp->use_smdi = 1; 07985 } 07986 } 07987 if (tmp->use_smdi) { 07988 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port); 07989 if (!(tmp->smdi_iface)) { 07990 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n"); 07991 tmp->use_smdi = 0; 07992 } 07993 } 07994 07995 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode)); 07996 tmp->amaflags = conf->chan.amaflags; 07997 if (!here) { 07998 tmp->confno = -1; 07999 tmp->propconfno = -1; 08000 } 08001 tmp->canpark = conf->chan.canpark; 08002 tmp->transfer = conf->chan.transfer; 08003 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext)); 08004 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language)); 08005 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret)); 08006 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest)); 08007 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context)); 08008 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num)); 08009 tmp->cid_ton = 0; 08010 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name)); 08011 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox)); 08012 tmp->msgstate = -1; 08013 tmp->group = conf->chan.group; 08014 tmp->callgroup = conf->chan.callgroup; 08015 tmp->pickupgroup= conf->chan.pickupgroup; 08016 tmp->rxgain = conf->chan.rxgain; 08017 tmp->txgain = conf->chan.txgain; 08018 tmp->tonezone = conf->chan.tonezone; 08019 tmp->onhooktime = time(NULL); 08020 if (tmp->subs[SUB_REAL].dfd > -1) { 08021 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law); 08022 if (tmp->dsp) 08023 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax); 08024 update_conf(tmp); 08025 if (!here) { 08026 if (chan_sig != SIG_PRI) 08027 /* Hang it up to be sure it's good */ 08028 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08029 } 08030 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone); 08031 #ifdef HAVE_PRI 08032 /* the dchannel is down so put the channel in alarm */ 08033 if (tmp->pri && !pri_is_up(tmp->pri)) { 08034 tmp->inalarm = 1; 08035 } 08036 #endif 08037 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) { 08038 tmp->inalarm = 1; 08039 handle_alarms(tmp, res); 08040 } else { 08041 /* yes, this looks strange... the unknown_alarm flag is only used to 08042 control whether an 'alarm cleared' message gets generated when we 08043 get an indication that the channel is no longer in alarm status. 08044 however, the channel *could* be in an alarm status that we aren't 08045 aware of (since get_alarms() only reports span alarms, not channel 08046 alarms). setting this flag will cause any potential 'alarm cleared' 08047 message to be suppressed, but if a real alarm occurs before that 08048 happens, this flag will get cleared by it and the situation will 08049 be normal. 08050 */ 08051 tmp->unknown_alarm = 1; 08052 } 08053 } 08054 08055 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 08056 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 08057 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 08058 tmp->sendcalleridafter = conf->chan.sendcalleridafter; 08059 08060 } 08061 if (tmp && !here) { 08062 /* nothing on the iflist */ 08063 if (!*wlist) { 08064 *wlist = tmp; 08065 tmp->prev = NULL; 08066 tmp->next = NULL; 08067 *wend = tmp; 08068 } else { 08069 /* at least one member on the iflist */ 08070 struct dahdi_pvt *working = *wlist; 08071 08072 /* check if we maybe have to put it on the begining */ 08073 if (working->channel > tmp->channel) { 08074 tmp->next = *wlist; 08075 tmp->prev = NULL; 08076 (*wlist)->prev = tmp; 08077 *wlist = tmp; 08078 } else { 08079 /* go through all the members and put the member in the right place */ 08080 while (working) { 08081 /* in the middle */ 08082 if (working->next) { 08083 if (working->channel < tmp->channel && working->next->channel > tmp->channel) { 08084 tmp->next = working->next; 08085 tmp->prev = working; 08086 working->next->prev = tmp; 08087 working->next = tmp; 08088 break; 08089 } 08090 } else { 08091 /* the last */ 08092 if (working->channel < tmp->channel) { 08093 working->next = tmp; 08094 tmp->next = NULL; 08095 tmp->prev = working; 08096 *wend = tmp; 08097 break; 08098 } 08099 } 08100 working = working->next; 08101 } 08102 } 08103 } 08104 } 08105 return tmp; 08106 }
static int my_dahdi_write | ( | struct dahdi_pvt * | p, | |
unsigned char * | buf, | |||
int | len, | |||
int | index, | |||
int | linear | |||
) | [static] |
Definition at line 5367 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().
05368 { 05369 int sent=0; 05370 int size; 05371 int res; 05372 int fd; 05373 fd = p->subs[index].dfd; 05374 while (len) { 05375 size = len; 05376 if (size > (linear ? READ_SIZE * 2 : READ_SIZE)) 05377 size = (linear ? READ_SIZE * 2 : READ_SIZE); 05378 res = write(fd, buf, size); 05379 if (res != size) { 05380 if (option_debug) 05381 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 05382 return sent; 05383 } 05384 len -= size; 05385 buf += size; 05386 } 05387 return sent; 05388 }
static int my_getsigstr | ( | struct ast_channel * | chan, | |
char * | str, | |||
const char * | term, | |||
int | ms | |||
) | [static] |
Definition at line 5844 of file chan_dahdi.c.
References ast_waitfordigit().
Referenced by ss_thread().
05845 { 05846 char c; 05847 05848 *str = 0; /* start with empty output buffer */ 05849 for (;;) 05850 { 05851 /* Wait for the first digit (up to specified ms). */ 05852 c = ast_waitfordigit(chan, ms); 05853 /* if timeout, hangup or error, return as such */ 05854 if (c < 1) 05855 return c; 05856 *str++ = c; 05857 *str = 0; 05858 if (strchr(term, c)) 05859 return 1; 05860 } 05861 }
static int pri_active_dchan_fd | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 2781 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().
02782 { 02783 int x = -1; 02784 02785 for (x = 0; x < NUM_DCHANS; x++) { 02786 if ((pri->dchans[x] == pri->pri)) 02787 break; 02788 } 02789 02790 return pri->fds[x]; 02791 }
static int pri_assign_bearer | ( | struct dahdi_pvt * | crv, | |
struct dahdi_pri * | pri, | |||
struct dahdi_pvt * | bearer | |||
) | [static] |
Definition at line 2751 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().
02752 { 02753 bearer->owner = &inuse; 02754 bearer->realcall = crv; 02755 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd; 02756 if (crv->subs[SUB_REAL].owner) 02757 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd; 02758 crv->bearer = bearer; 02759 crv->call = bearer->call; 02760 crv->pri = pri; 02761 return 0; 02762 }
static int pri_check_restart | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 8780 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().
08781 { 08782 do { 08783 pri->resetpos++; 08784 } while ((pri->resetpos < pri->numchans) && 08785 (!pri->pvts[pri->resetpos] || 08786 pri->pvts[pri->resetpos]->call || 08787 pri->pvts[pri->resetpos]->resetting)); 08788 if (pri->resetpos < pri->numchans) { 08789 /* Mark the channel as resetting and restart it */ 08790 pri->pvts[pri->resetpos]->resetting = 1; 08791 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos])); 08792 } else { 08793 pri->resetting = 0; 08794 time(&pri->lastreset); 08795 } 08796 return 0; 08797 }
static int pri_create_spanmap | ( | int | span, | |
int | trunkgroup, | |||
int | logicalspan | |||
) | [static] |
Definition at line 7602 of file chan_dahdi.c.
References ast_log(), dahdi_pri::mastertrunkgroup, dahdi_pri::prilogicalspan, and pris.
Referenced by setup_dahdi().
07603 { 07604 if (pris[span].mastertrunkgroup) { 07605 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); 07606 return -1; 07607 } 07608 pris[span].mastertrunkgroup = trunkgroup; 07609 pris[span].prilogicalspan = logicalspan; 07610 return 0; 07611 }
static int pri_create_trunkgroup | ( | int | trunkgroup, | |
int * | channels | |||
) | [static] |
Definition at line 7539 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().
07540 { 07541 struct dahdi_spaninfo si; 07542 struct dahdi_params p; 07543 int fd; 07544 int span; 07545 int ospan=0; 07546 int x,y; 07547 for (x = 0; x < NUM_SPANS; x++) { 07548 if (pris[x].trunkgroup == trunkgroup) { 07549 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]); 07550 return -1; 07551 } 07552 } 07553 for (y = 0; y < NUM_DCHANS; y++) { 07554 if (!channels[y]) 07555 break; 07556 memset(&si, 0, sizeof(si)); 07557 memset(&p, 0, sizeof(p)); 07558 fd = open(DAHDI_FILE_CHANNEL, O_RDWR); 07559 if (fd < 0) { 07560 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno)); 07561 return -1; 07562 } 07563 x = channels[y]; 07564 if (ioctl(fd, DAHDI_SPECIFY, &x)) { 07565 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno)); 07566 close(fd); 07567 return -1; 07568 } 07569 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) { 07570 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno)); 07571 return -1; 07572 } 07573 if (ioctl(fd, DAHDI_SPANSTAT, &si)) { 07574 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno)); 07575 close(fd); 07576 return -1; 07577 } 07578 span = p.spanno - 1; 07579 if (pris[span].trunkgroup) { 07580 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup); 07581 close(fd); 07582 return -1; 07583 } 07584 if (pris[span].pvts[0]) { 07585 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1); 07586 close(fd); 07587 return -1; 07588 } 07589 if (!y) { 07590 pris[span].trunkgroup = trunkgroup; 07591 pris[span].offset = channels[y] - p.chanpos; 07592 ospan = span; 07593 } 07594 pris[ospan].dchannels[y] = channels[y]; 07595 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED; 07596 pris[span].span = span + 1; 07597 close(fd); 07598 } 07599 return 0; 07600 }
static void* pri_dchannel | ( | void * | vpri | ) | [static] |
Definition at line 8872 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(), pollfd::events, pollfd::fd, 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, NUM_DCHANS, 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, pollfd::revents, dahdi_pri::switchtype, and t.
08873 { 08874 struct dahdi_pri *pri = vpri; 08875 pri_event *e; 08876 struct pollfd fds[NUM_DCHANS]; 08877 int res; 08878 int chanpos = 0; 08879 int x; 08880 int haveidles; 08881 int activeidles; 08882 int nextidle = -1; 08883 struct ast_channel *c; 08884 struct timeval tv, lowest, *next; 08885 struct timeval lastidle = { 0, 0 }; 08886 int doidling=0; 08887 char *cc; 08888 char idlen[80]; 08889 struct ast_channel *idle; 08890 pthread_t p; 08891 time_t t; 08892 int i, which=-1; 08893 int numdchans; 08894 int cause=0; 08895 struct dahdi_pvt *crv; 08896 pthread_t threadid; 08897 pthread_attr_t attr; 08898 char ani2str[6]; 08899 char plancallingnum[256]; 08900 char plancallingani[256]; 08901 char calledtonstr[10]; 08902 08903 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08904 08905 gettimeofday(&lastidle, NULL); 08906 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) { 08907 /* Need to do idle dialing, check to be sure though */ 08908 cc = strchr(pri->idleext, '@'); 08909 if (cc) { 08910 *cc = '\0'; 08911 cc++; 08912 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext)); 08913 #if 0 08914 /* Extensions may not be loaded yet */ 08915 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL)) 08916 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext); 08917 else 08918 #endif 08919 doidling = 1; 08920 } else 08921 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext); 08922 } 08923 for (;;) { 08924 for (i = 0; i < NUM_DCHANS; i++) { 08925 if (!pri->dchannels[i]) 08926 break; 08927 fds[i].fd = pri->fds[i]; 08928 fds[i].events = POLLIN | POLLPRI; 08929 fds[i].revents = 0; 08930 } 08931 numdchans = i; 08932 time(&t); 08933 ast_mutex_lock(&pri->lock); 08934 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) { 08935 if (pri->resetting && pri_is_up(pri)) { 08936 if (pri->resetpos < 0) 08937 pri_check_restart(pri); 08938 } else { 08939 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) { 08940 pri->resetting = 1; 08941 pri->resetpos = -1; 08942 } 08943 } 08944 } 08945 /* Look for any idle channels if appropriate */ 08946 if (doidling && pri_is_up(pri)) { 08947 nextidle = -1; 08948 haveidles = 0; 08949 activeidles = 0; 08950 for (x = pri->numchans; x >= 0; x--) { 08951 if (pri->pvts[x] && !pri->pvts[x]->owner && 08952 !pri->pvts[x]->call) { 08953 if (haveidles < pri->minunused) { 08954 haveidles++; 08955 } else if (!pri->pvts[x]->resetting) { 08956 nextidle = x; 08957 break; 08958 } 08959 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) 08960 activeidles++; 08961 } 08962 if (nextidle > -1) { 08963 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) { 08964 /* Don't create a new idle call more than once per second */ 08965 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial); 08966 idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause); 08967 if (idle) { 08968 pri->pvts[nextidle]->isidlecall = 1; 08969 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) { 08970 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name); 08971 dahdi_hangup(idle); 08972 } 08973 } else 08974 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen); 08975 gettimeofday(&lastidle, NULL); 08976 } 08977 } else if ((haveidles < pri->minunused) && 08978 (activeidles > pri->minidle)) { 08979 /* Mark something for hangup if there is something 08980 that can be hungup */ 08981 for (x = pri->numchans; x >= 0; x--) { 08982 /* find a candidate channel */ 08983 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) { 08984 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 08985 haveidles++; 08986 /* Stop if we have enough idle channels or 08987 can't spare any more active idle ones */ 08988 if ((haveidles >= pri->minunused) || 08989 (activeidles <= pri->minidle)) 08990 break; 08991 } 08992 } 08993 } 08994 } 08995 /* Start with reasonable max */ 08996 lowest = ast_tv(60, 0); 08997 for (i = 0; i < NUM_DCHANS; i++) { 08998 /* Find lowest available d-channel */ 08999 if (!pri->dchannels[i]) 09000 break; 09001 if ((next = pri_schedule_next(pri->dchans[i]))) { 09002 /* We need relative time here */ 09003 tv = ast_tvsub(*next, ast_tvnow()); 09004 if (tv.tv_sec < 0) { 09005 tv = ast_tv(0,0); 09006 } 09007 if (doidling || pri->resetting) { 09008 if (tv.tv_sec > 1) { 09009 tv = ast_tv(1, 0); 09010 } 09011 } else { 09012 if (tv.tv_sec > 60) { 09013 tv = ast_tv(60, 0); 09014 } 09015 } 09016 } else if (doidling || pri->resetting) { 09017 /* Make sure we stop at least once per second if we're 09018 monitoring idle channels */ 09019 tv = ast_tv(1,0); 09020 } else { 09021 /* Don't poll for more than 60 seconds */ 09022 tv = ast_tv(60, 0); 09023 } 09024 if (!i || ast_tvcmp(tv, lowest) < 0) { 09025 lowest = tv; 09026 } 09027 } 09028 ast_mutex_unlock(&pri->lock); 09029 09030 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 09031 pthread_testcancel(); 09032 e = NULL; 09033 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000); 09034 pthread_testcancel(); 09035 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 09036 09037 ast_mutex_lock(&pri->lock); 09038 if (!res) { 09039 for (which = 0; which < NUM_DCHANS; which++) { 09040 if (!pri->dchans[which]) 09041 break; 09042 /* Just a timeout, run the scheduler */ 09043 e = pri_schedule_run(pri->dchans[which]); 09044 if (e) 09045 break; 09046 } 09047 } else if (res > -1) { 09048 for (which = 0; which < NUM_DCHANS; which++) { 09049 if (!pri->dchans[which]) 09050 break; 09051 if (fds[which].revents & POLLPRI) { 09052 /* Check for an event */ 09053 x = 0; 09054 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x); 09055 if (x) 09056 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); 09057 /* Keep track of alarm state */ 09058 if (x == DAHDI_EVENT_ALARM) { 09059 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP); 09060 pri_find_dchan(pri); 09061 } else if (x == DAHDI_EVENT_NOALARM) { 09062 pri->dchanavail[which] |= DCHAN_NOTINALARM; 09063 pri_restart(pri->dchans[which]); 09064 } 09065 09066 if (option_debug) 09067 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span); 09068 } else if (fds[which].revents & POLLIN) { 09069 e = pri_check_event(pri->dchans[which]); 09070 } 09071 if (e) 09072 break; 09073 } 09074 } else if (errno != EINTR) 09075 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno)); 09076 09077 if (e) { 09078 if (pri->debug) 09079 pri_dump_event(pri->dchans[which], e); 09080 09081 if (e->e != PRI_EVENT_DCHAN_DOWN) { 09082 if (!(pri->dchanavail[which] & DCHAN_UP)) { 09083 if (option_verbose > 1) 09084 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span); 09085 } 09086 pri->dchanavail[which] |= DCHAN_UP; 09087 } else { 09088 if (pri->dchanavail[which] & DCHAN_UP) { 09089 if (option_verbose > 1) 09090 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span); 09091 } 09092 pri->dchanavail[which] &= ~DCHAN_UP; 09093 } 09094 09095 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which])) 09096 /* Must be an NFAS group that has the secondary dchan active */ 09097 pri->pri = pri->dchans[which]; 09098 09099 switch (e->e) { 09100 case PRI_EVENT_DCHAN_UP: 09101 if (!pri->pri) pri_find_dchan(pri); 09102 09103 /* Note presense of D-channel */ 09104 time(&pri->lastreset); 09105 09106 /* Restart in 5 seconds */ 09107 if (pri->resetinterval > -1) { 09108 pri->lastreset -= pri->resetinterval; 09109 pri->lastreset += 5; 09110 } 09111 pri->resetting = 0; 09112 /* Take the channels from inalarm condition */ 09113 for (i = 0; i < pri->numchans; i++) 09114 if (pri->pvts[i]) { 09115 pri->pvts[i]->inalarm = 0; 09116 } 09117 break; 09118 case PRI_EVENT_DCHAN_DOWN: 09119 pri_find_dchan(pri); 09120 if (!pri_is_up(pri)) { 09121 pri->resetting = 0; 09122 /* Hangup active channels and put them in alarm mode */ 09123 for (i = 0; i < pri->numchans; i++) { 09124 struct dahdi_pvt *p = pri->pvts[i]; 09125 if (p) { 09126 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 09127 /* T309 is not enabled : hangup calls when alarm occurs */ 09128 if (p->call) { 09129 if (p->pri && p->pri->pri) { 09130 pri_hangup(p->pri->pri, p->call, -1); 09131 pri_destroycall(p->pri->pri, p->call); 09132 p->call = NULL; 09133 } else 09134 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n"); 09135 } 09136 if (p->realcall) { 09137 pri_hangup_all(p->realcall, pri); 09138 } else if (p->owner) 09139 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09140 } 09141 p->inalarm = 1; 09142 } 09143 } 09144 } 09145 break; 09146 case PRI_EVENT_RESTART: 09147 if (e->restart.channel > -1) { 09148 chanpos = pri_find_principle(pri, e->restart.channel); 09149 if (chanpos < 0) 09150 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 09151 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 09152 else { 09153 if (option_verbose > 2) 09154 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n", 09155 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 09156 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09157 if (pri->pvts[chanpos]->call) { 09158 pri_destroycall(pri->pri, pri->pvts[chanpos]->call); 09159 pri->pvts[chanpos]->call = NULL; 09160 } 09161 /* Force soft hangup if appropriate */ 09162 if (pri->pvts[chanpos]->realcall) 09163 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 09164 else if (pri->pvts[chanpos]->owner) 09165 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09166 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09167 } 09168 } else { 09169 if (option_verbose > 2) 09170 ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span); 09171 for (x = 0; x < pri->numchans; x++) 09172 if (pri->pvts[x]) { 09173 ast_mutex_lock(&pri->pvts[x]->lock); 09174 if (pri->pvts[x]->call) { 09175 pri_destroycall(pri->pri, pri->pvts[x]->call); 09176 pri->pvts[x]->call = NULL; 09177 } 09178 if (pri->pvts[chanpos]->realcall) 09179 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 09180 else if (pri->pvts[x]->owner) 09181 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09182 ast_mutex_unlock(&pri->pvts[x]->lock); 09183 } 09184 } 09185 break; 09186 case PRI_EVENT_KEYPAD_DIGIT: 09187 chanpos = pri_find_principle(pri, e->digit.channel); 09188 if (chanpos < 0) { 09189 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 09190 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span); 09191 } else { 09192 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call); 09193 if (chanpos > -1) { 09194 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09195 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */ 09196 if (pri->overlapdial && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) { 09197 /* how to do that */ 09198 int digitlen = strlen(e->digit.digits); 09199 char digit; 09200 int i; 09201 for (i = 0; i < digitlen; i++) { 09202 digit = e->digit.digits[i]; 09203 { 09204 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 09205 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 09206 } 09207 } 09208 } 09209 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09210 } 09211 } 09212 break; 09213 09214 case PRI_EVENT_INFO_RECEIVED: 09215 chanpos = pri_find_principle(pri, e->ring.channel); 09216 if (chanpos < 0) { 09217 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 09218 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 09219 } else { 09220 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call); 09221 if (chanpos > -1) { 09222 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09223 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */ 09224 if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) { 09225 /* how to do that */ 09226 int digitlen = strlen(e->ring.callednum); 09227 char digit; 09228 int i; 09229 for (i = 0; i < digitlen; i++) { 09230 digit = e->ring.callednum[i]; 09231 { 09232 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 09233 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 09234 } 09235 } 09236 } 09237 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09238 } 09239 } 09240 break; 09241 case PRI_EVENT_RING: 09242 crv = NULL; 09243 if (e->ring.channel == -1) 09244 chanpos = pri_find_empty_chan(pri, 1); 09245 else 09246 chanpos = pri_find_principle(pri, e->ring.channel); 09247 /* if no channel specified find one empty */ 09248 if (chanpos < 0) { 09249 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 09250 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 09251 } else { 09252 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09253 if (pri->pvts[chanpos]->owner) { 09254 if (pri->pvts[chanpos]->call == e->ring.call) { 09255 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 09256 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 09257 break; 09258 } else { 09259 /* This is where we handle initial glare */ 09260 ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n", 09261 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 09262 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09263 chanpos = -1; 09264 } 09265 } 09266 if (chanpos > -1) 09267 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09268 } 09269 if ((chanpos < 0) && (e->ring.flexible)) 09270 chanpos = pri_find_empty_chan(pri, 1); 09271 if (chanpos > -1) { 09272 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09273 if (pri->switchtype == PRI_SWITCH_GR303_TMC) { 09274 /* Should be safe to lock CRV AFAIK while bearer is still locked */ 09275 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL)); 09276 if (crv) 09277 ast_mutex_lock(&crv->lock); 09278 if (!crv || crv->owner) { 09279 pri->pvts[chanpos]->call = NULL; 09280 if (crv) { 09281 if (crv->owner) 09282 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09283 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); 09284 } else 09285 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); 09286 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE); 09287 if (crv) 09288 ast_mutex_unlock(&crv->lock); 09289 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09290 break; 09291 } 09292 } 09293 pri->pvts[chanpos]->call = e->ring.call; 09294 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan); 09295 if (pri->pvts[chanpos]->use_callerid) { 09296 ast_shrink_phone_number(plancallingnum); 09297 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num)); 09298 #ifdef PRI_ANI 09299 if (!ast_strlen_zero(e->ring.callingani)) { 09300 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani); 09301 ast_shrink_phone_number(plancallingani); 09302 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani)); 09303 } else { 09304 pri->pvts[chanpos]->cid_ani[0] = '\0'; 09305 } 09306 #endif 09307 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name)); 09308 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */ 09309 } else { 09310 pri->pvts[chanpos]->cid_num[0] = '\0'; 09311 pri->pvts[chanpos]->cid_ani[0] = '\0'; 09312 pri->pvts[chanpos]->cid_name[0] = '\0'; 09313 pri->pvts[chanpos]->cid_ton = 0; 09314 } 09315 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri, 09316 e->ring.redirectingnum, e->ring.callingplanrdnis); 09317 /* If immediate=yes go to s|1 */ 09318 if (pri->pvts[chanpos]->immediate) { 09319 if (option_verbose > 2) 09320 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n"); 09321 pri->pvts[chanpos]->exten[0] = 's'; 09322 pri->pvts[chanpos]->exten[1] = '\0'; 09323 } 09324 /* Get called number */ 09325 else if (!ast_strlen_zero(e->ring.callednum)) { 09326 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten)); 09327 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 09328 } else if (pri->overlapdial) 09329 pri->pvts[chanpos]->exten[0] = '\0'; 09330 else { 09331 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */ 09332 pri->pvts[chanpos]->exten[0] = 's'; 09333 pri->pvts[chanpos]->exten[1] = '\0'; 09334 } 09335 /* Set DNID on all incoming calls -- even immediate */ 09336 if (!ast_strlen_zero(e->ring.callednum)) 09337 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 09338 /* No number yet, but received "sending complete"? */ 09339 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) { 09340 if (option_verbose > 2) 09341 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n"); 09342 pri->pvts[chanpos]->exten[0] = 's'; 09343 pri->pvts[chanpos]->exten[1] = '\0'; 09344 } 09345 /* Make sure extension exists (or in overlap dial mode, can exist) */ 09346 if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) || 09347 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 09348 /* Setup law */ 09349 int law; 09350 if (pri->switchtype != PRI_SWITCH_GR303_TMC) { 09351 /* Set to audio mode at this point */ 09352 law = 1; 09353 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1) 09354 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno)); 09355 } 09356 if (e->ring.layer1 == PRI_LAYER_1_ALAW) 09357 law = DAHDI_LAW_ALAW; 09358 else 09359 law = DAHDI_LAW_MULAW; 09360 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law); 09361 if (res < 0) 09362 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel); 09363 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law); 09364 if (res < 0) 09365 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel); 09366 if (e->ring.complete || !pri->overlapdial) { 09367 /* Just announce proceeding */ 09368 pri->pvts[chanpos]->proceeding = 1; 09369 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0); 09370 } else { 09371 if (pri->switchtype != PRI_SWITCH_GR303_TMC) 09372 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 09373 else 09374 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 09375 } 09376 /* Get the use_callingpres state */ 09377 pri->pvts[chanpos]->callingpres = e->ring.callingpres; 09378 09379 /* Start PBX */ 09380 if (!e->ring.complete && pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 09381 /* Release the PRI lock while we create the channel */ 09382 ast_mutex_unlock(&pri->lock); 09383 if (crv) { 09384 /* Set bearer and such */ 09385 pri_assign_bearer(crv, pri, pri->pvts[chanpos]); 09386 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 09387 pri->pvts[chanpos]->owner = &inuse; 09388 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel); 09389 } else { 09390 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 09391 } 09392 09393 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09394 09395 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 09396 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 09397 } 09398 if (e->ring.ani2 >= 0) { 09399 snprintf(ani2str, 5, "%.2d", e->ring.ani2); 09400 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 09401 } 09402 09403 #ifdef SUPPORT_USERUSER 09404 if (!ast_strlen_zero(e->ring.useruserinfo)) { 09405 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 09406 } 09407 #endif 09408 09409 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan); 09410 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 09411 if (e->ring.redirectingreason >= 0) 09412 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 09413 09414 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09415 ast_mutex_lock(&pri->lock); 09416 09417 pthread_attr_init(&attr); 09418 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 09419 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) { 09420 if (option_verbose > 2) 09421 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n", 09422 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"), 09423 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 09424 } else { 09425 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 09426 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 09427 if (c) 09428 ast_hangup(c); 09429 else { 09430 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 09431 pri->pvts[chanpos]->call = NULL; 09432 } 09433 } 09434 pthread_attr_destroy(&attr); 09435 } else { 09436 ast_mutex_unlock(&pri->lock); 09437 /* Release PRI lock while we create the channel */ 09438 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype); 09439 if (c) { 09440 char calledtonstr[10]; 09441 09442 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09443 09444 if (e->ring.ani2 >= 0) { 09445 snprintf(ani2str, 5, "%d", e->ring.ani2); 09446 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 09447 } 09448 09449 #ifdef SUPPORT_USERUSER 09450 if (!ast_strlen_zero(e->ring.useruserinfo)) { 09451 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 09452 } 09453 #endif 09454 09455 if (e->ring.redirectingreason >= 0) 09456 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 09457 09458 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan); 09459 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 09460 09461 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09462 ast_mutex_lock(&pri->lock); 09463 09464 if (option_verbose > 2) 09465 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n", 09466 plancallingnum, pri->pvts[chanpos]->exten, 09467 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 09468 dahdi_enable_ec(pri->pvts[chanpos]); 09469 } else { 09470 09471 ast_mutex_lock(&pri->lock); 09472 09473 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 09474 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 09475 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 09476 pri->pvts[chanpos]->call = NULL; 09477 } 09478 } 09479 } else { 09480 if (option_verbose > 2) 09481 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n", 09482 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 09483 pri->pvts[chanpos]->prioffset, pri->span); 09484 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED); 09485 pri->pvts[chanpos]->call = NULL; 09486 pri->pvts[chanpos]->exten[0] = '\0'; 09487 } 09488 if (crv) 09489 ast_mutex_unlock(&crv->lock); 09490 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09491 } else { 09492 if (e->ring.flexible) 09493 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION); 09494 else 09495 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL); 09496 } 09497 break; 09498 case PRI_EVENT_RINGING: 09499 chanpos = pri_find_principle(pri, e->ringing.channel); 09500 if (chanpos < 0) { 09501 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 09502 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 09503 } else { 09504 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call); 09505 if (chanpos < 0) { 09506 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 09507 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 09508 } else { 09509 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09510 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 09511 dahdi_enable_ec(pri->pvts[chanpos]); 09512 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1; 09513 pri->pvts[chanpos]->alerting = 1; 09514 } else 09515 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n"); 09516 #ifdef PRI_PROGRESS_MASK 09517 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) { 09518 #else 09519 if (e->ringing.progress == 8) { 09520 #endif 09521 /* Now we can do call progress detection */ 09522 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 09523 /* RINGING detection isn't required because we got ALERTING signal */ 09524 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING); 09525 pri->pvts[chanpos]->dsp_features = 0; 09526 } 09527 } 09528 09529 #ifdef SUPPORT_USERUSER 09530 if (!ast_strlen_zero(e->ringing.useruserinfo)) { 09531 struct ast_channel *owner = pri->pvts[chanpos]->owner; 09532 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09533 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo); 09534 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09535 } 09536 #endif 09537 09538 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09539 } 09540 } 09541 break; 09542 case PRI_EVENT_PROGRESS: 09543 /* Get chan value if e->e is not PRI_EVNT_RINGING */ 09544 chanpos = pri_find_principle(pri, e->proceeding.channel); 09545 if (chanpos > -1) { 09546 #ifdef PRI_PROGRESS_MASK 09547 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) { 09548 #else 09549 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) { 09550 #endif 09551 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, }; 09552 09553 if (e->proceeding.cause > -1) { 09554 if (option_verbose > 2) 09555 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause); 09556 09557 /* Work around broken, out of spec USER_BUSY cause in a progress message */ 09558 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) { 09559 if (pri->pvts[chanpos]->owner) { 09560 if (option_verbose > 2) 09561 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n"); 09562 09563 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause; 09564 f.subclass = AST_CONTROL_BUSY; 09565 } 09566 } 09567 } 09568 09569 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09570 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n", 09571 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 09572 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 09573 #ifdef PRI_PROGRESS_MASK 09574 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 09575 #else 09576 if (e->proceeding.progress == 8) { 09577 #endif 09578 /* Now we can do call progress detection */ 09579 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 09580 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 09581 pri->pvts[chanpos]->dsp_features = 0; 09582 } 09583 } 09584 pri->pvts[chanpos]->progress = 1; 09585 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09586 } 09587 } 09588 break; 09589 case PRI_EVENT_PROCEEDING: 09590 chanpos = pri_find_principle(pri, e->proceeding.channel); 09591 if (chanpos > -1) { 09592 if (!pri->pvts[chanpos]->proceeding) { 09593 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, }; 09594 09595 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09596 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n", 09597 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 09598 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 09599 #ifdef PRI_PROGRESS_MASK 09600 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 09601 #else 09602 if (e->proceeding.progress == 8) { 09603 #endif 09604 /* Now we can do call progress detection */ 09605 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 09606 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 09607 pri->pvts[chanpos]->dsp_features = 0; 09608 } 09609 /* Bring voice path up */ 09610 f.subclass = AST_CONTROL_PROGRESS; 09611 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 09612 } 09613 pri->pvts[chanpos]->proceeding = 1; 09614 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09615 } 09616 } 09617 break; 09618 case PRI_EVENT_FACNAME: 09619 chanpos = pri_find_principle(pri, e->facname.channel); 09620 if (chanpos < 0) { 09621 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 09622 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 09623 } else { 09624 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call); 09625 if (chanpos < 0) { 09626 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 09627 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 09628 } else { 09629 /* Re-use *69 field for PRI */ 09630 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09631 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num)); 09632 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name)); 09633 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1; 09634 dahdi_enable_ec(pri->pvts[chanpos]); 09635 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09636 } 09637 } 09638 break; 09639 case PRI_EVENT_ANSWER: 09640 chanpos = pri_find_principle(pri, e->answer.channel); 09641 if (chanpos < 0) { 09642 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 09643 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 09644 } else { 09645 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call); 09646 if (chanpos < 0) { 09647 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 09648 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 09649 } else { 09650 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09651 /* Now we can do call progress detection */ 09652 09653 /* We changed this so it turns on the DSP no matter what... progress or no progress. 09654 * By this time, we need DTMF detection and other features that were previously disabled 09655 * -- Matt F */ 09656 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 09657 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 09658 pri->pvts[chanpos]->dsp_features = 0; 09659 } 09660 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) { 09661 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n"); 09662 x = DAHDI_START; 09663 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 09664 if (res < 0) { 09665 if (errno != EINPROGRESS) { 09666 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 09667 } 09668 } 09669 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 09670 pri->pvts[chanpos]->dialing = 1; 09671 /* Send any "w" waited stuff */ 09672 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop); 09673 if (res < 0) { 09674 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno)); 09675 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 09676 } else 09677 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr); 09678 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 09679 } else if (pri->pvts[chanpos]->confirmanswer) { 09680 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel); 09681 } else { 09682 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1; 09683 /* Enable echo cancellation if it's not on already */ 09684 dahdi_enable_ec(pri->pvts[chanpos]); 09685 } 09686 09687 #ifdef SUPPORT_USERUSER 09688 if (!ast_strlen_zero(e->answer.useruserinfo)) { 09689 struct ast_channel *owner = pri->pvts[chanpos]->owner; 09690 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09691 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo); 09692 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09693 } 09694 #endif 09695 09696 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09697 } 09698 } 09699 break; 09700 case PRI_EVENT_HANGUP: 09701 chanpos = pri_find_principle(pri, e->hangup.channel); 09702 if (chanpos < 0) { 09703 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 09704 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 09705 } else { 09706 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 09707 if (chanpos > -1) { 09708 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09709 if (!pri->pvts[chanpos]->alreadyhungup) { 09710 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */ 09711 pri->pvts[chanpos]->alreadyhungup = 1; 09712 if (pri->pvts[chanpos]->realcall) 09713 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 09714 else if (pri->pvts[chanpos]->owner) { 09715 /* Queue a BUSY instead of a hangup if our cause is appropriate */ 09716 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 09717 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP) 09718 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09719 else { 09720 switch (e->hangup.cause) { 09721 case PRI_CAUSE_USER_BUSY: 09722 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 09723 break; 09724 case PRI_CAUSE_CALL_REJECTED: 09725 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 09726 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 09727 case PRI_CAUSE_SWITCH_CONGESTION: 09728 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 09729 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 09730 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 09731 break; 09732 default: 09733 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09734 } 09735 } 09736 } 09737 if (option_verbose > 2) 09738 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n", 09739 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause); 09740 } else { 09741 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 09742 pri->pvts[chanpos]->call = NULL; 09743 } 09744 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 09745 if (option_verbose > 2) 09746 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 09747 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 09748 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 09749 pri->pvts[chanpos]->resetting = 1; 09750 } 09751 if (e->hangup.aoc_units > -1) 09752 if (option_verbose > 2) 09753 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 09754 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 09755 09756 #ifdef SUPPORT_USERUSER 09757 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) { 09758 struct ast_channel *owner = pri->pvts[chanpos]->owner; 09759 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09760 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 09761 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09762 } 09763 #endif 09764 09765 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09766 } else { 09767 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 09768 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 09769 } 09770 } 09771 break; 09772 #ifndef PRI_EVENT_HANGUP_REQ 09773 #error please update libpri 09774 #endif 09775 case PRI_EVENT_HANGUP_REQ: 09776 chanpos = pri_find_principle(pri, e->hangup.channel); 09777 if (chanpos < 0) { 09778 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 09779 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 09780 } else { 09781 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 09782 if (chanpos > -1) { 09783 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09784 if (pri->pvts[chanpos]->realcall) 09785 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 09786 else if (pri->pvts[chanpos]->owner) { 09787 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 09788 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP) 09789 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09790 else { 09791 switch (e->hangup.cause) { 09792 case PRI_CAUSE_USER_BUSY: 09793 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 09794 break; 09795 case PRI_CAUSE_CALL_REJECTED: 09796 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 09797 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 09798 case PRI_CAUSE_SWITCH_CONGESTION: 09799 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 09800 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 09801 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 09802 break; 09803 default: 09804 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09805 } 09806 } 09807 if (option_verbose > 2) 09808 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); 09809 if (e->hangup.aoc_units > -1) 09810 if (option_verbose > 2) 09811 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 09812 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 09813 } else { 09814 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 09815 pri->pvts[chanpos]->call = NULL; 09816 } 09817 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 09818 if (option_verbose > 2) 09819 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n", 09820 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 09821 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 09822 pri->pvts[chanpos]->resetting = 1; 09823 } 09824 09825 #ifdef SUPPORT_USERUSER 09826 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 09827 struct ast_channel *owner = pri->pvts[chanpos]->owner; 09828 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09829 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 09830 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09831 } 09832 #endif 09833 09834 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09835 } else { 09836 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); 09837 } 09838 } 09839 break; 09840 case PRI_EVENT_HANGUP_ACK: 09841 chanpos = pri_find_principle(pri, e->hangup.channel); 09842 if (chanpos < 0) { 09843 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 09844 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 09845 } else { 09846 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 09847 if (chanpos > -1) { 09848 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09849 pri->pvts[chanpos]->call = NULL; 09850 pri->pvts[chanpos]->resetting = 0; 09851 if (pri->pvts[chanpos]->owner) { 09852 if (option_verbose > 2) 09853 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); 09854 } 09855 09856 #ifdef SUPPORT_USERUSER 09857 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 09858 struct ast_channel *owner = pri->pvts[chanpos]->owner; 09859 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09860 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 09861 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09862 } 09863 #endif 09864 09865 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09866 } 09867 } 09868 break; 09869 case PRI_EVENT_CONFIG_ERR: 09870 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err); 09871 break; 09872 case PRI_EVENT_RESTART_ACK: 09873 chanpos = pri_find_principle(pri, e->restartack.channel); 09874 if (chanpos < 0) { 09875 /* Sometime switches (e.g. I421 / British Telecom) don't give us the 09876 channel number, so we have to figure it out... This must be why 09877 everybody resets exactly a channel at a time. */ 09878 for (x = 0; x < pri->numchans; x++) { 09879 if (pri->pvts[x] && pri->pvts[x]->resetting) { 09880 chanpos = x; 09881 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09882 ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 09883 pri->pvts[chanpos]->prioffset, pri->span); 09884 if (pri->pvts[chanpos]->realcall) 09885 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 09886 else if (pri->pvts[chanpos]->owner) { 09887 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 09888 pri->pvts[chanpos]->prioffset, pri->span); 09889 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09890 } 09891 pri->pvts[chanpos]->resetting = 0; 09892 if (option_verbose > 2) 09893 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 09894 pri->pvts[chanpos]->prioffset, pri->span); 09895 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09896 if (pri->resetting) 09897 pri_check_restart(pri); 09898 break; 09899 } 09900 } 09901 if (chanpos < 0) { 09902 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 09903 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 09904 } 09905 } else { 09906 if (pri->pvts[chanpos]) { 09907 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09908 if (pri->pvts[chanpos]->realcall) 09909 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 09910 else if (pri->pvts[chanpos]->owner) { 09911 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n", 09912 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 09913 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09914 } 09915 pri->pvts[chanpos]->resetting = 0; 09916 if (option_verbose > 2) 09917 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 09918 pri->pvts[chanpos]->prioffset, pri->span); 09919 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09920 if (pri->resetting) 09921 pri_check_restart(pri); 09922 } 09923 } 09924 break; 09925 case PRI_EVENT_SETUP_ACK: 09926 chanpos = pri_find_principle(pri, e->setup_ack.channel); 09927 if (chanpos < 0) { 09928 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 09929 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span); 09930 } else { 09931 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call); 09932 if (chanpos > -1) { 09933 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09934 pri->pvts[chanpos]->setup_ack = 1; 09935 /* Send any queued digits */ 09936 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) { 09937 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]); 09938 pri_information(pri->pri, pri->pvts[chanpos]->call, 09939 pri->pvts[chanpos]->dialdest[x]); 09940 } 09941 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09942 } else 09943 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel); 09944 } 09945 break; 09946 case PRI_EVENT_NOTIFY: 09947 chanpos = pri_find_principle(pri, e->notify.channel); 09948 if (chanpos < 0) { 09949 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n", 09950 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span); 09951 } else { 09952 struct ast_frame f = { AST_FRAME_CONTROL, }; 09953 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09954 switch (e->notify.info) { 09955 case PRI_NOTIFY_REMOTE_HOLD: 09956 f.subclass = AST_CONTROL_HOLD; 09957 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 09958 break; 09959 case PRI_NOTIFY_REMOTE_RETRIEVAL: 09960 f.subclass = AST_CONTROL_UNHOLD; 09961 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 09962 break; 09963 } 09964 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09965 } 09966 break; 09967 default: 09968 ast_log(LOG_DEBUG, "Event: %d\n", e->e); 09969 } 09970 } 09971 ast_mutex_unlock(&pri->lock); 09972 } 09973 /* Never reached */ 09974 return NULL; 09975 }
Definition at line 8519 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pri::crvs, dahdi_pvt::next, and dahdi_pvt::pri.
08520 { 08521 struct dahdi_pvt *p; 08522 p = pri->crvs; 08523 while (p) { 08524 if (p->channel == crv) 08525 return p; 08526 p = p->next; 08527 } 08528 return NULL; 08529 }
static int pri_find_dchan | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 2793 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, dahdi_pri::dchans, NUM_DCHANS, and dahdi_pri::pri.
02794 { 02795 int oldslot = -1; 02796 struct pri *old; 02797 int newslot = -1; 02798 int x; 02799 old = pri->pri; 02800 for (x = 0; x < NUM_DCHANS; x++) { 02801 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0)) 02802 newslot = x; 02803 if (pri->dchans[x] == old) { 02804 oldslot = x; 02805 } 02806 } 02807 if (newslot < 0) { 02808 newslot = 0; 02809 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n", 02810 pri->dchannels[newslot]); 02811 } 02812 if (old && (oldslot != newslot)) 02813 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n", 02814 pri->dchannels[oldslot], pri->dchannels[newslot]); 02815 pri->pri = pri->dchans[newslot]; 02816 return 0; 02817 }
static int pri_find_empty_chan | ( | struct dahdi_pri * | pri, | |
int | backwards | |||
) | [static] |
Definition at line 8251 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().
08252 { 08253 int x; 08254 if (backwards) 08255 x = pri->numchans; 08256 else 08257 x = 0; 08258 for (;;) { 08259 if (backwards && (x < 0)) 08260 break; 08261 if (!backwards && (x >= pri->numchans)) 08262 break; 08263 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) { 08264 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n", 08265 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset); 08266 return x; 08267 } 08268 if (backwards) 08269 x--; 08270 else 08271 x++; 08272 } 08273 return -1; 08274 }
static int pri_find_principle | ( | struct dahdi_pri * | pri, | |
int | channel | |||
) | [static] |
Definition at line 8532 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.
08533 { 08534 int x; 08535 int span = PRI_SPAN(channel); 08536 int spanfd; 08537 struct dahdi_params param; 08538 int principle = -1; 08539 int explicit = PRI_EXPLICIT(channel); 08540 channel = PRI_CHANNEL(channel); 08541 08542 if (!explicit) { 08543 spanfd = pri_active_dchan_fd(pri); 08544 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m)) 08545 return -1; 08546 span = pris[param.spanno - 1].prilogicalspan; 08547 } 08548 08549 for (x = 0; x < pri->numchans; x++) { 08550 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) { 08551 principle = x; 08552 break; 08553 } 08554 } 08555 08556 return principle; 08557 }
static int pri_fixup_principle | ( | struct dahdi_pri * | pri, | |
int | principle, | |||
q931_call * | c | |||
) | [static] |
Definition at line 8559 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.
08560 { 08561 int x; 08562 struct dahdi_pvt *crv; 08563 if (!c) { 08564 if (principle < 0) 08565 return -1; 08566 return principle; 08567 } 08568 if ((principle > -1) && 08569 (principle < pri->numchans) && 08570 (pri->pvts[principle]) && 08571 (pri->pvts[principle]->call == c)) 08572 return principle; 08573 /* First, check for other bearers */ 08574 for (x = 0; x < pri->numchans; x++) { 08575 if (!pri->pvts[x]) 08576 continue; 08577 if (pri->pvts[x]->call == c) { 08578 /* Found our call */ 08579 if (principle != x) { 08580 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x]; 08581 08582 if (option_verbose > 2) 08583 ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n", 08584 old->channel, new->channel); 08585 if (new->owner) { 08586 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n", 08587 old->channel, new->channel, new->channel); 08588 return -1; 08589 } 08590 /* Fix it all up now */ 08591 new->owner = old->owner; 08592 old->owner = NULL; 08593 if (new->owner) { 08594 ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1); 08595 new->owner->tech_pvt = new; 08596 new->owner->fds[0] = new->subs[SUB_REAL].dfd; 08597 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner; 08598 old->subs[SUB_REAL].owner = NULL; 08599 } else 08600 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); 08601 new->call = old->call; 08602 old->call = NULL; 08603 08604 /* Copy any DSP that may be present */ 08605 new->dsp = old->dsp; 08606 new->dsp_features = old->dsp_features; 08607 old->dsp = NULL; 08608 old->dsp_features = 0; 08609 } 08610 return principle; 08611 } 08612 } 08613 /* Now check for a CRV with no bearer */ 08614 crv = pri->crvs; 08615 while (crv) { 08616 if (crv->call == c) { 08617 /* This is our match... Perform some basic checks */ 08618 if (crv->bearer) 08619 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n"); 08620 else if (pri->pvts[principle]->owner) 08621 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n"); 08622 else { 08623 /* Looks good. Drop the pseudo channel now, clear up the assignment, and 08624 wakeup the potential sleeper */ 08625 dahdi_close_sub(crv, SUB_REAL); 08626 pri->pvts[principle]->call = crv->call; 08627 pri_assign_bearer(crv, pri, pri->pvts[principle]); 08628 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n", 08629 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset, 08630 pri->trunkgroup, crv->channel); 08631 wakeup_sub(crv, SUB_REAL, pri); 08632 } 08633 return principle; 08634 } 08635 crv = crv->next; 08636 } 08637 ast_log(LOG_WARNING, "Call specified, but not found?\n"); 08638 return -1; 08639 }
Definition at line 1072 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().
01073 { 01074 int res; 01075 /* Grab the lock first */ 01076 do { 01077 res = ast_mutex_trylock(&pri->lock); 01078 if (res) { 01079 DEADLOCK_AVOIDANCE(&pvt->lock); 01080 } 01081 } while (res); 01082 /* Then break the poll */ 01083 if (pri->master != AST_PTHREADT_NULL) 01084 pthread_kill(pri->master, SIGURG); 01085 return 0; 01086 }
Definition at line 8799 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.
08800 { 08801 int x; 08802 int redo; 08803 ast_mutex_unlock(&pri->lock); 08804 ast_mutex_lock(&p->lock); 08805 do { 08806 redo = 0; 08807 for (x = 0; x < 3; x++) { 08808 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) { 08809 redo++; 08810 DEADLOCK_AVOIDANCE(&p->lock); 08811 } 08812 if (p->subs[x].owner) { 08813 ast_queue_hangup(p->subs[x].owner); 08814 ast_mutex_unlock(&p->subs[x].owner->lock); 08815 } 08816 } 08817 } while (redo); 08818 ast_mutex_unlock(&p->lock); 08819 ast_mutex_lock(&pri->lock); 08820 return 0; 08821 }
static int pri_is_up | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 2741 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, NUM_DCHANS, and dahdi_pvt::pri.
Referenced by pri_dchannel().
02742 { 02743 int x; 02744 for (x = 0; x < NUM_DCHANS; x++) { 02745 if (pri->dchanavail[x] == DCHAN_AVAILABLE) 02746 return 1; 02747 } 02748 return 0; 02749 }
static char* pri_order | ( | int | level | ) | [static] |
Definition at line 2764 of file chan_dahdi.c.
Referenced by handle_pri_show_span().
02765 { 02766 switch (level) { 02767 case 0: 02768 return "Primary"; 02769 case 1: 02770 return "Secondary"; 02771 case 2: 02772 return "Tertiary"; 02773 case 3: 02774 return "Quaternary"; 02775 default: 02776 return "<Unknown>"; 02777 } 02778 }
static void pri_rel | ( | struct dahdi_pri * | pri | ) | [inline, static] |
Definition at line 361 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().
00362 { 00363 ast_mutex_unlock(&pri->lock); 00364 }
static int pri_resolve_span | ( | int * | span, | |
int | channel, | |||
int | offset, | |||
struct dahdi_spaninfo * | si | |||
) | [static] |
Definition at line 7493 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().
07494 { 07495 int x; 07496 int trunkgroup; 07497 /* Get appropriate trunk group if there is one */ 07498 trunkgroup = pris[*span].mastertrunkgroup; 07499 if (trunkgroup) { 07500 /* Select a specific trunk group */ 07501 for (x = 0; x < NUM_SPANS; x++) { 07502 if (pris[x].trunkgroup == trunkgroup) { 07503 *span = x; 07504 return 0; 07505 } 07506 } 07507 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup); 07508 *span = -1; 07509 } else { 07510 if (pris[*span].trunkgroup) { 07511 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup); 07512 *span = -1; 07513 } else if (pris[*span].mastertrunkgroup) { 07514 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup); 07515 *span = -1; 07516 } else { 07517 if (si->totalchans == 31) { 07518 /* E1 */ 07519 pris[*span].dchannels[0] = 16 + offset; 07520 } else if (si->totalchans == 24) { 07521 /* T1 or J1 */ 07522 pris[*span].dchannels[0] = 24 + offset; 07523 } else if (si->totalchans == 3) { 07524 /* BRI */ 07525 pris[*span].dchannels[0] = 3 + offset; 07526 } else { 07527 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); 07528 *span = -1; 07529 return 0; 07530 } 07531 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED; 07532 pris[*span].offset = offset; 07533 pris[*span].span = *span + 1; 07534 } 07535 } 07536 return 0; 07537 }
static int process_dahdi | ( | struct dahdi_chan_conf * | confp, | |
const char * | cat, | |||
struct ast_variable * | v, | |||
int | reload, | |||
int | skipchannels | |||
) | [static] |
Definition at line 11330 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_strlen_zero(), ast_true(), ast_verbose(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, build_channels(), dahdi_pvt::busycompare, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::callgroup, dahdi_pvt::callprogress, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, dahdi_pvt::cancallforward, dahdi_pvt::canpark, dahdi_chan_conf::chan, dahdi_pvt::cid_name, dahdi_pvt::cid_num, CID_SIG_BELL, CID_SIG_DTMF, CID_SIG_SMDI, CID_SIG_V23, CID_SIG_V23_JP, dahdi_pvt::cid_signalling, dahdi_pvt::cid_start, CID_START_POLARITY, CID_START_RING, dahdi_pvt::context, ringContextData::contextData, dahdi_pvt::dahditrcallerid, 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_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().
11331 { 11332 struct dahdi_pvt *tmp; 11333 int y; 11334 int found_pseudo = 0; 11335 char dahdichan[MAX_CHANLIST_LEN] = {}; 11336 11337 for (; v; v = v->next) { 11338 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 11339 continue; 11340 11341 /* Create the interface list */ 11342 if (!strcasecmp(v->name, "channel") 11343 #ifdef HAVE_PRI 11344 || !strcasecmp(v->name, "crv") 11345 #endif 11346 ) { 11347 int iscrv; 11348 if (skipchannels) 11349 continue; 11350 iscrv = !strcasecmp(v->name, "crv"); 11351 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo)) 11352 return -1; 11353 } else if (!strcasecmp(v->name, "buffers")) { 11354 int res; 11355 char policy[21] = ""; 11356 11357 res = sscanf(v->value, "%d,%20s", &confp->chan.buf_no, policy); 11358 if (res != 2) { 11359 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n"); 11360 confp->chan.buf_no = numbufs; 11361 continue; 11362 } 11363 if (confp->chan.buf_no < 0) 11364 confp->chan.buf_no = numbufs; 11365 if (!strcasecmp(policy, "full")) { 11366 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL; 11367 } else if (!strcasecmp(policy, "immediate")) { 11368 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE; 11369 } else { 11370 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy); 11371 } 11372 } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) { 11373 ast_copy_string(dahdichan, v->value, sizeof(dahdichan)); 11374 if (v->name[0] == 'z' || v->name[0] == 'Z') { 11375 ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat); 11376 } 11377 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) { 11378 if (ast_true(v->value)) 11379 confp->chan.usedistinctiveringdetection = 1; 11380 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) { 11381 if (ast_true(v->value)) 11382 distinctiveringaftercid = 1; 11383 } else if (!strcasecmp(v->name, "dring1context")) { 11384 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData)); 11385 } else if (!strcasecmp(v->name, "dring2context")) { 11386 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData)); 11387 } else if (!strcasecmp(v->name, "dring3context")) { 11388 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData)); 11389 } else if (!strcasecmp(v->name, "dring1")) { 11390 sscanf(v->value, "%d,%d,%d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]); 11391 } else if (!strcasecmp(v->name, "dring2")) { 11392 sscanf(v->value, "%d,%d,%d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]); 11393 } else if (!strcasecmp(v->name, "dring3")) { 11394 sscanf(v->value, "%d,%d,%d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]); 11395 } else if (!strcasecmp(v->name, "usecallerid")) { 11396 confp->chan.use_callerid = ast_true(v->value); 11397 } else if (!strcasecmp(v->name, "cidsignalling")) { 11398 if (!strcasecmp(v->value, "bell")) 11399 confp->chan.cid_signalling = CID_SIG_BELL; 11400 else if (!strcasecmp(v->value, "v23")) 11401 confp->chan.cid_signalling = CID_SIG_V23; 11402 else if (!strcasecmp(v->value, "dtmf")) 11403 confp->chan.cid_signalling = CID_SIG_DTMF; 11404 else if (!strcasecmp(v->value, "smdi")) 11405 confp->chan.cid_signalling = CID_SIG_SMDI; 11406 else if (!strcasecmp(v->value, "v23_jp")) 11407 confp->chan.cid_signalling = CID_SIG_V23_JP; 11408 else if (ast_true(v->value)) 11409 confp->chan.cid_signalling = CID_SIG_BELL; 11410 } else if (!strcasecmp(v->name, "cidstart")) { 11411 if (!strcasecmp(v->value, "ring")) 11412 confp->chan.cid_start = CID_START_RING; 11413 else if (!strcasecmp(v->value, "polarity")) 11414 confp->chan.cid_start = CID_START_POLARITY; 11415 else if (ast_true(v->value)) 11416 confp->chan.cid_start = CID_START_RING; 11417 } else if (!strcasecmp(v->name, "threewaycalling")) { 11418 confp->chan.threewaycalling = ast_true(v->value); 11419 } else if (!strcasecmp(v->name, "cancallforward")) { 11420 confp->chan.cancallforward = ast_true(v->value); 11421 } else if (!strcasecmp(v->name, "relaxdtmf")) { 11422 if (ast_true(v->value)) 11423 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 11424 else 11425 confp->chan.dtmfrelax = 0; 11426 } else if (!strcasecmp(v->name, "mailbox")) { 11427 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox)); 11428 } else if (!strcasecmp(v->name, "hasvoicemail")) { 11429 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) { 11430 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox)); 11431 } 11432 } else if (!strcasecmp(v->name, "adsi")) { 11433 confp->chan.adsi = ast_true(v->value); 11434 } else if (!strcasecmp(v->name, "usesmdi")) { 11435 confp->chan.use_smdi = ast_true(v->value); 11436 } else if (!strcasecmp(v->name, "smdiport")) { 11437 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port)); 11438 } else if (!strcasecmp(v->name, "transfer")) { 11439 confp->chan.transfer = ast_true(v->value); 11440 } else if (!strcasecmp(v->name, "canpark")) { 11441 confp->chan.canpark = ast_true(v->value); 11442 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) { 11443 confp->chan.echocanbridged = ast_true(v->value); 11444 } else if (!strcasecmp(v->name, "busydetect")) { 11445 confp->chan.busydetect = ast_true(v->value); 11446 } else if (!strcasecmp(v->name, "busycount")) { 11447 confp->chan.busycount = atoi(v->value); 11448 } else if (!strcasecmp(v->name, "silencethreshold")) { 11449 confp->chan.silencethreshold = atoi(v->value); 11450 } else if (!strcasecmp(v->name, "busycompare")) { 11451 confp->chan.busycompare = ast_true(v->value); 11452 } else if (!strcasecmp(v->name, "busypattern")) { 11453 int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength); 11454 if (count == 1) 11455 confp->chan.busyquietlength = 0; 11456 else if (count < 1) 11457 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n"); 11458 } else if (!strcasecmp(v->name, "busyfuzziness")) { 11459 confp->chan.busyfuzziness = atoi(v->value); 11460 } else if (!strcasecmp(v->name, "callprogress")) { 11461 if (ast_true(v->value)) 11462 confp->chan.callprogress |= 1; 11463 else 11464 confp->chan.callprogress &= ~1; 11465 } else if (!strcasecmp(v->name, "faxdetect")) { 11466 if (!strcasecmp(v->value, "incoming")) { 11467 confp->chan.callprogress |= 4; 11468 confp->chan.callprogress &= ~2; 11469 } else if (!strcasecmp(v->value, "outgoing")) { 11470 confp->chan.callprogress &= ~4; 11471 confp->chan.callprogress |= 2; 11472 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) 11473 confp->chan.callprogress |= 6; 11474 else 11475 confp->chan.callprogress &= ~6; 11476 } else if (!strcasecmp(v->name, "echocancel")) { 11477 if (!ast_strlen_zero(v->value)) { 11478 y = atoi(v->value); 11479 } else 11480 y = 0; 11481 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024)) 11482 confp->chan.echocancel = y; 11483 else { 11484 confp->chan.echocancel = ast_true(v->value); 11485 if (confp->chan.echocancel) 11486 confp->chan.echocancel=128; 11487 } 11488 } else if (!strcasecmp(v->name, "echotraining")) { 11489 if (sscanf(v->value, "%d", &y) == 1) { 11490 if ((y < 10) || (y > 4000)) { 11491 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno); 11492 } else { 11493 confp->chan.echotraining = y; 11494 } 11495 } else if (ast_true(v->value)) { 11496 confp->chan.echotraining = 400; 11497 } else 11498 confp->chan.echotraining = 0; 11499 } else if (!strcasecmp(v->name, "hidecallerid")) { 11500 confp->chan.hidecallerid = ast_true(v->value); 11501 } else if (!strcasecmp(v->name, "hidecalleridname")) { 11502 confp->chan.hidecalleridname = ast_true(v->value); 11503 } else if (!strcasecmp(v->name, "pulsedial")) { 11504 confp->chan.pulse = ast_true(v->value); 11505 } else if (!strcasecmp(v->name, "callreturn")) { 11506 confp->chan.callreturn = ast_true(v->value); 11507 } else if (!strcasecmp(v->name, "callwaiting")) { 11508 confp->chan.callwaiting = ast_true(v->value); 11509 } else if (!strcasecmp(v->name, "callwaitingcallerid")) { 11510 confp->chan.callwaitingcallerid = ast_true(v->value); 11511 } else if (!strcasecmp(v->name, "context")) { 11512 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context)); 11513 } else if (!strcasecmp(v->name, "language")) { 11514 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language)); 11515 } else if (!strcasecmp(v->name, "progzone")) { 11516 ast_copy_string(progzone, v->value, sizeof(progzone)); 11517 } else if (!strcasecmp(v->name, "mohinterpret") 11518 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) { 11519 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret)); 11520 } else if (!strcasecmp(v->name, "mohsuggest")) { 11521 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest)); 11522 } else if (!strcasecmp(v->name, "stripmsd")) { 11523 confp->chan.stripmsd = atoi(v->value); 11524 } else if (!strcasecmp(v->name, "jitterbuffers")) { 11525 numbufs = atoi(v->value); 11526 } else if (!strcasecmp(v->name, "group")) { 11527 confp->chan.group = ast_get_group(v->value); 11528 } else if (!strcasecmp(v->name, "callgroup")) { 11529 confp->chan.callgroup = ast_get_group(v->value); 11530 } else if (!strcasecmp(v->name, "pickupgroup")) { 11531 confp->chan.pickupgroup = ast_get_group(v->value); 11532 } else if (!strcasecmp(v->name, "immediate")) { 11533 confp->chan.immediate = ast_true(v->value); 11534 } else if (!strcasecmp(v->name, "transfertobusy")) { 11535 confp->chan.transfertobusy = ast_true(v->value); 11536 } else if (!strcasecmp(v->name, "rxgain")) { 11537 if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) { 11538 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value); 11539 } 11540 } else if (!strcasecmp(v->name, "txgain")) { 11541 if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) { 11542 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value); 11543 } 11544 } else if (!strcasecmp(v->name, "tonezone")) { 11545 if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) { 11546 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value); 11547 } 11548 } else if (!strcasecmp(v->name, "callerid")) { 11549 if (!strcasecmp(v->value, "asreceived")) { 11550 confp->chan.cid_num[0] = '\0'; 11551 confp->chan.cid_name[0] = '\0'; 11552 } else { 11553 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num)); 11554 } 11555 } else if (!strcasecmp(v->name, "fullname")) { 11556 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name)); 11557 } else if (!strcasecmp(v->name, "cid_number")) { 11558 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num)); 11559 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) { 11560 confp->chan.dahditrcallerid = ast_true(v->value); 11561 if (strstr(v->name, "zap")) { 11562 ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat); 11563 } 11564 } else if (!strcasecmp(v->name, "restrictcid")) { 11565 confp->chan.restrictcid = ast_true(v->value); 11566 } else if (!strcasecmp(v->name, "usecallingpres")) { 11567 confp->chan.use_callingpres = ast_true(v->value); 11568 } else if (!strcasecmp(v->name, "accountcode")) { 11569 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode)); 11570 } else if (!strcasecmp(v->name, "amaflags")) { 11571 y = ast_cdr_amaflags2int(v->value); 11572 if (y < 0) 11573 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno); 11574 else 11575 confp->chan.amaflags = y; 11576 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) { 11577 confp->chan.polarityonanswerdelay = atoi(v->value); 11578 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) { 11579 confp->chan.answeronpolarityswitch = ast_true(v->value); 11580 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) { 11581 confp->chan.hanguponpolarityswitch = ast_true(v->value); 11582 } else if (!strcasecmp(v->name, "sendcalleridafter")) { 11583 confp->chan.sendcalleridafter = atoi(v->value); 11584 } else if (reload != 1){ 11585 if (!strcasecmp(v->name, "signalling")) { 11586 confp->chan.outsigmod = -1; 11587 if (!strcasecmp(v->value, "em")) { 11588 confp->chan.sig = SIG_EM; 11589 } else if (!strcasecmp(v->value, "em_e1")) { 11590 confp->chan.sig = SIG_EM_E1; 11591 } else if (!strcasecmp(v->value, "em_w")) { 11592 confp->chan.sig = SIG_EMWINK; 11593 confp->chan.radio = 0; 11594 } else if (!strcasecmp(v->value, "fxs_ls")) { 11595 confp->chan.sig = SIG_FXSLS; 11596 confp->chan.radio = 0; 11597 } else if (!strcasecmp(v->value, "fxs_gs")) { 11598 confp->chan.sig = SIG_FXSGS; 11599 confp->chan.radio = 0; 11600 } else if (!strcasecmp(v->value, "fxs_ks")) { 11601 confp->chan.sig = SIG_FXSKS; 11602 confp->chan.radio = 0; 11603 } else if (!strcasecmp(v->value, "fxo_ls")) { 11604 confp->chan.sig = SIG_FXOLS; 11605 confp->chan.radio = 0; 11606 } else if (!strcasecmp(v->value, "fxo_gs")) { 11607 confp->chan.sig = SIG_FXOGS; 11608 confp->chan.radio = 0; 11609 } else if (!strcasecmp(v->value, "fxo_ks")) { 11610 confp->chan.sig = SIG_FXOKS; 11611 confp->chan.radio = 0; 11612 } else if (!strcasecmp(v->value, "fxs_rx")) { 11613 confp->chan.sig = SIG_FXSKS; 11614 confp->chan.radio = 1; 11615 } else if (!strcasecmp(v->value, "fxo_rx")) { 11616 confp->chan.sig = SIG_FXOLS; 11617 confp->chan.radio = 1; 11618 } else if (!strcasecmp(v->value, "fxs_tx")) { 11619 confp->chan.sig = SIG_FXSLS; 11620 confp->chan.radio = 1; 11621 } else if (!strcasecmp(v->value, "fxo_tx")) { 11622 confp->chan.sig = SIG_FXOGS; 11623 confp->chan.radio = 1; 11624 } else if (!strcasecmp(v->value, "em_rx")) { 11625 confp->chan.sig = SIG_EM; 11626 confp->chan.radio = 1; 11627 } else if (!strcasecmp(v->value, "em_tx")) { 11628 confp->chan.sig = SIG_EM; 11629 confp->chan.radio = 1; 11630 } else if (!strcasecmp(v->value, "em_rxtx")) { 11631 confp->chan.sig = SIG_EM; 11632 confp->chan.radio = 2; 11633 } else if (!strcasecmp(v->value, "em_txrx")) { 11634 confp->chan.sig = SIG_EM; 11635 confp->chan.radio = 2; 11636 } else if (!strcasecmp(v->value, "sf")) { 11637 confp->chan.sig = SIG_SF; 11638 confp->chan.radio = 0; 11639 } else if (!strcasecmp(v->value, "sf_w")) { 11640 confp->chan.sig = SIG_SFWINK; 11641 confp->chan.radio = 0; 11642 } else if (!strcasecmp(v->value, "sf_featd")) { 11643 confp->chan.sig = SIG_FEATD; 11644 confp->chan.radio = 0; 11645 } else if (!strcasecmp(v->value, "sf_featdmf")) { 11646 confp->chan.sig = SIG_FEATDMF; 11647 confp->chan.radio = 0; 11648 } else if (!strcasecmp(v->value, "sf_featb")) { 11649 confp->chan.sig = SIG_SF_FEATB; 11650 confp->chan.radio = 0; 11651 } else if (!strcasecmp(v->value, "sf")) { 11652 confp->chan.sig = SIG_SF; 11653 confp->chan.radio = 0; 11654 } else if (!strcasecmp(v->value, "sf_rx")) { 11655 confp->chan.sig = SIG_SF; 11656 confp->chan.radio = 1; 11657 } else if (!strcasecmp(v->value, "sf_tx")) { 11658 confp->chan.sig = SIG_SF; 11659 confp->chan.radio = 1; 11660 } else if (!strcasecmp(v->value, "sf_rxtx")) { 11661 confp->chan.sig = SIG_SF; 11662 confp->chan.radio = 2; 11663 } else if (!strcasecmp(v->value, "sf_txrx")) { 11664 confp->chan.sig = SIG_SF; 11665 confp->chan.radio = 2; 11666 } else if (!strcasecmp(v->value, "featd")) { 11667 confp->chan.sig = SIG_FEATD; 11668 confp->chan.radio = 0; 11669 } else if (!strcasecmp(v->value, "featdmf")) { 11670 confp->chan.sig = SIG_FEATDMF; 11671 confp->chan.radio = 0; 11672 } else if (!strcasecmp(v->value, "featdmf_ta")) { 11673 confp->chan.sig = SIG_FEATDMF_TA; 11674 confp->chan.radio = 0; 11675 } else if (!strcasecmp(v->value, "e911")) { 11676 confp->chan.sig = SIG_E911; 11677 confp->chan.radio = 0; 11678 } else if (!strcasecmp(v->value, "fgccama")) { 11679 confp->chan.sig = SIG_FGC_CAMA; 11680 confp->chan.radio = 0; 11681 } else if (!strcasecmp(v->value, "fgccamamf")) { 11682 confp->chan.sig = SIG_FGC_CAMAMF; 11683 confp->chan.radio = 0; 11684 } else if (!strcasecmp(v->value, "featb")) { 11685 confp->chan.sig = SIG_FEATB; 11686 confp->chan.radio = 0; 11687 #ifdef HAVE_PRI 11688 } else if (!strcasecmp(v->value, "pri_net")) { 11689 confp->chan.radio = 0; 11690 confp->chan.sig = SIG_PRI; 11691 confp->pri.nodetype = PRI_NETWORK; 11692 } else if (!strcasecmp(v->value, "pri_cpe")) { 11693 confp->chan.sig = SIG_PRI; 11694 confp->chan.radio = 0; 11695 confp->pri.nodetype = PRI_CPE; 11696 } else if (!strcasecmp(v->value, "gr303fxoks_net")) { 11697 confp->chan.sig = SIG_GR303FXOKS; 11698 confp->chan.radio = 0; 11699 confp->pri.nodetype = PRI_NETWORK; 11700 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) { 11701 confp->chan.sig = SIG_GR303FXSKS; 11702 confp->chan.radio = 0; 11703 confp->pri.nodetype = PRI_CPE; 11704 #endif 11705 } else { 11706 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value); 11707 } 11708 } else if (!strcasecmp(v->name, "outsignalling")) { 11709 if (!strcasecmp(v->value, "em")) { 11710 confp->chan.outsigmod = SIG_EM; 11711 } else if (!strcasecmp(v->value, "em_e1")) { 11712 confp->chan.outsigmod = SIG_EM_E1; 11713 } else if (!strcasecmp(v->value, "em_w")) { 11714 confp->chan.outsigmod = SIG_EMWINK; 11715 } else if (!strcasecmp(v->value, "sf")) { 11716 confp->chan.outsigmod = SIG_SF; 11717 } else if (!strcasecmp(v->value, "sf_w")) { 11718 confp->chan.outsigmod = SIG_SFWINK; 11719 } else if (!strcasecmp(v->value, "sf_featd")) { 11720 confp->chan.outsigmod = SIG_FEATD; 11721 } else if (!strcasecmp(v->value, "sf_featdmf")) { 11722 confp->chan.outsigmod = SIG_FEATDMF; 11723 } else if (!strcasecmp(v->value, "sf_featb")) { 11724 confp->chan.outsigmod = SIG_SF_FEATB; 11725 } else if (!strcasecmp(v->value, "sf")) { 11726 confp->chan.outsigmod = SIG_SF; 11727 } else if (!strcasecmp(v->value, "featd")) { 11728 confp->chan.outsigmod = SIG_FEATD; 11729 } else if (!strcasecmp(v->value, "featdmf")) { 11730 confp->chan.outsigmod = SIG_FEATDMF; 11731 } else if (!strcasecmp(v->value, "featdmf_ta")) { 11732 confp->chan.outsigmod = SIG_FEATDMF_TA; 11733 } else if (!strcasecmp(v->value, "e911")) { 11734 confp->chan.outsigmod = SIG_E911; 11735 } else if (!strcasecmp(v->value, "fgccama")) { 11736 confp->chan.outsigmod = SIG_FGC_CAMA; 11737 } else if (!strcasecmp(v->value, "fgccamamf")) { 11738 confp->chan.outsigmod = SIG_FGC_CAMAMF; 11739 } else if (!strcasecmp(v->value, "featb")) { 11740 confp->chan.outsigmod = SIG_FEATB; 11741 } else { 11742 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value); 11743 } 11744 #ifdef HAVE_PRI 11745 } else if (!strcasecmp(v->name, "pridialplan")) { 11746 if (!strcasecmp(v->value, "national")) { 11747 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1; 11748 } else if (!strcasecmp(v->value, "unknown")) { 11749 confp->pri.dialplan = PRI_UNKNOWN + 1; 11750 } else if (!strcasecmp(v->value, "private")) { 11751 confp->pri.dialplan = PRI_PRIVATE + 1; 11752 } else if (!strcasecmp(v->value, "international")) { 11753 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1; 11754 } else if (!strcasecmp(v->value, "local")) { 11755 confp->pri.dialplan = PRI_LOCAL_ISDN + 1; 11756 } else if (!strcasecmp(v->value, "dynamic")) { 11757 confp->pri.dialplan = -1; 11758 } else { 11759 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 11760 } 11761 } else if (!strcasecmp(v->name, "prilocaldialplan")) { 11762 if (!strcasecmp(v->value, "national")) { 11763 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1; 11764 } else if (!strcasecmp(v->value, "unknown")) { 11765 confp->pri.localdialplan = PRI_UNKNOWN + 1; 11766 } else if (!strcasecmp(v->value, "private")) { 11767 confp->pri.localdialplan = PRI_PRIVATE + 1; 11768 } else if (!strcasecmp(v->value, "international")) { 11769 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1; 11770 } else if (!strcasecmp(v->value, "local")) { 11771 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1; 11772 } else if (!strcasecmp(v->value, "dynamic")) { 11773 confp->pri.localdialplan = -1; 11774 } else { 11775 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 11776 } 11777 } else if (!strcasecmp(v->name, "switchtype")) { 11778 if (!strcasecmp(v->value, "national")) 11779 confp->pri.switchtype = PRI_SWITCH_NI2; 11780 else if (!strcasecmp(v->value, "ni1")) 11781 confp->pri.switchtype = PRI_SWITCH_NI1; 11782 else if (!strcasecmp(v->value, "dms100")) 11783 confp->pri.switchtype = PRI_SWITCH_DMS100; 11784 else if (!strcasecmp(v->value, "4ess")) 11785 confp->pri.switchtype = PRI_SWITCH_ATT4ESS; 11786 else if (!strcasecmp(v->value, "5ess")) 11787 confp->pri.switchtype = PRI_SWITCH_LUCENT5E; 11788 else if (!strcasecmp(v->value, "euroisdn")) 11789 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1; 11790 else if (!strcasecmp(v->value, "qsig")) 11791 confp->pri.switchtype = PRI_SWITCH_QSIG; 11792 else { 11793 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value); 11794 return -1; 11795 } 11796 } else if (!strcasecmp(v->name, "nsf")) { 11797 if (!strcasecmp(v->value, "sdn")) 11798 confp->pri.nsf = PRI_NSF_SDN; 11799 else if (!strcasecmp(v->value, "megacom")) 11800 confp->pri.nsf = PRI_NSF_MEGACOM; 11801 else if (!strcasecmp(v->value, "tollfreemegacom")) 11802 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM; 11803 else if (!strcasecmp(v->value, "accunet")) 11804 confp->pri.nsf = PRI_NSF_ACCUNET; 11805 else if (!strcasecmp(v->value, "none")) 11806 confp->pri.nsf = PRI_NSF_NONE; 11807 else { 11808 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value); 11809 confp->pri.nsf = PRI_NSF_NONE; 11810 } 11811 } else if (!strcasecmp(v->name, "priindication")) { 11812 if (!strcasecmp(v->value, "outofband")) 11813 confp->chan.priindication_oob = 1; 11814 else if (!strcasecmp(v->value, "inband")) 11815 confp->chan.priindication_oob = 0; 11816 else 11817 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n", 11818 v->value, v->lineno); 11819 } else if (!strcasecmp(v->name, "priexclusive")) { 11820 confp->chan.priexclusive = ast_true(v->value); 11821 } else if (!strcasecmp(v->name, "internationalprefix")) { 11822 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix)); 11823 } else if (!strcasecmp(v->name, "nationalprefix")) { 11824 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix)); 11825 } else if (!strcasecmp(v->name, "localprefix")) { 11826 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix)); 11827 } else if (!strcasecmp(v->name, "privateprefix")) { 11828 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix)); 11829 } else if (!strcasecmp(v->name, "unknownprefix")) { 11830 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix)); 11831 } else if (!strcasecmp(v->name, "resetinterval")) { 11832 if (!strcasecmp(v->value, "never")) 11833 confp->pri.resetinterval = -1; 11834 else if (atoi(v->value) >= 60) 11835 confp->pri.resetinterval = atoi(v->value); 11836 else 11837 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n", 11838 v->value, v->lineno); 11839 } else if (!strcasecmp(v->name, "minunused")) { 11840 confp->pri.minunused = atoi(v->value); 11841 } else if (!strcasecmp(v->name, "minidle")) { 11842 confp->pri.minidle = atoi(v->value); 11843 } else if (!strcasecmp(v->name, "idleext")) { 11844 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext)); 11845 } else if (!strcasecmp(v->name, "idledial")) { 11846 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial)); 11847 } else if (!strcasecmp(v->name, "overlapdial")) { 11848 confp->pri.overlapdial = ast_true(v->value); 11849 #ifdef HAVE_PRI_INBANDDISCONNECT 11850 } else if (!strcasecmp(v->name, "inbanddisconnect")) { 11851 confp->pri.inbanddisconnect = ast_true(v->value); 11852 #endif 11853 } else if (!strcasecmp(v->name, "pritimer")) { 11854 #ifdef PRI_GETSET_TIMERS 11855 char *timerc, *c; 11856 int timer, timeridx; 11857 c = v->value; 11858 timerc = strsep(&c, ","); 11859 if (timerc) { 11860 timer = atoi(c); 11861 if (!timer) 11862 ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer\n", timerc); 11863 else { 11864 if ((timeridx = pri_timer2idx(timerc)) >= 0) 11865 pritimers[timeridx] = timer; 11866 else 11867 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer\n", timerc); 11868 } 11869 } else 11870 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string\n", v->value); 11871 11872 } else if (!strcasecmp(v->name, "facilityenable")) { 11873 confp->pri.facilityenable = ast_true(v->value); 11874 #endif /* PRI_GETSET_TIMERS */ 11875 #endif /* HAVE_PRI */ 11876 } else if (!strcasecmp(v->name, "cadence")) { 11877 /* setup to scan our argument */ 11878 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 11879 int i; 11880 struct dahdi_ring_cadence new_cadence; 11881 int cid_location = -1; 11882 int firstcadencepos = 0; 11883 char original_args[80]; 11884 int cadence_is_ok = 1; 11885 11886 ast_copy_string(original_args, v->value, sizeof(original_args)); 11887 /* 16 cadences allowed (8 pairs) */ 11888 element_count = sscanf(v->value, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11], &c[12], &c[13], &c[14], &c[15]); 11889 11890 /* Cadence must be even (on/off) */ 11891 if (element_count % 2 == 1) { 11892 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args); 11893 cadence_is_ok = 0; 11894 } 11895 11896 /* Ring cadences cannot be negative */ 11897 for (i = 0; i < element_count; i++) { 11898 if (c[i] == 0) { 11899 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args); 11900 cadence_is_ok = 0; 11901 break; 11902 } else if (c[i] < 0) { 11903 if (i % 2 == 1) { 11904 /* Silence duration, negative possibly okay */ 11905 if (cid_location == -1) { 11906 cid_location = i; 11907 c[i] *= -1; 11908 } else { 11909 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args); 11910 cadence_is_ok = 0; 11911 break; 11912 } 11913 } else { 11914 if (firstcadencepos == 0) { 11915 firstcadencepos = i; /* only recorded to avoid duplicate specification */ 11916 /* duration will be passed negative to the DAHDI driver */ 11917 } else { 11918 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args); 11919 cadence_is_ok = 0; 11920 break; 11921 } 11922 } 11923 } 11924 } 11925 11926 /* Substitute our scanned cadence */ 11927 for (i = 0; i < 16; i++) { 11928 new_cadence.ringcadence[i] = c[i]; 11929 } 11930 11931 if (cadence_is_ok) { 11932 /* ---we scanned it without getting annoyed; now some sanity checks--- */ 11933 if (element_count < 2) { 11934 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args); 11935 } else { 11936 if (cid_location == -1) { 11937 /* user didn't say; default to first pause */ 11938 cid_location = 1; 11939 } else { 11940 /* convert element_index to cidrings value */ 11941 cid_location = (cid_location + 1) / 2; 11942 } 11943 /* ---we like their cadence; try to install it--- */ 11944 if (!user_has_defined_cadences++) 11945 /* this is the first user-defined cadence; clear the default user cadences */ 11946 num_cadence = 0; 11947 if ((num_cadence+1) >= NUM_CADENCE_MAX) 11948 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args); 11949 else { 11950 cadences[num_cadence] = new_cadence; 11951 cidrings[num_cadence++] = cid_location; 11952 if (option_verbose > 2) 11953 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args); 11954 } 11955 } 11956 } 11957 } else if (!strcasecmp(v->name, "ringtimeout")) { 11958 ringt_base = (atoi(v->value) * 8) / READ_SIZE; 11959 } else if (!strcasecmp(v->name, "prewink")) { 11960 confp->timing.prewinktime = atoi(v->value); 11961 } else if (!strcasecmp(v->name, "preflash")) { 11962 confp->timing.preflashtime = atoi(v->value); 11963 } else if (!strcasecmp(v->name, "wink")) { 11964 confp->timing.winktime = atoi(v->value); 11965 } else if (!strcasecmp(v->name, "flash")) { 11966 confp->timing.flashtime = atoi(v->value); 11967 } else if (!strcasecmp(v->name, "start")) { 11968 confp->timing.starttime = atoi(v->value); 11969 } else if (!strcasecmp(v->name, "rxwink")) { 11970 confp->timing.rxwinktime = atoi(v->value); 11971 } else if (!strcasecmp(v->name, "rxflash")) { 11972 confp->timing.rxflashtime = atoi(v->value); 11973 } else if (!strcasecmp(v->name, "debounce")) { 11974 confp->timing.debouncetime = atoi(v->value); 11975 } else if (!strcasecmp(v->name, "toneduration")) { 11976 int toneduration; 11977 int ctlfd; 11978 int res; 11979 struct dahdi_dialparams dps; 11980 11981 ctlfd = open(DAHDI_FILE_CTL, O_RDWR); 11982 11983 if (ctlfd == -1) { 11984 ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n"); 11985 return -1; 11986 } 11987 11988 toneduration = atoi(v->value); 11989 if (toneduration > -1) { 11990 memset(&dps, 0, sizeof(dps)); 11991 11992 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration; 11993 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps); 11994 if (res < 0) { 11995 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno)); 11996 return -1; 11997 } 11998 } 11999 close(ctlfd); 12000 } else if (!strcasecmp(v->name, "defaultcic")) { 12001 ast_copy_string(defaultcic, v->value, sizeof(defaultcic)); 12002 } else if (!strcasecmp(v->name, "defaultozz")) { 12003 ast_copy_string(defaultozz, v->value, sizeof(defaultozz)); 12004 } 12005 } else if (!skipchannels) 12006 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload)\n", v->name); 12007 } 12008 if (dahdichan[0]) { 12009 /* The user has set 'dahdichan' */ 12010 /*< \todo pass proper line number instead of 0 */ 12011 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) { 12012 return -1; 12013 } 12014 } 12015 /*< \todo why check for the pseudo in the per-channel section. 12016 * Any actual use for manual setup of the pseudo channel? */ 12017 if (!found_pseudo && reload == 0) { 12018 /* use the default configuration for a channel, so 12019 that any settings from real configured channels 12020 don't "leak" into the pseudo channel config 12021 */ 12022 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 12023 12024 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload); 12025 12026 if (tmp) { 12027 if (option_verbose > 2) 12028 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n"); 12029 } else { 12030 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n"); 12031 } 12032 } 12033 return 0; 12034 }
static char* redirectingreason2str | ( | int | redirectingreason | ) | [static] |
Definition at line 8823 of file chan_dahdi.c.
Referenced by __oh323_new().
08824 { 08825 switch (redirectingreason) { 08826 case 0: 08827 return "UNKNOWN"; 08828 case 1: 08829 return "BUSY"; 08830 case 2: 08831 return "NO_REPLY"; 08832 case 0xF: 08833 return "UNCONDITIONAL"; 08834 default: 08835 return "NOREDIRECT"; 08836 } 08837 }
static int reload | ( | void | ) | [static] |
Definition at line 12341 of file chan_dahdi.c.
References ast_log(), and setup_dahdi().
12342 { 12343 int res = 0; 12344 12345 res = setup_dahdi(1); 12346 if (res) { 12347 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n"); 12348 return -1; 12349 } 12350 return 0; 12351 }
static int reset_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1702 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().
01703 { 01704 struct dahdi_confinfo zi; 01705 memset(&zi, 0, sizeof(zi)); 01706 p->confno = -1; 01707 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf)); 01708 if (p->subs[SUB_REAL].dfd > -1) { 01709 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi)) 01710 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno)); 01711 } 01712 return 0; 01713 }
static int restart_monitor | ( | void | ) | [static] |
Definition at line 7461 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().
07462 { 07463 pthread_attr_t attr; 07464 pthread_attr_init(&attr); 07465 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 07466 /* If we're supposed to be stopped -- stay stopped */ 07467 if (monitor_thread == AST_PTHREADT_STOP) 07468 return 0; 07469 ast_mutex_lock(&monlock); 07470 if (monitor_thread == pthread_self()) { 07471 ast_mutex_unlock(&monlock); 07472 ast_log(LOG_WARNING, "Cannot kill myself\n"); 07473 return -1; 07474 } 07475 if (monitor_thread != AST_PTHREADT_NULL) { 07476 /* Wake up the thread */ 07477 pthread_kill(monitor_thread, SIGURG); 07478 } else { 07479 /* Start a new monitor */ 07480 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) { 07481 ast_mutex_unlock(&monlock); 07482 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 07483 pthread_attr_destroy(&attr); 07484 return -1; 07485 } 07486 } 07487 ast_mutex_unlock(&monlock); 07488 pthread_attr_destroy(&attr); 07489 return 0; 07490 }
static int restore_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2035 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().
02036 { 02037 int res; 02038 if (p->saveconf.confmode) { 02039 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf); 02040 p->saveconf.confmode = 0; 02041 if (res) { 02042 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno)); 02043 return -1; 02044 } 02045 } 02046 if (option_debug) 02047 ast_log(LOG_DEBUG, "Restored conferencing\n"); 02048 return 0; 02049 }
static int restore_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1961 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().
01962 { 01963 int res; 01964 01965 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 01966 if (res) { 01967 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno)); 01968 return -1; 01969 } 01970 01971 return 0; 01972 }
static int save_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2007 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().
02008 { 02009 struct dahdi_confinfo c; 02010 int res; 02011 if (p->saveconf.confmode) { 02012 ast_log(LOG_WARNING, "Can't save conference -- already in use\n"); 02013 return -1; 02014 } 02015 p->saveconf.chan = 0; 02016 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf); 02017 if (res) { 02018 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno)); 02019 p->saveconf.confmode = 0; 02020 return -1; 02021 } 02022 c.chan = 0; 02023 c.confno = 0; 02024 c.confmode = DAHDI_CONF_NORMAL; 02025 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c); 02026 if (res) { 02027 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno)); 02028 return -1; 02029 } 02030 if (option_debug) 02031 ast_log(LOG_DEBUG, "Disabled conferencing\n"); 02032 return 0; 02033 }
static int send_callerid | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2075 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().
02076 { 02077 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */ 02078 int res; 02079 /* Take out of linear mode if necessary */ 02080 if (p->subs[SUB_REAL].linear) { 02081 p->subs[SUB_REAL].linear = 0; 02082 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 02083 } 02084 while (p->cidpos < p->cidlen) { 02085 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos); 02086 if (res < 0) { 02087 if (errno == EAGAIN) 02088 return 0; 02089 else { 02090 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 02091 return -1; 02092 } 02093 } 02094 if (!res) 02095 return 0; 02096 p->cidpos += res; 02097 } 02098 free(p->cidspill); 02099 p->cidspill = NULL; 02100 if (p->callwaitcas) { 02101 /* Wait for CID/CW to expire */ 02102 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES; 02103 } else 02104 restore_conference(p); 02105 return 0; 02106 }
static int send_cwcidspill | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2053 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().
02054 { 02055 p->callwaitcas = 0; 02056 p->cidcwexpire = 0; 02057 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) 02058 return -1; 02059 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p)); 02060 /* Make sure we account for the end */ 02061 p->cidlen += READ_SIZE * 4; 02062 p->cidpos = 0; 02063 send_callerid(p); 02064 if (option_verbose > 2) 02065 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num); 02066 return 0; 02067 }
static int send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 2690 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().
02691 { 02692 /* Data will be our digit string */ 02693 struct dahdi_pvt *p; 02694 char *digits = (char *) data; 02695 02696 if (ast_strlen_zero(digits)) { 02697 ast_log(LOG_DEBUG, "No digit string sent to application!\n"); 02698 return -1; 02699 } 02700 02701 p = (struct dahdi_pvt *)chan->tech_pvt; 02702 02703 if (!p) { 02704 ast_log(LOG_DEBUG, "Unable to find technology private\n"); 02705 return -1; 02706 } 02707 02708 ast_mutex_lock(&p->lock); 02709 02710 if (!p->pri || !p->call) { 02711 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n"); 02712 ast_mutex_unlock(&p->lock); 02713 return -1; 02714 } 02715 02716 if (!pri_grab(p, p->pri)) { 02717 pri_keypad_facility(p->pri->pri, p->call, digits); 02718 pri_rel(p->pri); 02719 } else { 02720 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n"); 02721 ast_mutex_unlock(&p->lock); 02722 return -1; 02723 } 02724 02725 ast_mutex_unlock(&p->lock); 02726 02727 return 0; 02728 }
static int set_actual_gain | ( | int | fd, | |
int | chan, | |||
float | rxgain, | |||
float | txgain, | |||
int | law | |||
) | [static] |
Definition at line 1942 of file chan_dahdi.c.
References set_actual_rxgain(), and set_actual_txgain().
Referenced by bump_gains(), dahdi_call(), and restore_gains().
01943 { 01944 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law); 01945 }
static int set_actual_rxgain | ( | int | fd, | |
int | chan, | |||
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 1924 of file chan_dahdi.c.
References ast_log(), errno, fill_rxgain(), and LOG_DEBUG.
Referenced by dahdi_setoption(), and set_actual_gain().
01925 { 01926 struct dahdi_gains g; 01927 int res; 01928 01929 memset(&g, 0, sizeof(g)); 01930 g.chan = chan; 01931 res = ioctl(fd, DAHDI_GETGAINS, &g); 01932 if (res) { 01933 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno)); 01934 return res; 01935 } 01936 01937 fill_rxgain(&g, gain, law); 01938 01939 return ioctl(fd, DAHDI_SETGAINS, &g); 01940 }
static int set_actual_txgain | ( | int | fd, | |
int | chan, | |||
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 1905 of file chan_dahdi.c.
References ast_log(), errno, fill_txgain(), LOG_DEBUG, and option_debug.
Referenced by dahdi_setoption(), and set_actual_gain().
01906 { 01907 struct dahdi_gains g; 01908 int res; 01909 01910 memset(&g, 0, sizeof(g)); 01911 g.chan = chan; 01912 res = ioctl(fd, DAHDI_GETGAINS, &g); 01913 if (res) { 01914 if (option_debug) 01915 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno)); 01916 return res; 01917 } 01918 01919 fill_txgain(&g, gain, law); 01920 01921 return ioctl(fd, DAHDI_SETGAINS, &g); 01922 }
static int setup_dahdi | ( | int | reload | ) | [static] |
Definition at line 12036 of file chan_dahdi.c.
References ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verbose(), CHAN_ZAP_MODE, dahdi_chan_conf_default(), dahdi_chan_mode, default_jbconf, global_jbconf, iflock, ast_variable::lineno, LOG_ERROR, ast_variable::name, ast_variable::next, NUM_SPANS, option_verbose, pri_create_spanmap(), pri_create_trunkgroup(), pris, process_dahdi(), restart_monitor(), start_pri(), ast_variable::value, and VERBOSE_PREFIX_2.
Referenced by dahdi_restart(), load_module(), and reload().
12037 { 12038 struct ast_config *cfg; 12039 struct ast_variable *v; 12040 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 12041 int res; 12042 12043 #ifdef HAVE_PRI 12044 char *c; 12045 int spanno; 12046 int i, x; 12047 int logicalspan; 12048 int trunkgroup; 12049 int dchannels[NUM_DCHANS]; 12050 #endif 12051 12052 #ifdef HAVE_ZAPTEL 12053 int load_from_zapata_conf = 1; 12054 #else 12055 int load_from_zapata_conf = (dahdi_chan_mode == CHAN_ZAP_MODE); 12056 #endif 12057 12058 if (load_from_zapata_conf) { 12059 if (!(cfg = ast_config_load("zapata.conf"))) { 12060 ast_log(LOG_ERROR, "Unable to load zapata.conf\n"); 12061 return 0; 12062 } 12063 } else { 12064 if (!(cfg = ast_config_load("chan_dahdi.conf"))) { 12065 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n"); 12066 return 0; 12067 } 12068 } 12069 12070 /* It's a little silly to lock it, but we mind as well just to be sure */ 12071 ast_mutex_lock(&iflock); 12072 #ifdef HAVE_PRI 12073 if (reload != 1) { 12074 /* Process trunkgroups first */ 12075 v = ast_variable_browse(cfg, "trunkgroups"); 12076 while (v) { 12077 if (!strcasecmp(v->name, "trunkgroup")) { 12078 trunkgroup = atoi(v->value); 12079 if (trunkgroup > 0) { 12080 if ((c = strchr(v->value, ','))) { 12081 i = 0; 12082 memset(dchannels, 0, sizeof(dchannels)); 12083 while (c && (i < NUM_DCHANS)) { 12084 dchannels[i] = atoi(c + 1); 12085 if (dchannels[i] < 0) { 12086 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); 12087 } else 12088 i++; 12089 c = strchr(c + 1, ','); 12090 } 12091 if (i) { 12092 if (pri_create_trunkgroup(trunkgroup, dchannels)) { 12093 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); 12094 } else if (option_verbose > 1) 12095 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"); 12096 } else 12097 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 12098 } else 12099 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 12100 } else 12101 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno); 12102 } else if (!strcasecmp(v->name, "spanmap")) { 12103 spanno = atoi(v->value); 12104 if (spanno > 0) { 12105 if ((c = strchr(v->value, ','))) { 12106 trunkgroup = atoi(c + 1); 12107 if (trunkgroup > 0) { 12108 if ((c = strchr(c + 1, ','))) 12109 logicalspan = atoi(c + 1); 12110 else 12111 logicalspan = 0; 12112 if (logicalspan >= 0) { 12113 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { 12114 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 12115 } else if (option_verbose > 1) 12116 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 12117 } else 12118 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); 12119 } else 12120 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno); 12121 } else 12122 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno); 12123 } else 12124 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno); 12125 } else { 12126 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); 12127 } 12128 v = v->next; 12129 } 12130 } 12131 #endif 12132 12133 /* Copy the default jb config over global_jbconf */ 12134 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 12135 12136 v = ast_variable_browse(cfg, "channels"); 12137 res = process_dahdi(&conf, "", v, reload, 0); 12138 ast_mutex_unlock(&iflock); 12139 ast_config_destroy(cfg); 12140 if (res) 12141 return res; 12142 cfg = ast_config_load("users.conf"); 12143 if (cfg) { 12144 char *cat; 12145 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1); 12146 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) { 12147 if (!strcasecmp(cat, "general")) 12148 continue; 12149 if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) { 12150 struct dahdi_chan_conf sect_conf; 12151 memcpy(§_conf, &conf, sizeof(sect_conf)); 12152 12153 process_dahdi(§_conf, cat, ast_variable_browse(cfg, cat), reload, 0); 12154 } 12155 } 12156 ast_config_destroy(cfg); 12157 } 12158 #ifdef HAVE_PRI 12159 if (reload != 1) { 12160 for (x = 0; x < NUM_SPANS; x++) { 12161 if (pris[x].pvts[0]) { 12162 if (start_pri(pris + x)) { 12163 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1); 12164 return -1; 12165 } else if (option_verbose > 1) 12166 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1); 12167 } 12168 } 12169 } 12170 #endif 12171 /* And start the monitor for the first time */ 12172 restart_monitor(); 12173 return 0; 12174 }
static void * ss_thread | ( | void * | data | ) | [static] |
Definition at line 5881 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().
05882 { 05883 struct ast_channel *chan = data; 05884 struct dahdi_pvt *p = chan->tech_pvt; 05885 char exten[AST_MAX_EXTENSION] = ""; 05886 char exten2[AST_MAX_EXTENSION] = ""; 05887 unsigned char buf[256]; 05888 char dtmfcid[300]; 05889 char dtmfbuf[300]; 05890 struct callerid_state *cs = NULL; 05891 char *name = NULL, *number = NULL; 05892 int distMatches; 05893 int curRingData[3]; 05894 int receivedRingT; 05895 int counter1; 05896 int counter; 05897 int samples = 0; 05898 struct ast_smdi_md_message *smdi_msg = NULL; 05899 int flags; 05900 int i; 05901 int timeout; 05902 int getforward = 0; 05903 char *s1, *s2; 05904 int len = 0; 05905 int res; 05906 int index; 05907 05908 ast_mutex_lock(&ss_thread_lock); 05909 ss_thread_count++; 05910 ast_mutex_unlock(&ss_thread_lock); 05911 /* in the bizarre case where the channel has become a zombie before we 05912 even get started here, abort safely 05913 */ 05914 if (!p) { 05915 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name); 05916 ast_hangup(chan); 05917 goto quit; 05918 } 05919 if (option_verbose > 2) 05920 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name); 05921 index = dahdi_get_index(chan, p, 1); 05922 if (index < 0) { 05923 ast_log(LOG_WARNING, "Huh?\n"); 05924 ast_hangup(chan); 05925 goto quit; 05926 } 05927 if (p->dsp) 05928 ast_dsp_digitreset(p->dsp); 05929 switch (p->sig) { 05930 #ifdef HAVE_PRI 05931 case SIG_PRI: 05932 /* Now loop looking for an extension */ 05933 ast_copy_string(exten, p->exten, sizeof(exten)); 05934 len = strlen(exten); 05935 res = 0; 05936 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 05937 if (len && !ast_ignore_pattern(chan->context, exten)) 05938 tone_zone_play_tone(p->subs[index].dfd, -1); 05939 else 05940 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 05941 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) 05942 timeout = matchdigittimeout; 05943 else 05944 timeout = gendigittimeout; 05945 res = ast_waitfordigit(chan, timeout); 05946 if (res < 0) { 05947 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 05948 ast_hangup(chan); 05949 goto quit; 05950 } else if (res) { 05951 exten[len++] = res; 05952 exten[len] = '\0'; 05953 } else 05954 break; 05955 } 05956 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */ 05957 if (ast_strlen_zero(exten)) { 05958 if (option_verbose > 2) 05959 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n"); 05960 exten[0] = 's'; 05961 exten[1] = '\0'; 05962 } 05963 tone_zone_play_tone(p->subs[index].dfd, -1); 05964 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) { 05965 /* Start the real PBX */ 05966 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 05967 if (p->dsp) ast_dsp_digitreset(p->dsp); 05968 dahdi_enable_ec(p); 05969 ast_setstate(chan, AST_STATE_RING); 05970 res = ast_pbx_run(chan); 05971 if (res) { 05972 ast_log(LOG_WARNING, "PBX exited non-zero!\n"); 05973 } 05974 } else { 05975 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context); 05976 chan->hangupcause = AST_CAUSE_UNALLOCATED; 05977 ast_hangup(chan); 05978 p->exten[0] = '\0'; 05979 /* Since we send release complete here, we won't get one */ 05980 p->call = NULL; 05981 } 05982 goto quit; 05983 break; 05984 #endif 05985 case SIG_FEATD: 05986 case SIG_FEATDMF: 05987 case SIG_FEATDMF_TA: 05988 case SIG_E911: 05989 case SIG_FGC_CAMAMF: 05990 case SIG_FEATB: 05991 case SIG_EMWINK: 05992 case SIG_SF_FEATD: 05993 case SIG_SF_FEATDMF: 05994 case SIG_SF_FEATB: 05995 case SIG_SFWINK: 05996 if (dahdi_wink(p, index)) 05997 goto quit; 05998 /* Fall through */ 05999 case SIG_EM: 06000 case SIG_EM_E1: 06001 case SIG_SF: 06002 case SIG_FGC_CAMA: 06003 res = tone_zone_play_tone(p->subs[index].dfd, -1); 06004 if (p->dsp) 06005 ast_dsp_digitreset(p->dsp); 06006 /* set digit mode appropriately */ 06007 if (p->dsp) { 06008 if (NEED_MFDETECT(p)) 06009 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 06010 else 06011 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 06012 } 06013 memset(dtmfbuf, 0, sizeof(dtmfbuf)); 06014 /* Wait for the first digit only if immediate=no */ 06015 if (!p->immediate) 06016 /* Wait for the first digit (up to 5 seconds). */ 06017 res = ast_waitfordigit(chan, 5000); 06018 else 06019 res = 0; 06020 if (res > 0) { 06021 /* save first char */ 06022 dtmfbuf[0] = res; 06023 switch (p->sig) { 06024 case SIG_FEATD: 06025 case SIG_SF_FEATD: 06026 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06027 if (res > 0) 06028 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06029 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06030 break; 06031 case SIG_FEATDMF_TA: 06032 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06033 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06034 if (dahdi_wink(p, index)) goto quit; 06035 dtmfbuf[0] = 0; 06036 /* Wait for the first digit (up to 5 seconds). */ 06037 res = ast_waitfordigit(chan, 5000); 06038 if (res <= 0) break; 06039 dtmfbuf[0] = res; 06040 /* fall through intentionally */ 06041 case SIG_FEATDMF: 06042 case SIG_E911: 06043 case SIG_FGC_CAMAMF: 06044 case SIG_SF_FEATDMF: 06045 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06046 /* if international caca, do it again to get real ANO */ 06047 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14)) 06048 { 06049 if (dahdi_wink(p, index)) goto quit; 06050 dtmfbuf[0] = 0; 06051 /* Wait for the first digit (up to 5 seconds). */ 06052 res = ast_waitfordigit(chan, 5000); 06053 if (res <= 0) break; 06054 dtmfbuf[0] = res; 06055 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06056 } 06057 if (res > 0) { 06058 /* if E911, take off hook */ 06059 if (p->sig == SIG_E911) 06060 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06061 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000); 06062 } 06063 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06064 break; 06065 case SIG_FEATB: 06066 case SIG_SF_FEATB: 06067 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06068 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06069 break; 06070 case SIG_EMWINK: 06071 /* if we received a '*', we are actually receiving Feature Group D 06072 dial syntax, so use that mode; otherwise, fall through to normal 06073 mode 06074 */ 06075 if (res == '*') { 06076 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06077 if (res > 0) 06078 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06079 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06080 break; 06081 } 06082 default: 06083 /* If we got the first digit, get the rest */ 06084 len = 1; 06085 dtmfbuf[len] = '\0'; 06086 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06087 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06088 timeout = matchdigittimeout; 06089 } else { 06090 timeout = gendigittimeout; 06091 } 06092 res = ast_waitfordigit(chan, timeout); 06093 if (res < 0) { 06094 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 06095 ast_hangup(chan); 06096 goto quit; 06097 } else if (res) { 06098 dtmfbuf[len++] = res; 06099 dtmfbuf[len] = '\0'; 06100 } else { 06101 break; 06102 } 06103 } 06104 break; 06105 } 06106 } 06107 if (res == -1) { 06108 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno)); 06109 ast_hangup(chan); 06110 goto quit; 06111 } else if (res < 0) { 06112 ast_log(LOG_DEBUG, "Got hung up before digits finished\n"); 06113 ast_hangup(chan); 06114 goto quit; 06115 } 06116 06117 if (p->sig == SIG_FGC_CAMA) { 06118 char anibuf[100]; 06119 06120 if (ast_safe_sleep(chan,1000) == -1) { 06121 ast_hangup(chan); 06122 goto quit; 06123 } 06124 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06125 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 06126 res = my_getsigstr(chan, anibuf, "#", 10000); 06127 if ((res > 0) && (strlen(anibuf) > 2)) { 06128 if (anibuf[strlen(anibuf) - 1] == '#') 06129 anibuf[strlen(anibuf) - 1] = 0; 06130 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2); 06131 } 06132 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 06133 } 06134 06135 ast_copy_string(exten, dtmfbuf, sizeof(exten)); 06136 if (ast_strlen_zero(exten)) 06137 ast_copy_string(exten, "s", sizeof(exten)); 06138 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) { 06139 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */ 06140 if (exten[0] == '*') { 06141 char *stringp=NULL; 06142 ast_copy_string(exten2, exten, sizeof(exten2)); 06143 /* Parse out extension and callerid */ 06144 stringp=exten2 +1; 06145 s1 = strsep(&stringp, "*"); 06146 s2 = strsep(&stringp, "*"); 06147 if (s2) { 06148 if (!ast_strlen_zero(p->cid_num)) 06149 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 06150 else 06151 ast_set_callerid(chan, s1, NULL, s1); 06152 ast_copy_string(exten, s2, sizeof(exten)); 06153 } else 06154 ast_copy_string(exten, s1, sizeof(exten)); 06155 } else if (p->sig == SIG_FEATD) 06156 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 06157 } 06158 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 06159 if (exten[0] == '*') { 06160 char *stringp=NULL; 06161 ast_copy_string(exten2, exten, sizeof(exten2)); 06162 /* Parse out extension and callerid */ 06163 stringp=exten2 +1; 06164 s1 = strsep(&stringp, "#"); 06165 s2 = strsep(&stringp, "#"); 06166 if (s2) { 06167 if (!ast_strlen_zero(p->cid_num)) 06168 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 06169 else 06170 if (*(s1 + 2)) 06171 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2); 06172 ast_copy_string(exten, s2 + 1, sizeof(exten)); 06173 } else 06174 ast_copy_string(exten, s1 + 2, sizeof(exten)); 06175 } else 06176 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 06177 } 06178 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) { 06179 if (exten[0] == '*') { 06180 char *stringp=NULL; 06181 ast_copy_string(exten2, exten, sizeof(exten2)); 06182 /* Parse out extension and callerid */ 06183 stringp=exten2 +1; 06184 s1 = strsep(&stringp, "#"); 06185 s2 = strsep(&stringp, "#"); 06186 if (s2 && (*(s2 + 1) == '0')) { 06187 if (*(s2 + 2)) 06188 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2); 06189 } 06190 if (s1) ast_copy_string(exten, s1, sizeof(exten)); 06191 else ast_copy_string(exten, "911", sizeof(exten)); 06192 } else 06193 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel); 06194 } 06195 if (p->sig == SIG_FEATB) { 06196 if (exten[0] == '*') { 06197 char *stringp=NULL; 06198 ast_copy_string(exten2, exten, sizeof(exten2)); 06199 /* Parse out extension and callerid */ 06200 stringp=exten2 +1; 06201 s1 = strsep(&stringp, "#"); 06202 ast_copy_string(exten, exten2 + 1, sizeof(exten)); 06203 } else 06204 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel); 06205 } 06206 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 06207 dahdi_wink(p, index); 06208 /* some switches require a minimum guard time between 06209 the last FGD wink and something that answers 06210 immediately. This ensures it */ 06211 if (ast_safe_sleep(chan,100)) goto quit; 06212 } 06213 dahdi_enable_ec(p); 06214 if (NEED_MFDETECT(p)) { 06215 if (p->dsp) { 06216 if (!p->hardwaredtmf) 06217 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 06218 else { 06219 ast_dsp_free(p->dsp); 06220 p->dsp = NULL; 06221 } 06222 } 06223 } 06224 06225 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) { 06226 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06227 if (p->dsp) ast_dsp_digitreset(p->dsp); 06228 res = ast_pbx_run(chan); 06229 if (res) { 06230 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 06231 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06232 } 06233 goto quit; 06234 } else { 06235 if (option_verbose > 2) 06236 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context); 06237 sleep(2); 06238 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO); 06239 if (res < 0) 06240 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel); 06241 else 06242 sleep(1); 06243 res = ast_streamfile(chan, "ss-noservice", chan->language); 06244 if (res >= 0) 06245 ast_waitstream(chan, ""); 06246 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06247 ast_hangup(chan); 06248 goto quit; 06249 } 06250 break; 06251 case SIG_FXOLS: 06252 case SIG_FXOGS: 06253 case SIG_FXOKS: 06254 /* Read the first digit */ 06255 timeout = firstdigittimeout; 06256 /* If starting a threeway call, never timeout on the first digit so someone 06257 can use flash-hook as a "hold" feature */ 06258 if (p->subs[SUB_THREEWAY].owner) 06259 timeout = 999999; 06260 while (len < AST_MAX_EXTENSION-1) { 06261 /* Read digit unless it's supposed to be immediate, in which case the 06262 only answer is 's' */ 06263 if (p->immediate) 06264 res = 's'; 06265 else 06266 res = ast_waitfordigit(chan, timeout); 06267 timeout = 0; 06268 if (res < 0) { 06269 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 06270 res = tone_zone_play_tone(p->subs[index].dfd, -1); 06271 ast_hangup(chan); 06272 goto quit; 06273 } else if (res) { 06274 exten[len++]=res; 06275 exten[len] = '\0'; 06276 } 06277 if (!ast_ignore_pattern(chan->context, exten)) 06278 tone_zone_play_tone(p->subs[index].dfd, -1); 06279 else 06280 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 06281 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) { 06282 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 06283 if (getforward) { 06284 /* Record this as the forwarding extension */ 06285 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 06286 if (option_verbose > 2) 06287 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel); 06288 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06289 if (res) 06290 break; 06291 usleep(500000); 06292 res = tone_zone_play_tone(p->subs[index].dfd, -1); 06293 sleep(1); 06294 memset(exten, 0, sizeof(exten)); 06295 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 06296 len = 0; 06297 getforward = 0; 06298 } else { 06299 res = tone_zone_play_tone(p->subs[index].dfd, -1); 06300 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06301 if (!ast_strlen_zero(p->cid_num)) { 06302 if (!p->hidecallerid) 06303 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 06304 else 06305 ast_set_callerid(chan, NULL, NULL, p->cid_num); 06306 } 06307 if (!ast_strlen_zero(p->cid_name)) { 06308 if (!p->hidecallerid) 06309 ast_set_callerid(chan, NULL, p->cid_name, NULL); 06310 } 06311 ast_setstate(chan, AST_STATE_RING); 06312 dahdi_enable_ec(p); 06313 res = ast_pbx_run(chan); 06314 if (res) { 06315 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 06316 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06317 } 06318 goto quit; 06319 } 06320 } else { 06321 /* It's a match, but they just typed a digit, and there is an ambiguous match, 06322 so just set the timeout to matchdigittimeout and wait some more */ 06323 timeout = matchdigittimeout; 06324 } 06325 } else if (res == 0) { 06326 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n"); 06327 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06328 dahdi_wait_event(p->subs[index].dfd); 06329 ast_hangup(chan); 06330 goto quit; 06331 } else if (p->callwaiting && !strcmp(exten, "*70")) { 06332 if (option_verbose > 2) 06333 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name); 06334 /* Disable call waiting if enabled */ 06335 p->callwaiting = 0; 06336 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06337 if (res) { 06338 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 06339 chan->name, strerror(errno)); 06340 } 06341 len = 0; 06342 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len); 06343 memset(exten, 0, sizeof(exten)); 06344 timeout = firstdigittimeout; 06345 06346 } else if (!strcmp(exten,ast_pickup_ext())) { 06347 /* Scan all channels and see if there are any 06348 * ringing channels that have call groups 06349 * that equal this channels pickup group 06350 */ 06351 if (index == SUB_REAL) { 06352 /* Switch us from Third call to Call Wait */ 06353 if (p->subs[SUB_THREEWAY].owner) { 06354 /* If you make a threeway call and the *8# a call, it should actually 06355 look like a callwait */ 06356 alloc_sub(p, SUB_CALLWAIT); 06357 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 06358 unalloc_sub(p, SUB_THREEWAY); 06359 } 06360 dahdi_enable_ec(p); 06361 if (ast_pickup_call(chan)) { 06362 ast_log(LOG_DEBUG, "No call pickup possible...\n"); 06363 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06364 dahdi_wait_event(p->subs[index].dfd); 06365 } 06366 ast_hangup(chan); 06367 goto quit; 06368 } else { 06369 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n"); 06370 ast_hangup(chan); 06371 goto quit; 06372 } 06373 06374 } else if (!p->hidecallerid && !strcmp(exten, "*67")) { 06375 if (option_verbose > 2) 06376 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name); 06377 /* Disable Caller*ID if enabled */ 06378 p->hidecallerid = 1; 06379 if (chan->cid.cid_num) 06380 free(chan->cid.cid_num); 06381 chan->cid.cid_num = NULL; 06382 if (chan->cid.cid_name) 06383 free(chan->cid.cid_name); 06384 chan->cid.cid_name = NULL; 06385 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06386 if (res) { 06387 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 06388 chan->name, strerror(errno)); 06389 } 06390 len = 0; 06391 memset(exten, 0, sizeof(exten)); 06392 timeout = firstdigittimeout; 06393 } else if (p->callreturn && !strcmp(exten, "*69")) { 06394 res = 0; 06395 if (!ast_strlen_zero(p->lastcid_num)) { 06396 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language); 06397 } 06398 if (!res) 06399 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06400 break; 06401 } else if (!strcmp(exten, "*78")) { 06402 /* Do not disturb */ 06403 if (option_verbose > 2) 06404 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel); 06405 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 06406 "Channel: %s/%d\r\n" 06407 "Status: enabled\r\n", dahdi_chan_name, p->channel); 06408 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06409 p->dnd = 1; 06410 getforward = 0; 06411 memset(exten, 0, sizeof(exten)); 06412 len = 0; 06413 } else if (!strcmp(exten, "*79")) { 06414 /* Do not disturb */ 06415 if (option_verbose > 2) 06416 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel); 06417 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 06418 "Channel: %s/%d\r\n" 06419 "Status: disabled\r\n", dahdi_chan_name, p->channel); 06420 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06421 p->dnd = 0; 06422 getforward = 0; 06423 memset(exten, 0, sizeof(exten)); 06424 len = 0; 06425 } else if (p->cancallforward && !strcmp(exten, "*72")) { 06426 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06427 getforward = 1; 06428 memset(exten, 0, sizeof(exten)); 06429 len = 0; 06430 } else if (p->cancallforward && !strcmp(exten, "*73")) { 06431 if (option_verbose > 2) 06432 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel); 06433 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06434 memset(p->call_forward, 0, sizeof(p->call_forward)); 06435 getforward = 0; 06436 memset(exten, 0, sizeof(exten)); 06437 len = 0; 06438 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 06439 p->subs[SUB_THREEWAY].owner && 06440 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 06441 /* This is a three way call, the main call being a real channel, 06442 and we're parking the first call. */ 06443 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL); 06444 if (option_verbose > 2) 06445 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name); 06446 break; 06447 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) { 06448 if (option_verbose > 2) 06449 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num); 06450 res = ast_db_put("blacklist", p->lastcid_num, "1"); 06451 if (!res) { 06452 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06453 memset(exten, 0, sizeof(exten)); 06454 len = 0; 06455 } 06456 } else if (p->hidecallerid && !strcmp(exten, "*82")) { 06457 if (option_verbose > 2) 06458 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name); 06459 /* Enable Caller*ID if enabled */ 06460 p->hidecallerid = 0; 06461 if (chan->cid.cid_num) 06462 free(chan->cid.cid_num); 06463 chan->cid.cid_num = NULL; 06464 if (chan->cid.cid_name) 06465 free(chan->cid.cid_name); 06466 chan->cid.cid_name = NULL; 06467 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 06468 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06469 if (res) { 06470 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 06471 chan->name, strerror(errno)); 06472 } 06473 len = 0; 06474 memset(exten, 0, sizeof(exten)); 06475 timeout = firstdigittimeout; 06476 } else if (!strcmp(exten, "*0")) { 06477 struct ast_channel *nbridge = 06478 p->subs[SUB_THREEWAY].owner; 06479 struct dahdi_pvt *pbridge = NULL; 06480 /* set up the private struct of the bridged one, if any */ 06481 if (nbridge && ast_bridged_channel(nbridge)) 06482 pbridge = ast_bridged_channel(nbridge)->tech_pvt; 06483 if (nbridge && pbridge && 06484 (nbridge->tech == chan_tech) && 06485 (ast_bridged_channel(nbridge)->tech == chan_tech) && 06486 ISTRUNK(pbridge)) { 06487 int func = DAHDI_FLASH; 06488 /* Clear out the dial buffer */ 06489 p->dop.dialstr[0] = '\0'; 06490 /* flash hookswitch */ 06491 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 06492 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 06493 nbridge->name, strerror(errno)); 06494 } 06495 swap_subs(p, SUB_REAL, SUB_THREEWAY); 06496 unalloc_sub(p, SUB_THREEWAY); 06497 p->owner = p->subs[SUB_REAL].owner; 06498 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 06499 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 06500 ast_hangup(chan); 06501 goto quit; 06502 } else { 06503 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06504 dahdi_wait_event(p->subs[index].dfd); 06505 tone_zone_play_tone(p->subs[index].dfd, -1); 06506 swap_subs(p, SUB_REAL, SUB_THREEWAY); 06507 unalloc_sub(p, SUB_THREEWAY); 06508 p->owner = p->subs[SUB_REAL].owner; 06509 ast_hangup(chan); 06510 goto quit; 06511 } 06512 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) && 06513 ((exten[0] != '*') || (strlen(exten) > 2))) { 06514 if (option_debug) 06515 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); 06516 break; 06517 } 06518 if (!timeout) 06519 timeout = gendigittimeout; 06520 if (len && !ast_ignore_pattern(chan->context, exten)) 06521 tone_zone_play_tone(p->subs[index].dfd, -1); 06522 } 06523 break; 06524 case SIG_FXSLS: 06525 case SIG_FXSGS: 06526 case SIG_FXSKS: 06527 #ifdef HAVE_PRI 06528 if (p->pri) { 06529 /* This is a GR-303 trunk actually. Wait for the first ring... */ 06530 struct ast_frame *f; 06531 int res; 06532 time_t start; 06533 06534 time(&start); 06535 ast_setstate(chan, AST_STATE_RING); 06536 while (time(NULL) < start + 3) { 06537 res = ast_waitfor(chan, 1000); 06538 if (res) { 06539 f = ast_read(chan); 06540 if (!f) { 06541 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n"); 06542 ast_hangup(chan); 06543 goto quit; 06544 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) { 06545 res = 1; 06546 } else 06547 res = 0; 06548 ast_frfree(f); 06549 if (res) { 06550 ast_log(LOG_DEBUG, "Got ring!\n"); 06551 res = 0; 06552 break; 06553 } 06554 } 06555 } 06556 } 06557 #endif 06558 /* check for SMDI messages */ 06559 if (p->use_smdi && p->smdi_iface) { 06560 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); 06561 06562 if (smdi_msg != NULL) { 06563 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten)); 06564 06565 if (smdi_msg->type == 'B') 06566 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b"); 06567 else if (smdi_msg->type == 'N') 06568 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u"); 06569 06570 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name); 06571 } else { 06572 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n"); 06573 } 06574 } 06575 06576 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) { 06577 number = smdi_msg->calling_st; 06578 06579 /* If we want caller id, we're in a prering state due to a polarity reversal 06580 * and we're set to use a polarity reversal to trigger the start of caller id, 06581 * grab the caller id and wait for ringing to start... */ 06582 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) { 06583 /* If set to use DTMF CID signalling, listen for DTMF */ 06584 if (p->cid_signalling == CID_SIG_DTMF) { 06585 int i = 0; 06586 cs = NULL; 06587 ast_log(LOG_DEBUG, "Receiving DTMF cid on " 06588 "channel %s\n", chan->name); 06589 dahdi_setlinear(p->subs[index].dfd, 0); 06590 res = 2000; 06591 for (;;) { 06592 struct ast_frame *f; 06593 res = ast_waitfor(chan, res); 06594 if (res <= 0) { 06595 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 06596 "Exiting simple switch\n"); 06597 ast_hangup(chan); 06598 goto quit; 06599 } 06600 f = ast_read(chan); 06601 if (!f) 06602 break; 06603 if (f->frametype == AST_FRAME_DTMF) { 06604 dtmfbuf[i++] = f->subclass; 06605 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass); 06606 res = 2000; 06607 } 06608 ast_frfree(f); 06609 if (chan->_state == AST_STATE_RING || 06610 chan->_state == AST_STATE_RINGING) 06611 break; /* Got ring */ 06612 } 06613 dtmfbuf[i] = '\0'; 06614 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06615 /* Got cid and ring. */ 06616 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf); 06617 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 06618 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 06619 dtmfcid, flags); 06620 /* If first byte is NULL, we have no cid */ 06621 if (!ast_strlen_zero(dtmfcid)) 06622 number = dtmfcid; 06623 else 06624 number = NULL; 06625 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 06626 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { 06627 cs = callerid_new(p->cid_signalling); 06628 if (cs) { 06629 samples = 0; 06630 #if 1 06631 bump_gains(p); 06632 #endif 06633 /* Take out of linear mode for Caller*ID processing */ 06634 dahdi_setlinear(p->subs[index].dfd, 0); 06635 06636 /* First we wait and listen for the Caller*ID */ 06637 for (;;) { 06638 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 06639 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 06640 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 06641 callerid_free(cs); 06642 ast_hangup(chan); 06643 goto quit; 06644 } 06645 if (i & DAHDI_IOMUX_SIGEVENT) { 06646 res = dahdi_get_event(p->subs[index].dfd); 06647 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 06648 06649 if (p->cid_signalling == CID_SIG_V23_JP) { 06650 #ifdef DAHDI_EVENT_RINGBEGIN 06651 if (res == DAHDI_EVENT_RINGBEGIN) { 06652 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06653 usleep(1); 06654 } 06655 #endif 06656 } else { 06657 res = 0; 06658 break; 06659 } 06660 } else if (i & DAHDI_IOMUX_READ) { 06661 res = read(p->subs[index].dfd, buf, sizeof(buf)); 06662 if (res < 0) { 06663 if (errno != ELAST) { 06664 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 06665 callerid_free(cs); 06666 ast_hangup(chan); 06667 goto quit; 06668 } 06669 break; 06670 } 06671 samples += res; 06672 06673 if (p->cid_signalling == CID_SIG_V23_JP) { 06674 res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); 06675 } else { 06676 res = callerid_feed(cs, buf, res, AST_LAW(p)); 06677 } 06678 06679 if (res < 0) { 06680 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name); 06681 break; 06682 } else if (res) 06683 break; 06684 else if (samples > (8000 * 10)) 06685 break; 06686 } 06687 } 06688 if (res == 1) { 06689 callerid_get(cs, &name, &number, &flags); 06690 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 06691 } 06692 06693 if (p->cid_signalling == CID_SIG_V23_JP) { 06694 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 06695 usleep(1); 06696 res = 4000; 06697 } else { 06698 06699 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 06700 res = 2000; 06701 } 06702 06703 for (;;) { 06704 struct ast_frame *f; 06705 res = ast_waitfor(chan, res); 06706 if (res <= 0) { 06707 ast_log(LOG_WARNING, "CID timed out waiting for ring. " 06708 "Exiting simple switch\n"); 06709 ast_hangup(chan); 06710 goto quit; 06711 } 06712 if (!(f = ast_read(chan))) { 06713 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); 06714 ast_hangup(chan); 06715 goto quit; 06716 } 06717 ast_frfree(f); 06718 if (chan->_state == AST_STATE_RING || 06719 chan->_state == AST_STATE_RINGING) 06720 break; /* Got ring */ 06721 } 06722 06723 /* We must have a ring by now, so, if configured, lets try to listen for 06724 * distinctive ringing */ 06725 if (p->usedistinctiveringdetection) { 06726 len = 0; 06727 distMatches = 0; 06728 /* Clear the current ring data array so we dont have old data in it. */ 06729 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++) 06730 curRingData[receivedRingT] = 0; 06731 receivedRingT = 0; 06732 counter = 0; 06733 counter1 = 0; 06734 /* Check to see if context is what it should be, if not set to be. */ 06735 if (strcmp(p->context,p->defcontext) != 0) { 06736 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 06737 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 06738 } 06739 06740 for (;;) { 06741 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 06742 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 06743 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 06744 callerid_free(cs); 06745 ast_hangup(chan); 06746 goto quit; 06747 } 06748 if (i & DAHDI_IOMUX_SIGEVENT) { 06749 res = dahdi_get_event(p->subs[index].dfd); 06750 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 06751 res = 0; 06752 /* Let us detect distinctive ring */ 06753 06754 curRingData[receivedRingT] = p->ringt; 06755 06756 if (p->ringt < p->ringt_base/2) 06757 break; 06758 /* Increment the ringT counter so we can match it against 06759 values in chan_dahdi.conf for distinctive ring */ 06760 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 06761 break; 06762 } else if (i & DAHDI_IOMUX_READ) { 06763 res = read(p->subs[index].dfd, buf, sizeof(buf)); 06764 if (res < 0) { 06765 if (errno != ELAST) { 06766 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 06767 callerid_free(cs); 06768 ast_hangup(chan); 06769 goto quit; 06770 } 06771 break; 06772 } 06773 if (p->ringt) 06774 p->ringt--; 06775 if (p->ringt == 1) { 06776 res = -1; 06777 break; 06778 } 06779 } 06780 } 06781 if (option_verbose > 2) 06782 /* this only shows up if you have n of the dring patterns filled in */ 06783 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 06784 06785 for (counter = 0; counter < 3; counter++) { 06786 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 06787 channel */ 06788 distMatches = 0; 06789 for (counter1 = 0; counter1 < 3; counter1++) { 06790 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >= 06791 (p->drings.ringnum[counter].ring[counter1]-10)) { 06792 distMatches++; 06793 } 06794 } 06795 if (distMatches == 3) { 06796 /* The ring matches, set the context to whatever is for distinctive ring.. */ 06797 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 06798 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 06799 if (option_verbose > 2) 06800 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context); 06801 break; 06802 } 06803 } 06804 } 06805 /* Restore linear mode (if appropriate) for Caller*ID processing */ 06806 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06807 #if 1 06808 restore_gains(p); 06809 #endif 06810 } else 06811 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 06812 } else { 06813 ast_log(LOG_WARNING, "Channel %s in prering " 06814 "state, but I have nothing to do. " 06815 "Terminating simple switch, should be " 06816 "restarted by the actual ring.\n", 06817 chan->name); 06818 ast_hangup(chan); 06819 goto quit; 06820 } 06821 } else if (p->use_callerid && p->cid_start == CID_START_RING) { 06822 /* FSK Bell202 callerID */ 06823 cs = callerid_new(p->cid_signalling); 06824 if (cs) { 06825 #if 1 06826 bump_gains(p); 06827 #endif 06828 samples = 0; 06829 len = 0; 06830 distMatches = 0; 06831 /* Clear the current ring data array so we dont have old data in it. */ 06832 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++) 06833 curRingData[receivedRingT] = 0; 06834 receivedRingT = 0; 06835 counter = 0; 06836 counter1 = 0; 06837 /* Check to see if context is what it should be, if not set to be. */ 06838 if (strcmp(p->context,p->defcontext) != 0) { 06839 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 06840 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 06841 } 06842 06843 /* Take out of linear mode for Caller*ID processing */ 06844 dahdi_setlinear(p->subs[index].dfd, 0); 06845 for (;;) { 06846 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 06847 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 06848 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 06849 callerid_free(cs); 06850 ast_hangup(chan); 06851 goto quit; 06852 } 06853 if (i & DAHDI_IOMUX_SIGEVENT) { 06854 res = dahdi_get_event(p->subs[index].dfd); 06855 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 06856 /* If we get a PR event, they hung up while processing calerid */ 06857 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { 06858 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); 06859 p->polarity = POLARITY_IDLE; 06860 callerid_free(cs); 06861 ast_hangup(chan); 06862 goto quit; 06863 } 06864 res = 0; 06865 /* Let us detect callerid when the telco uses distinctive ring */ 06866 06867 curRingData[receivedRingT] = p->ringt; 06868 06869 if (p->ringt < p->ringt_base/2) 06870 break; 06871 /* Increment the ringT counter so we can match it against 06872 values in chan_dahdi.conf for distinctive ring */ 06873 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 06874 break; 06875 } else if (i & DAHDI_IOMUX_READ) { 06876 res = read(p->subs[index].dfd, buf, sizeof(buf)); 06877 if (res < 0) { 06878 if (errno != ELAST) { 06879 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 06880 callerid_free(cs); 06881 ast_hangup(chan); 06882 goto quit; 06883 } 06884 break; 06885 } 06886 if (p->ringt) 06887 p->ringt--; 06888 if (p->ringt == 1) { 06889 res = -1; 06890 break; 06891 } 06892 samples += res; 06893 res = callerid_feed(cs, buf, res, AST_LAW(p)); 06894 if (res < 0) { 06895 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno)); 06896 break; 06897 } else if (res) 06898 break; 06899 else if (samples > (8000 * 10)) 06900 break; 06901 } 06902 } 06903 if (res == 1) { 06904 callerid_get(cs, &name, &number, &flags); 06905 if (option_debug) 06906 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 06907 } 06908 if (distinctiveringaftercid == 1) { 06909 /* Clear the current ring data array so we dont have old data in it. */ 06910 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) { 06911 curRingData[receivedRingT] = 0; 06912 } 06913 receivedRingT = 0; 06914 if (option_verbose > 2) 06915 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n"); 06916 for (;;) { 06917 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 06918 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 06919 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 06920 callerid_free(cs); 06921 ast_hangup(chan); 06922 goto quit; 06923 } 06924 if (i & DAHDI_IOMUX_SIGEVENT) { 06925 res = dahdi_get_event(p->subs[index].dfd); 06926 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 06927 res = 0; 06928 /* Let us detect callerid when the telco uses distinctive ring */ 06929 06930 curRingData[receivedRingT] = p->ringt; 06931 06932 if (p->ringt < p->ringt_base/2) 06933 break; 06934 /* Increment the ringT counter so we can match it against 06935 values in chan_dahdi.conf for distinctive ring */ 06936 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 06937 break; 06938 } else if (i & DAHDI_IOMUX_READ) { 06939 res = read(p->subs[index].dfd, buf, sizeof(buf)); 06940 if (res < 0) { 06941 if (errno != ELAST) { 06942 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 06943 callerid_free(cs); 06944 ast_hangup(chan); 06945 goto quit; 06946 } 06947 break; 06948 } 06949 if (p->ringt) 06950 p->ringt--; 06951 if (p->ringt == 1) { 06952 res = -1; 06953 break; 06954 } 06955 } 06956 } 06957 } 06958 if (p->usedistinctiveringdetection) { 06959 if (option_verbose > 2) 06960 /* this only shows up if you have n of the dring patterns filled in */ 06961 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 06962 06963 for (counter = 0; counter < 3; counter++) { 06964 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 06965 channel */ 06966 if (option_verbose > 2) 06967 /* this only shows up if you have n of the dring patterns filled in */ 06968 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n", 06969 p->drings.ringnum[counter].ring[0], 06970 p->drings.ringnum[counter].ring[1], 06971 p->drings.ringnum[counter].ring[2]); 06972 distMatches = 0; 06973 for (counter1 = 0; counter1 < 3; counter1++) { 06974 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >= 06975 (p->drings.ringnum[counter].ring[counter1]-10)) { 06976 distMatches++; 06977 } 06978 } 06979 if (distMatches == 3) { 06980 /* The ring matches, set the context to whatever is for distinctive ring.. */ 06981 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 06982 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 06983 if (option_verbose > 2) 06984 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context); 06985 break; 06986 } 06987 } 06988 } 06989 /* Restore linear mode (if appropriate) for Caller*ID processing */ 06990 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06991 #if 1 06992 restore_gains(p); 06993 #endif 06994 if (res < 0) { 06995 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); 06996 } 06997 } else 06998 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 06999 } 07000 else 07001 cs = NULL; 07002 07003 if (number) 07004 ast_shrink_phone_number(number); 07005 ast_set_callerid(chan, number, name, number); 07006 07007 if (smdi_msg) 07008 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy); 07009 07010 if (cs) 07011 callerid_free(cs); 07012 07013 ast_setstate(chan, AST_STATE_RING); 07014 chan->rings = 1; 07015 p->ringt = p->ringt_base; 07016 res = ast_pbx_run(chan); 07017 if (res) { 07018 ast_hangup(chan); 07019 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07020 } 07021 goto quit; 07022 default: 07023 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel); 07024 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07025 if (res < 0) 07026 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 07027 } 07028 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07029 if (res < 0) 07030 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 07031 ast_hangup(chan); 07032 quit: 07033 ast_mutex_lock(&ss_thread_lock); 07034 ss_thread_count--; 07035 ast_cond_signal(&ss_thread_complete); 07036 ast_mutex_unlock(&ss_thread_lock); 07037 return NULL; 07038 }
static int start_pri | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 9977 of file chan_dahdi.c.
References ast_log(), dahdi_close_pri_fd(), DAHDI_FILE_CHANNEL, 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().
09978 { 09979 int res, x; 09980 struct dahdi_params p; 09981 struct dahdi_bufferinfo bi; 09982 struct dahdi_spaninfo si; 09983 int i; 09984 09985 for (i = 0; i < NUM_DCHANS; i++) { 09986 if (!pri->dchannels[i]) 09987 break; 09988 pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600); 09989 x = pri->dchannels[i]; 09990 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) { 09991 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno)); 09992 return -1; 09993 } 09994 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p); 09995 if (res) { 09996 dahdi_close_pri_fd(pri, i); 09997 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno)); 09998 return -1; 09999 } 10000 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) { 10001 dahdi_close_pri_fd(pri, i); 10002 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/dahdi/system.conf\n", x); 10003 return -1; 10004 } 10005 memset(&si, 0, sizeof(si)); 10006 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si); 10007 if (res) { 10008 dahdi_close_pri_fd(pri, i); 10009 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno)); 10010 } 10011 if (!si.alarms) 10012 pri->dchanavail[i] |= DCHAN_NOTINALARM; 10013 else 10014 pri->dchanavail[i] &= ~DCHAN_NOTINALARM; 10015 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 10016 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 10017 bi.numbufs = 32; 10018 bi.bufsize = 1024; 10019 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) { 10020 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno)); 10021 dahdi_close_pri_fd(pri, i); 10022 return -1; 10023 } 10024 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype); 10025 /* Force overlap dial if we're doing GR-303! */ 10026 if (pri->switchtype == PRI_SWITCH_GR303_TMC) 10027 pri->overlapdial = 1; 10028 pri_set_overlapdial(pri->dchans[i],pri->overlapdial); 10029 #ifdef HAVE_PRI_INBANDDISCONNECT 10030 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect); 10031 #endif 10032 /* Enslave to master if appropriate */ 10033 if (i) 10034 pri_enslave(pri->dchans[0], pri->dchans[i]); 10035 if (!pri->dchans[i]) { 10036 dahdi_close_pri_fd(pri, i); 10037 ast_log(LOG_ERROR, "Unable to create PRI structure\n"); 10038 return -1; 10039 } 10040 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG); 10041 pri_set_nsf(pri->dchans[i], pri->nsf); 10042 #ifdef PRI_GETSET_TIMERS 10043 for (x = 0; x < PRI_MAX_TIMERS; x++) { 10044 if (pritimers[x] != 0) 10045 pri_set_timer(pri->dchans[i], x, pritimers[x]); 10046 } 10047 #endif 10048 } 10049 /* Assume primary is the one we use */ 10050 pri->pri = pri->dchans[0]; 10051 pri->resetpos = -1; 10052 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) { 10053 for (i = 0; i < NUM_DCHANS; i++) { 10054 if (!pri->dchannels[i]) 10055 break; 10056 dahdi_close_pri_fd(pri, i); 10057 } 10058 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno)); 10059 return -1; 10060 } 10061 return 0; 10062 }
static void swap_subs | ( | struct dahdi_pvt * | p, | |
int | a, | |||
int | b | |||
) | [static] |
Definition at line 1193 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().
01194 { 01195 int tchan; 01196 int tinthreeway; 01197 struct ast_channel *towner; 01198 01199 ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b); 01200 01201 tchan = p->subs[a].chan; 01202 towner = p->subs[a].owner; 01203 tinthreeway = p->subs[a].inthreeway; 01204 01205 p->subs[a].chan = p->subs[b].chan; 01206 p->subs[a].owner = p->subs[b].owner; 01207 p->subs[a].inthreeway = p->subs[b].inthreeway; 01208 01209 p->subs[b].chan = tchan; 01210 p->subs[b].owner = towner; 01211 p->subs[b].inthreeway = tinthreeway; 01212 01213 if (p->subs[a].owner) 01214 p->subs[a].owner->fds[0] = p->subs[a].dfd; 01215 if (p->subs[b].owner) 01216 p->subs[b].owner->fds[0] = p->subs[b].dfd; 01217 wakeup_sub(p, a, NULL); 01218 wakeup_sub(p, b, NULL); 01219 }
static int unalloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 1332 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().
01333 { 01334 if (!x) { 01335 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel); 01336 return -1; 01337 } 01338 ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel); 01339 dahdi_close_sub(p, x); 01340 p->subs[x].linear = 0; 01341 p->subs[x].chan = 0; 01342 p->subs[x].owner = NULL; 01343 p->subs[x].inthreeway = 0; 01344 p->polarity = POLARITY_IDLE; 01345 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf)); 01346 return 0; 01347 }
static int unload_module | ( | void | ) | [static] |
Definition at line 11227 of file chan_dahdi.c.
References __unload_module(), ast_mutex_destroy(), lock, NUM_SPANS, and pris.
11228 { 11229 #ifdef HAVE_PRI 11230 int y; 11231 for (y = 0; y < NUM_SPANS; y++) 11232 ast_mutex_destroy(&pris[y].lock); 11233 #endif 11234 return __unload_module(); 11235 }
static int update_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1715 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().
01716 { 01717 int needconf = 0; 01718 int x; 01719 int useslavenative; 01720 struct dahdi_pvt *slave = NULL; 01721 01722 useslavenative = isslavenative(p, &slave); 01723 /* Start with the obvious, general stuff */ 01724 for (x = 0; x < 3; x++) { 01725 /* Look for three way calls */ 01726 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) { 01727 conf_add(p, &p->subs[x], x, 0); 01728 needconf++; 01729 } else { 01730 conf_del(p, &p->subs[x], x); 01731 } 01732 } 01733 /* If we have a slave, add him to our conference now. or DAX 01734 if this is slave native */ 01735 for (x = 0; x < MAX_SLAVES; x++) { 01736 if (p->slaves[x]) { 01737 if (useslavenative) 01738 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 01739 else { 01740 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 01741 needconf++; 01742 } 01743 } 01744 } 01745 /* If we're supposed to be in there, do so now */ 01746 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 01747 if (useslavenative) 01748 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 01749 else { 01750 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 01751 needconf++; 01752 } 01753 } 01754 /* If we have a master, add ourselves to his conference */ 01755 if (p->master) { 01756 if (isslavenative(p->master, NULL)) { 01757 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 01758 } else { 01759 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 01760 } 01761 } 01762 if (!needconf) { 01763 /* Nobody is left (or should be left) in our conference. 01764 Kill it. */ 01765 p->confno = -1; 01766 } 01767 if (option_debug) 01768 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf); 01769 return 0; 01770 }
Definition at line 1135 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().
01139 { 01140 #ifdef HAVE_PRI 01141 if (pri) 01142 ast_mutex_unlock(&pri->lock); 01143 #endif 01144 for (;;) { 01145 if (p->subs[a].owner) { 01146 if (ast_mutex_trylock(&p->subs[a].owner->lock)) { 01147 DEADLOCK_AVOIDANCE(&p->lock); 01148 } else { 01149 ast_queue_frame(p->subs[a].owner, &ast_null_frame); 01150 ast_mutex_unlock(&p->subs[a].owner->lock); 01151 break; 01152 } 01153 } else 01154 break; 01155 } 01156 #ifdef HAVE_PRI 01157 if (pri) 01158 ast_mutex_lock(&pri->lock); 01159 #endif 01160 }
static int zap_action_dialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 11073 of file chan_dahdi.c.
References __action_dialoffhook(), and s.
11074 { 11075 return __action_dialoffhook(s, m, 1); 11076 }
static int zap_action_dndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10973 of file chan_dahdi.c.
References __action_dnd(), and s.
10974 { 10975 return __action_dnd(s, m, 1, 0); 10976 }
static int zap_action_dndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10963 of file chan_dahdi.c.
References __action_dnd(), and s.
10964 { 10965 return __action_dnd(s, m, 1, 1); 10966 }
static int zap_action_restart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 11152 of file chan_dahdi.c.
References __action_restart(), and s.
11153 { 11154 return __action_restart(s, m, 1); 11155 }
static int zap_action_showchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 11128 of file chan_dahdi.c.
References __action_showchannels(), and s.
11129 { 11130 return __action_showchannels(s, m, 1); 11131 }
static int zap_action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 11002 of file chan_dahdi.c.
References __action_transfer(), and s.
11003 { 11004 return __action_transfer(s, m, 1); 11005 }
static int zap_action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 11030 of file chan_dahdi.c.
References __action_transferhangup(), and s.
11031 { 11032 return __action_transferhangup(s, m, 1); 11033 }
static int zap_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 2735 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and send_keypad_facility_exec().
Referenced by load_module().
02736 { 02737 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); 02738 return send_keypad_facility_exec(chan, data); 02739 }
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 = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 12367 of file chan_dahdi.c.
int alarm |
struct { ... } alarms[] [static] |
Referenced by alarm2str(), and dahdi_show_status().
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 12367 of file chan_dahdi.c.
struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static] |
Definition at line 1093 of file chan_dahdi.c.
struct ast_channel_tech* chan_tech [static] |
Definition at line 1061 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 1104 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 10869 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 10874 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 10854 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 10864 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 10859 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 10879 of file chan_dahdi.c.
struct ast_cli_entry dahdi_cli[] [static] |
struct ast_cli_entry dahdi_pri_cli[] [static] |
char dahdi_restart_usage[] [static] |
Definition at line 10847 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static] |
Definition at line 2677 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 2683 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static] |
Definition at line 2680 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 10740 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 10839 of file chan_dahdi.c.
struct ast_channel_tech dahdi_tech [static] |
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 110 of file chan_dahdi.c.
char defaultcic[64] = "" [static] |
Definition at line 199 of file chan_dahdi.c.
char defaultozz[64] = "" [static] |
Definition at line 200 of file chan_dahdi.c.
char destroy_channel_usage[] [static] |
Initial value:
"Usage: dahdi destroy channel <chan num>\n" " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n"
Definition at line 10843 of file chan_dahdi.c.
int distinctiveringaftercid = 0 [static] |
Definition at line 204 of file chan_dahdi.c.
struct dahdi_distRings drings [static] |
char* events[] [static] |
int firstdigittimeout = 16000 [static] |
Wait up to 16 seconds for first digit (FXO logic).
Definition at line 218 of file chan_dahdi.c.
Referenced by disa_exec(), mgcp_ss(), and skinny_ss().
int gendigittimeout = 8000 [static] |
How long to wait for following digits (FXO logic).
Definition at line 221 of file chan_dahdi.c.
Referenced by mgcp_ss(), and skinny_ss().
struct ast_jb_conf global_jbconf [static] |
Definition at line 117 of file chan_dahdi.c.
int ifcount = 0 [static] |
Definition at line 230 of file chan_dahdi.c.
Referenced by __action_showchannels(), __oh323_destroy(), __sip_destroy(), __sip_show_channels(), __unload_module(), chandup(), complete_sipch(), dahdi_destroy_channel_bynum(), dahdi_hangup(), dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), destroy_channel(), do_monitor(), find_call(), find_call_locked(), find_channel(), get_sip_pvt_byid_locked(), handle_request_subscribe(), load_module(), mkintf(), oh323_alloc(), phone_request(), sip_alloc(), sip_show_channel(), sip_show_history(), and unload_module().
ast_mutex_t iflock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
Protect the interface list (of dahdi_pvt's).
Definition at line 227 of file chan_dahdi.c.
Referenced by __action_showchannels(), __sip_show_channels(), __unload_module(), complete_sipch(), 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_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 209 of file chan_dahdi.c.
Referenced by ast_extension_state2(), 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 224 of file chan_dahdi.c.
Referenced by mgcp_ss(), and skinny_ss().
pthread_t monitor_thread = AST_PTHREADT_NULL [static] |
This is the thread for the monitor which checks for input on the channels which are not currently in use.
Definition at line 242 of file chan_dahdi.c.
Referenced by reload_config(), restart_monitor(), and unload_module().
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 238 of file chan_dahdi.c.
Referenced by __unload_module(), dahdi_restart(), do_monitor(), restart_monitor(), and unload_module().
char* name |
Definition at line 1485 of file chan_dahdi.c.
int num_cadence = 4 [static] |
Definition at line 1090 of file chan_dahdi.c.
int num_restart_pending = 0 [static] |
Definition at line 247 of file chan_dahdi.c.
int numbufs = 4 [static] |
Definition at line 206 of file chan_dahdi.c.
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 10327 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 10331 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 10335 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 10339 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 10343 of file chan_dahdi.c.
int pridebugfd = -1 [static] |
Definition at line 213 of file chan_dahdi.c.
ast_mutex_t pridebugfdlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
Definition at line 233 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 214 of file chan_dahdi.c.
Definition at line 353 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 202 of file chan_dahdi.c.
ast_mutex_t restart_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
int ringt_base = DEFAULT_RINGT [static] |
Configured ring timeout base.
Definition at line 294 of file chan_dahdi.c.
struct dahdi_pvt* round_robin[32] |
char show_channel_usage[] [static] |
Initial value:
"Usage: dahdi show channel <chan num>\n" " Detailed information about a given channel\n"
Definition at line 10835 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 10831 of file chan_dahdi.c.
ast_cond_t ss_thread_complete [static] |
Definition at line 243 of file chan_dahdi.c.
int ss_thread_count = 0 [static] |
Definition at line 246 of file chan_dahdi.c.
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] |
Definition at line 1091 of file chan_dahdi.c.
char* zap_send_keypad_facility_app = "ZapSendKeypadFacility" [static] |
Definition at line 2678 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 2686 of file chan_dahdi.c.
char* zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static] |
Definition at line 2681 of file chan_dahdi.c.
struct ast_channel_tech zap_tech [static] |