#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 10935 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 10965 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 10966 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 11353 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_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 12393 of file chan_dahdi.c.
#define TRAILER_MS 5 |
Referenced by dahdi_sendtext().
#define TRANSFER 0 |
Definition at line 10934 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 11064 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().
11065 { 11066 struct dahdi_pvt *p = NULL; 11067 const char *channel = local_astman_header(m, "Channel", zap_mode); 11068 const char *number = astman_get_header(m, "Number"); 11069 int i; 11070 11071 if (ast_strlen_zero(channel)) { 11072 astman_send_error(s, m, "No channel specified"); 11073 return 0; 11074 } 11075 if (ast_strlen_zero(number)) { 11076 astman_send_error(s, m, "No number specified"); 11077 return 0; 11078 } 11079 if (!(p = find_channel(atoi(channel)))) { 11080 astman_send_error(s, m, "No such channel"); 11081 return 0; 11082 } 11083 if (!p->owner) { 11084 astman_send_error(s, m, "Channel does not have an owner"); 11085 return 0; 11086 } 11087 for (i = 0; i < strlen(number); i++) { 11088 struct ast_frame f = { AST_FRAME_DTMF, number[i] }; 11089 11090 dahdi_queue_frame(p, &f, NULL); 11091 } 11092 local_astman_ack(s, m, "DialOffHook", zap_mode); 11093 11094 return 0; 11095 }
static int __action_dnd | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode, | |||
int | dnd | |||
) | [static] |
Definition at line 10968 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().
10969 { 10970 struct dahdi_pvt *p = NULL; 10971 const char *channel = local_astman_header(m, "Channel", zap_mode); 10972 10973 if (ast_strlen_zero(channel)) { 10974 astman_send_error(s, m, "No channel specified"); 10975 return 0; 10976 } 10977 if (!(p = find_channel(atoi(channel)))) { 10978 astman_send_error(s, m, "No such channel"); 10979 return 0; 10980 } 10981 p->dnd = dnd; 10982 local_astman_ack(s, m, "DND", zap_mode); 10983 10984 return 0; 10985 }
static int __action_restart | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 11162 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().
11163 { 11164 if (dahdi_restart() != 0) { 11165 if (zap_mode) { 11166 astman_send_error(s, m, "Failed to restart Zap"); 11167 } else { 11168 astman_send_error(s, m, "Failed to restart DAHDI"); 11169 } 11170 return 1; 11171 } 11172 local_astman_ack(s, m, "Restart: Success", zap_mode); 11173 return 0; 11174 }
static int __action_showchannels | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 11107 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().
11108 { 11109 struct dahdi_pvt *tmp = NULL; 11110 const char *id = astman_get_header(m, "ActionID"); 11111 char idText[256] = ""; 11112 11113 local_astman_ack(s, m, " channel status will follow", zap_mode); 11114 if (!ast_strlen_zero(id)) 11115 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id); 11116 11117 ast_mutex_lock(&iflock); 11118 11119 tmp = iflist; 11120 while (tmp) { 11121 if (tmp->channel > 0) { 11122 int alarm = get_alarms(tmp); 11123 astman_append(s, 11124 "Event: %sShowChannels\r\n" 11125 "Channel: %d\r\n" 11126 "Signalling: %s\r\n" 11127 "Context: %s\r\n" 11128 "DND: %s\r\n" 11129 "Alarm: %s\r\n" 11130 "%s" 11131 "\r\n", 11132 dahdi_chan_name, 11133 tmp->channel, sig2str(tmp->sig), tmp->context, 11134 tmp->dnd ? "Enabled" : "Disabled", 11135 alarm2str(alarm), idText); 11136 } 11137 11138 tmp = tmp->next; 11139 } 11140 11141 ast_mutex_unlock(&iflock); 11142 11143 astman_append(s, 11144 "Event: %sShowChannelsComplete\r\n" 11145 "%s" 11146 "\r\n", 11147 dahdi_chan_name, 11148 idText); 11149 return 0; 11150 }
static int __action_transfer | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 11007 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().
11008 { 11009 struct dahdi_pvt *p = NULL; 11010 const char *channel = local_astman_header(m, "Channel", zap_mode); 11011 11012 if (ast_strlen_zero(channel)) { 11013 astman_send_error(s, m, "No channel specified"); 11014 return 0; 11015 } 11016 if (!(p = find_channel(atoi(channel)))) { 11017 astman_send_error(s, m, "No such channel"); 11018 return 0; 11019 } 11020 dahdi_fake_event(p,TRANSFER); 11021 local_astman_ack(s, m, "Transfer", zap_mode); 11022 11023 return 0; 11024 }
static int __action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 11036 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().
11037 { 11038 struct dahdi_pvt *p = NULL; 11039 const char *channel = local_astman_header(m, "Channel", zap_mode); 11040 11041 if (ast_strlen_zero(channel)) { 11042 astman_send_error(s, m, "No channel specified"); 11043 return 0; 11044 } 11045 if (!(p = find_channel(atoi(channel)))) { 11046 astman_send_error(s, m, "No such channel"); 11047 return 0; 11048 } 11049 dahdi_fake_event(p, HANGUP); 11050 local_astman_ack(s, m, "Hangup", zap_mode); 11051 return 0; 11052 }
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 12402 of file chan_dahdi.c.
static int __unload_module | ( | void | ) | [static] |
Definition at line 11193 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().
11194 { 11195 struct dahdi_pvt *p; 11196 11197 #ifdef HAVE_PRI 11198 int i, j; 11199 for (i = 0; i < NUM_SPANS; i++) { 11200 if (pris[i].master != AST_PTHREADT_NULL) 11201 pthread_cancel(pris[i].master); 11202 } 11203 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry)); 11204 11205 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 11206 ast_unregister_application(dahdi_send_keypad_facility_app); 11207 } 11208 ast_unregister_application(zap_send_keypad_facility_app); 11209 #endif 11210 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 11211 local_astman_unregister("DialOffHook"); 11212 local_astman_unregister("Hangup"); 11213 local_astman_unregister("Transfer"); 11214 local_astman_unregister("DNDoff"); 11215 local_astman_unregister("DNDon"); 11216 local_astman_unregister("ShowChannels"); 11217 local_astman_unregister("Restart"); 11218 ast_channel_unregister(chan_tech); 11219 ast_mutex_lock(&iflock); 11220 /* Hangup all interfaces if they have an owner */ 11221 p = iflist; 11222 while (p) { 11223 if (p->owner) 11224 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 11225 p = p->next; 11226 } 11227 ast_mutex_unlock(&iflock); 11228 ast_mutex_lock(&monlock); 11229 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 11230 pthread_cancel(monitor_thread); 11231 pthread_kill(monitor_thread, SIGURG); 11232 pthread_join(monitor_thread, NULL); 11233 } 11234 monitor_thread = AST_PTHREADT_STOP; 11235 ast_mutex_unlock(&monlock); 11236 11237 destroy_all_channels(); 11238 #ifdef HAVE_PRI 11239 for (i = 0; i < NUM_SPANS; i++) { 11240 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) 11241 pthread_join(pris[i].master, NULL); 11242 for (j = 0; j < NUM_DCHANS; j++) { 11243 dahdi_close_pri_fd(&(pris[i]), j); 11244 } 11245 } 11246 #endif 11247 ast_cond_destroy(&ss_thread_complete); 11248 return 0; 11249 }
static void __unreg_module | ( | void | ) | [static] |
Definition at line 12402 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 8845 of file chan_dahdi.c.
References ast_strlen_zero(), dahdi_pri::internationalprefix, dahdi_pri::localprefix, dahdi_pri::nationalprefix, dahdi_pri::privateprefix, and dahdi_pri::unknownprefix.
08846 { 08847 if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */ 08848 if (size) { 08849 *buf = '\0'; 08850 } 08851 return; 08852 } 08853 08854 switch (plan) { 08855 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */ 08856 snprintf(buf, size, "%s%s", pri->internationalprefix, number); 08857 break; 08858 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */ 08859 snprintf(buf, size, "%s%s", pri->nationalprefix, number); 08860 break; 08861 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */ 08862 snprintf(buf, size, "%s%s", pri->localprefix, number); 08863 break; 08864 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */ 08865 snprintf(buf, size, "%s%s", pri->privateprefix, number); 08866 break; 08867 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */ 08868 snprintf(buf, size, "%s%s", pri->unknownprefix, number); 08869 break; 08870 default: /* other Q.931 dialplan => don't twiddle with callingnum */ 08871 snprintf(buf, size, "%s", number); 08872 break; 08873 } 08874 }
static int attempt_transfer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3906 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().
03907 { 03908 /* In order to transfer, we need at least one of the channels to 03909 actually be in a call bridge. We can't conference two applications 03910 together (but then, why would we want to?) */ 03911 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 03912 /* The three-way person we're about to transfer to could still be in MOH, so 03913 stop if now if appropriate */ 03914 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) 03915 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD); 03916 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) { 03917 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING); 03918 } 03919 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) { 03920 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 03921 } 03922 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { 03923 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 03924 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name); 03925 return -1; 03926 } 03927 /* Orphan the channel after releasing the lock */ 03928 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 03929 unalloc_sub(p, SUB_THREEWAY); 03930 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 03931 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 03932 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) { 03933 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING); 03934 } 03935 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) { 03936 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 03937 } 03938 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { 03939 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 03940 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); 03941 return -1; 03942 } 03943 /* Three-way is now the REAL */ 03944 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03945 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock); 03946 unalloc_sub(p, SUB_THREEWAY); 03947 /* Tell the caller not to hangup */ 03948 return 1; 03949 } else { 03950 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n", 03951 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name); 03952 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 03953 return -1; 03954 } 03955 return 0; 03956 }
static int available | ( | struct dahdi_pvt * | p, | |
int | channelmatch, | |||
ast_group_t | groupmatch, | |||
int * | busy, | |||
int * | channelmatched, | |||
int * | groupmatched | |||
) | [inline, static] |
Definition at line 8112 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().
08113 { 08114 int res; 08115 struct dahdi_params par; 08116 08117 /* First, check group matching */ 08118 if (groupmatch) { 08119 if ((p->group & groupmatch) != groupmatch) 08120 return 0; 08121 *groupmatched = 1; 08122 } 08123 /* Check to see if we have a channel match */ 08124 if (channelmatch != -1) { 08125 if (p->channel != channelmatch) 08126 return 0; 08127 *channelmatched = 1; 08128 } 08129 /* We're at least busy at this point */ 08130 if (busy) { 08131 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS)) 08132 *busy = 1; 08133 } 08134 /* If do not disturb, definitely not */ 08135 if (p->dnd) 08136 return 0; 08137 /* If guard time, definitely not */ 08138 if (p->guardtime && (time(NULL) < p->guardtime)) 08139 return 0; 08140 08141 /* If no owner definitely available */ 08142 if (!p->owner) { 08143 #ifdef HAVE_PRI 08144 /* Trust PRI */ 08145 if (p->pri) { 08146 if (p->resetting || p->call) 08147 return 0; 08148 else 08149 return 1; 08150 } 08151 #endif 08152 if (!(p->radio || (p->oprmode < 0))) 08153 { 08154 if (!p->sig || (p->sig == SIG_FXSLS)) 08155 return 1; 08156 /* Check hook state */ 08157 if (p->subs[SUB_REAL].dfd > -1) { 08158 memset(&par, 0, sizeof(par)); 08159 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 08160 } else { 08161 /* Assume not off hook on CVRS */ 08162 res = 0; 08163 par.rxisoffhook = 0; 08164 } 08165 if (res) { 08166 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno)); 08167 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) { 08168 /* When "onhook" that means no battery on the line, and thus 08169 it is out of service..., if it's on a TDM card... If it's a channel 08170 bank, there is no telling... */ 08171 if (par.rxbits > -1) 08172 return 1; 08173 if (par.rxisoffhook) 08174 return 1; 08175 else 08176 #ifdef DAHDI_CHECK_HOOKSTATE 08177 return 0; 08178 #else 08179 return 1; 08180 #endif 08181 } else if (par.rxisoffhook) { 08182 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel); 08183 /* Not available when the other end is off hook */ 08184 return 0; 08185 } 08186 } 08187 return 1; 08188 } 08189 08190 /* If it's not an FXO, forget about call wait */ 08191 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 08192 return 0; 08193 08194 if (!p->callwaiting) { 08195 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */ 08196 return 0; 08197 } 08198 08199 if (p->subs[SUB_CALLWAIT].dfd > -1) { 08200 /* If there is already a call waiting call, then we can't take a second one */ 08201 return 0; 08202 } 08203 08204 if ((p->owner->_state != AST_STATE_UP) && 08205 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) { 08206 /* If the current call is not up, then don't allow the call */ 08207 return 0; 08208 } 08209 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) { 08210 /* Can't take a call wait when the three way calling hasn't been merged yet. */ 08211 return 0; 08212 } 08213 /* We're cool */ 08214 return 1; 08215 }
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 11261 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().
11262 { 11263 char *c, *chan; 11264 int x, start, finish; 11265 struct dahdi_pvt *tmp; 11266 #ifdef HAVE_PRI 11267 struct dahdi_pri *pri; 11268 int trunkgroup, y; 11269 #endif 11270 11271 if ((reload == 0) && (conf->chan.sig < 0)) { 11272 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); 11273 return -1; 11274 } 11275 11276 c = ast_strdupa(value); 11277 11278 #ifdef HAVE_PRI 11279 pri = NULL; 11280 if (iscrv) { 11281 if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) { 11282 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno); 11283 return -1; 11284 } 11285 if (trunkgroup < 1) { 11286 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno); 11287 return -1; 11288 } 11289 c += y; 11290 for (y = 0; y < NUM_SPANS; y++) { 11291 if (pris[y].trunkgroup == trunkgroup) { 11292 pri = pris + y; 11293 break; 11294 } 11295 } 11296 if (!pri) { 11297 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno); 11298 return -1; 11299 } 11300 } 11301 #endif 11302 11303 while ((chan = strsep(&c, ","))) { 11304 if (sscanf(chan, "%d-%d", &start, &finish) == 2) { 11305 /* Range */ 11306 } else if (sscanf(chan, "%d", &start)) { 11307 /* Just one */ 11308 finish = start; 11309 } else if (!strcasecmp(chan, "pseudo")) { 11310 finish = start = CHAN_PSEUDO; 11311 if (found_pseudo) 11312 *found_pseudo = 1; 11313 } else { 11314 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan); 11315 return -1; 11316 } 11317 if (finish < start) { 11318 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); 11319 x = finish; 11320 finish = start; 11321 start = x; 11322 } 11323 11324 for (x = start; x <= finish; x++) { 11325 #ifdef HAVE_PRI 11326 tmp = mkintf(x, conf, pri, reload); 11327 #else 11328 tmp = mkintf(x, conf, NULL, reload); 11329 #endif 11330 11331 if (tmp) { 11332 if (option_verbose > 2) { 11333 #ifdef HAVE_PRI 11334 if (pri) 11335 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig)); 11336 else 11337 #endif 11338 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig)); 11339 } 11340 } else { 11341 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n", 11342 (reload == 1) ? "reconfigure" : "register", value); 11343 return -1; 11344 } 11345 } 11346 } 11347 11348 return 0; 11349 }
static void build_status | ( | char * | s, | |
size_t | len, | |||
int | status, | |||
int | active | |||
) | [static] |
Definition at line 10238 of file chan_dahdi.c.
References DCHAN_NOTINALARM, and DCHAN_PROVISIONED.
Referenced by handle_pri_show_span(), and handle_pri_show_spans().
10239 { 10240 if (!s || len < 1) { 10241 return; 10242 } 10243 s[0] = '\0'; 10244 if (status & DCHAN_PROVISIONED) 10245 strncat(s, "Provisioned, ", len - strlen(s) - 1); 10246 if (!(status & DCHAN_NOTINALARM)) 10247 strncat(s, "In Alarm, ", len - strlen(s) - 1); 10248 if (status & DCHAN_UP) 10249 strncat(s, "Up", len - strlen(s) - 1); 10250 else 10251 strncat(s, "Down", len - strlen(s) - 1); 10252 if (active) 10253 strncat(s, ", Active", len - strlen(s) - 1); 10254 else 10255 strncat(s, ", Standby", len - strlen(s) - 1); 10256 s[len - 1] = '\0'; 10257 }
static int bump_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1945 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().
01946 { 01947 int res; 01948 01949 /* Bump receive gain by 5.0db */ 01950 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law); 01951 if (res) { 01952 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno)); 01953 return -1; 01954 } 01955 01956 return 0; 01957 }
Definition at line 8217 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().
08218 { 08219 struct dahdi_pvt *p; 08220 struct dahdi_bufferinfo bi; 08221 int res; 08222 08223 if ((p = ast_malloc(sizeof(*p)))) { 08224 memcpy(p, src, sizeof(struct dahdi_pvt)); 08225 ast_mutex_init(&p->lock); 08226 p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO); 08227 /* Allocate a DAHDI structure */ 08228 if (p->subs[SUB_REAL].dfd < 0) { 08229 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno)); 08230 destroy_dahdi_pvt(&p); 08231 return NULL; 08232 } 08233 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 08234 if (!res) { 08235 bi.txbufpolicy = p->buf_policy; 08236 bi.rxbufpolicy = p->buf_policy; 08237 bi.numbufs = p->buf_no; 08238 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 08239 if (res < 0) { 08240 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno)); 08241 } 08242 } else 08243 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno)); 08244 } 08245 p->destroy = 1; 08246 p->next = iflist; 08247 p->prev = NULL; 08248 iflist = p; 08249 if (iflist->next) 08250 iflist->next->prev = p; 08251 return p; 08252 }
static int check_for_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3958 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().
03959 { 03960 struct dahdi_confinfo ci; 03961 /* Fine if we already have a master, etc */ 03962 if (p->master || (p->confno > -1)) 03963 return 0; 03964 memset(&ci, 0, sizeof(ci)); 03965 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 03966 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno)); 03967 return 0; 03968 } 03969 /* If we have no master and don't have a confno, then 03970 if we're in a conference, it's probably a MeetMe room or 03971 some such, so don't let us 3-way out! */ 03972 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) { 03973 if (option_verbose > 2) 03974 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n"); 03975 return 1; 03976 } 03977 return 0; 03978 }
static char* complete_span_4 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 10105 of file chan_dahdi.c.
References complete_span_helper().
10106 { 10107 return complete_span_helper(line,word,pos,state,3); 10108 }
static char* complete_span_5 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 10110 of file chan_dahdi.c.
References complete_span_helper().
10111 { 10112 return complete_span_helper(line,word,pos,state,4); 10113 }
static char* complete_span_helper | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state, | |||
int | rpos | |||
) | [static] |
Definition at line 10086 of file chan_dahdi.c.
References asprintf, ast_log(), errno, NUM_SPANS, and pris.
Referenced by complete_span_4(), and complete_span_5().
10087 { 10088 int which, span; 10089 char *ret = NULL; 10090 10091 if (pos != rpos) 10092 return ret; 10093 10094 for (which = span = 0; span < NUM_SPANS; span++) { 10095 if (pris[span].pri && ++which > state) { 10096 if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */ 10097 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 10098 } 10099 break; 10100 } 10101 } 10102 return ret; 10103 }
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 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 01647 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno)); 01648 return -1; 01649 } 01650 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 01651 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 01652 return 0; 01653 }
static int dahdi_action_dialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 11102 of file chan_dahdi.c.
References __action_dialoffhook(), and s.
11103 { 11104 return __action_dialoffhook(s, m, 0); 11105 }
static int dahdi_action_dndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 11002 of file chan_dahdi.c.
References __action_dnd(), and s.
11003 { 11004 return __action_dnd(s, m, 0, 0); 11005 }
static int dahdi_action_dndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10992 of file chan_dahdi.c.
References __action_dnd(), and s.
10993 { 10994 return __action_dnd(s, m, 0, 1); 10995 }
static int dahdi_action_restart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 11181 of file chan_dahdi.c.
References __action_restart(), and s.
11182 { 11183 return __action_restart(s, m, 0); 11184 }
static int dahdi_action_showchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 11157 of file chan_dahdi.c.
References __action_showchannels(), and s.
11158 { 11159 return __action_showchannels(s, m, 0); 11160 }
static int dahdi_action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 11031 of file chan_dahdi.c.
References __action_transfer(), and s.
11032 { 11033 return __action_transfer(s, m, 0); 11034 }
static int dahdi_action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 11059 of file chan_dahdi.c.
References __action_transferhangup(), and s.
11060 { 11061 return __action_transferhangup(s, m, 0); 11062 }
static int dahdi_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3150 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.
03151 { 03152 struct dahdi_pvt *p = ast->tech_pvt; 03153 int res = 0; 03154 int index; 03155 int oldstate = ast->_state; 03156 ast_setstate(ast, AST_STATE_UP); 03157 ast_mutex_lock(&p->lock); 03158 index = dahdi_get_index(ast, p, 0); 03159 if (index < 0) 03160 index = SUB_REAL; 03161 /* nothing to do if a radio channel */ 03162 if ((p->radio || (p->oprmode < 0))) { 03163 ast_mutex_unlock(&p->lock); 03164 return 0; 03165 } 03166 switch (p->sig) { 03167 case SIG_FXSLS: 03168 case SIG_FXSGS: 03169 case SIG_FXSKS: 03170 p->ringt = 0; 03171 /* Fall through */ 03172 case SIG_EM: 03173 case SIG_EM_E1: 03174 case SIG_EMWINK: 03175 case SIG_FEATD: 03176 case SIG_FEATDMF: 03177 case SIG_FEATDMF_TA: 03178 case SIG_E911: 03179 case SIG_FGC_CAMA: 03180 case SIG_FGC_CAMAMF: 03181 case SIG_FEATB: 03182 case SIG_SF: 03183 case SIG_SFWINK: 03184 case SIG_SF_FEATD: 03185 case SIG_SF_FEATDMF: 03186 case SIG_SF_FEATB: 03187 case SIG_FXOLS: 03188 case SIG_FXOGS: 03189 case SIG_FXOKS: 03190 /* Pick up the line */ 03191 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name); 03192 if (p->hanguponpolarityswitch) { 03193 gettimeofday(&p->polaritydelaytv, NULL); 03194 } 03195 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 03196 tone_zone_play_tone(p->subs[index].dfd, -1); 03197 p->dialing = 0; 03198 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) { 03199 if (oldstate == AST_STATE_RINGING) { 03200 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n"); 03201 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1); 03202 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03203 p->owner = p->subs[SUB_REAL].owner; 03204 } 03205 } 03206 if (p->sig & __DAHDI_SIG_FXS) { 03207 dahdi_enable_ec(p); 03208 dahdi_train_ec(p); 03209 } 03210 break; 03211 #ifdef HAVE_PRI 03212 case SIG_PRI: 03213 /* Send a pri acknowledge */ 03214 if (!pri_grab(p, p->pri)) { 03215 p->proceeding = 1; 03216 p->dialing = 0; 03217 res = pri_answer(p->pri->pri, p->call, 0, !p->digital); 03218 pri_rel(p->pri); 03219 } else { 03220 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 03221 res = -1; 03222 } 03223 break; 03224 #endif 03225 case 0: 03226 ast_mutex_unlock(&p->lock); 03227 return 0; 03228 default: 03229 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel); 03230 res = -1; 03231 } 03232 ast_mutex_unlock(&p->lock); 03233 return res; 03234 }
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 3559 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.
03560 { 03561 struct ast_channel *who; 03562 struct dahdi_pvt *p0, *p1, *op0, *op1; 03563 struct dahdi_pvt *master = NULL, *slave = NULL; 03564 struct ast_frame *f; 03565 int inconf = 0; 03566 int nothingok = 1; 03567 int ofd0, ofd1; 03568 int oi0, oi1, i0 = -1, i1 = -1, t0, t1; 03569 int os0 = -1, os1 = -1; 03570 int priority = 0; 03571 struct ast_channel *oc0, *oc1; 03572 enum ast_bridge_result res; 03573 03574 #ifdef PRI_2BCT 03575 int triedtopribridge = 0; 03576 q931_call *q931c0 = NULL, *q931c1 = NULL; 03577 #endif 03578 03579 /* For now, don't attempt to native bridge if either channel needs DTMF detection. 03580 There is code below to handle it properly until DTMF is actually seen, 03581 but due to currently unresolved issues it's ignored... 03582 */ 03583 03584 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 03585 return AST_BRIDGE_FAILED_NOWARN; 03586 03587 ast_mutex_lock(&c0->lock); 03588 while (ast_mutex_trylock(&c1->lock)) { 03589 DEADLOCK_AVOIDANCE(&c0->lock); 03590 } 03591 03592 p0 = c0->tech_pvt; 03593 p1 = c1->tech_pvt; 03594 /* cant do pseudo-channels here */ 03595 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) { 03596 ast_mutex_unlock(&c0->lock); 03597 ast_mutex_unlock(&c1->lock); 03598 return AST_BRIDGE_FAILED_NOWARN; 03599 } 03600 03601 oi0 = dahdi_get_index(c0, p0, 0); 03602 oi1 = dahdi_get_index(c1, p1, 0); 03603 if ((oi0 < 0) || (oi1 < 0)) { 03604 ast_mutex_unlock(&c0->lock); 03605 ast_mutex_unlock(&c1->lock); 03606 return AST_BRIDGE_FAILED; 03607 } 03608 03609 op0 = p0 = c0->tech_pvt; 03610 op1 = p1 = c1->tech_pvt; 03611 ofd0 = c0->fds[0]; 03612 ofd1 = c1->fds[0]; 03613 oc0 = p0->owner; 03614 oc1 = p1->owner; 03615 03616 if (ast_mutex_trylock(&p0->lock)) { 03617 /* Don't block, due to potential for deadlock */ 03618 ast_mutex_unlock(&c0->lock); 03619 ast_mutex_unlock(&c1->lock); 03620 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 03621 return AST_BRIDGE_RETRY; 03622 } 03623 if (ast_mutex_trylock(&p1->lock)) { 03624 /* Don't block, due to potential for deadlock */ 03625 ast_mutex_unlock(&p0->lock); 03626 ast_mutex_unlock(&c0->lock); 03627 ast_mutex_unlock(&c1->lock); 03628 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 03629 return AST_BRIDGE_RETRY; 03630 } 03631 03632 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 03633 if (p0->owner && p1->owner) { 03634 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */ 03635 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) { 03636 master = p0; 03637 slave = p1; 03638 inconf = 1; 03639 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) { 03640 master = p1; 03641 slave = p0; 03642 inconf = 1; 03643 } else { 03644 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n"); 03645 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n", 03646 p0->channel, 03647 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 03648 p0->subs[SUB_REAL].inthreeway, p0->channel, 03649 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 03650 p1->subs[SUB_REAL].inthreeway); 03651 } 03652 nothingok = 0; 03653 } 03654 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) { 03655 if (p1->subs[SUB_THREEWAY].inthreeway) { 03656 master = p1; 03657 slave = p0; 03658 nothingok = 0; 03659 } 03660 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) { 03661 if (p0->subs[SUB_THREEWAY].inthreeway) { 03662 master = p0; 03663 slave = p1; 03664 nothingok = 0; 03665 } 03666 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) { 03667 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise, 03668 don't put us in anything */ 03669 if (p1->subs[SUB_CALLWAIT].inthreeway) { 03670 master = p1; 03671 slave = p0; 03672 nothingok = 0; 03673 } 03674 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) { 03675 /* Same as previous */ 03676 if (p0->subs[SUB_CALLWAIT].inthreeway) { 03677 master = p0; 03678 slave = p1; 03679 nothingok = 0; 03680 } 03681 } 03682 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n", 03683 master ? master->channel : 0, slave ? slave->channel : 0, nothingok); 03684 if (master && slave) { 03685 /* Stop any tones, or play ringtone as appropriate. If they're bridged 03686 in an active threeway call with a channel that is ringing, we should 03687 indicate ringing. */ 03688 if ((oi1 == SUB_THREEWAY) && 03689 p1->subs[SUB_THREEWAY].inthreeway && 03690 p1->subs[SUB_REAL].owner && 03691 p1->subs[SUB_REAL].inthreeway && 03692 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 03693 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name); 03694 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE); 03695 os1 = p1->subs[SUB_REAL].owner->_state; 03696 } else { 03697 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1); 03698 tone_zone_play_tone(p0->subs[oi0].dfd, -1); 03699 } 03700 if ((oi0 == SUB_THREEWAY) && 03701 p0->subs[SUB_THREEWAY].inthreeway && 03702 p0->subs[SUB_REAL].owner && 03703 p0->subs[SUB_REAL].inthreeway && 03704 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 03705 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name); 03706 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE); 03707 os0 = p0->subs[SUB_REAL].owner->_state; 03708 } else { 03709 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0); 03710 tone_zone_play_tone(p1->subs[oi0].dfd, -1); 03711 } 03712 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 03713 if (!p0->echocanbridged || !p1->echocanbridged) { 03714 /* Disable echo cancellation if appropriate */ 03715 dahdi_disable_ec(p0); 03716 dahdi_disable_ec(p1); 03717 } 03718 } 03719 dahdi_link(slave, master); 03720 master->inconference = inconf; 03721 } else if (!nothingok) 03722 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]); 03723 03724 update_conf(p0); 03725 update_conf(p1); 03726 t0 = p0->subs[SUB_REAL].inthreeway; 03727 t1 = p1->subs[SUB_REAL].inthreeway; 03728 03729 ast_mutex_unlock(&p0->lock); 03730 ast_mutex_unlock(&p1->lock); 03731 03732 ast_mutex_unlock(&c0->lock); 03733 ast_mutex_unlock(&c1->lock); 03734 03735 /* Native bridge failed */ 03736 if ((!master || !slave) && !nothingok) { 03737 dahdi_enable_ec(p0); 03738 dahdi_enable_ec(p1); 03739 return AST_BRIDGE_FAILED; 03740 } 03741 03742 if (option_verbose > 2) 03743 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name); 03744 03745 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 03746 disable_dtmf_detect(op0); 03747 03748 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 03749 disable_dtmf_detect(op1); 03750 03751 for (;;) { 03752 struct ast_channel *c0_priority[2] = {c0, c1}; 03753 struct ast_channel *c1_priority[2] = {c1, c0}; 03754 03755 /* Here's our main loop... Start by locking things, looking for private parts, 03756 and then balking if anything is wrong */ 03757 ast_mutex_lock(&c0->lock); 03758 while (ast_mutex_trylock(&c1->lock)) { 03759 DEADLOCK_AVOIDANCE(&c0->lock); 03760 } 03761 03762 p0 = c0->tech_pvt; 03763 p1 = c1->tech_pvt; 03764 03765 if (op0 == p0) 03766 i0 = dahdi_get_index(c0, p0, 1); 03767 if (op1 == p1) 03768 i1 = dahdi_get_index(c1, p1, 1); 03769 ast_mutex_unlock(&c0->lock); 03770 ast_mutex_unlock(&c1->lock); 03771 03772 if (!timeoutms || 03773 (op0 != p0) || 03774 (op1 != p1) || 03775 (ofd0 != c0->fds[0]) || 03776 (ofd1 != c1->fds[0]) || 03777 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 03778 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 03779 (oc0 != p0->owner) || 03780 (oc1 != p1->owner) || 03781 (t0 != p0->subs[SUB_REAL].inthreeway) || 03782 (t1 != p1->subs[SUB_REAL].inthreeway) || 03783 (oi0 != i0) || 03784 (oi1 != i1)) { 03785 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n", 03786 op0->channel, oi0, op1->channel, oi1); 03787 res = AST_BRIDGE_RETRY; 03788 goto return_from_bridge; 03789 } 03790 03791 #ifdef PRI_2BCT 03792 q931c0 = p0->call; 03793 q931c1 = p1->call; 03794 if (p0->transfer && p1->transfer 03795 && q931c0 && q931c1 03796 && !triedtopribridge) { 03797 pri_channel_bridge(q931c0, q931c1); 03798 triedtopribridge = 1; 03799 } 03800 #endif 03801 03802 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms); 03803 if (!who) { 03804 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 03805 continue; 03806 } 03807 f = ast_read(who); 03808 if (!f || (f->frametype == AST_FRAME_CONTROL)) { 03809 *fo = f; 03810 *rc = who; 03811 res = AST_BRIDGE_COMPLETE; 03812 goto return_from_bridge; 03813 } 03814 if (f->frametype == AST_FRAME_DTMF) { 03815 if ((who == c0) && p0->pulsedial) { 03816 ast_write(c1, f); 03817 } else if ((who == c1) && p1->pulsedial) { 03818 ast_write(c0, f); 03819 } else { 03820 *fo = f; 03821 *rc = who; 03822 res = AST_BRIDGE_COMPLETE; 03823 goto return_from_bridge; 03824 } 03825 } 03826 ast_frfree(f); 03827 03828 /* Swap who gets priority */ 03829 priority = !priority; 03830 } 03831 03832 return_from_bridge: 03833 if (op0 == p0) 03834 dahdi_enable_ec(p0); 03835 03836 if (op1 == p1) 03837 dahdi_enable_ec(p1); 03838 03839 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 03840 enable_dtmf_detect(op0); 03841 03842 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 03843 enable_dtmf_detect(op1); 03844 03845 dahdi_unlink(slave, master, 1); 03846 03847 return res; 03848 }
static int dahdi_call | ( | struct ast_channel * | ast, | |
char * | rdest, | |||
int | timeout | |||
) | [static] |
Definition at line 2133 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.
02134 { 02135 struct dahdi_pvt *p = ast->tech_pvt; 02136 int x, res, index,mysig; 02137 char *c, *n, *l; 02138 #ifdef HAVE_PRI 02139 char *s = NULL; 02140 #endif 02141 char dest[256]; /* must be same length as p->dialdest */ 02142 ast_mutex_lock(&p->lock); 02143 ast_copy_string(dest, rdest, sizeof(dest)); 02144 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest)); 02145 if ((ast->_state == AST_STATE_BUSY)) { 02146 p->subs[SUB_REAL].needbusy = 1; 02147 ast_mutex_unlock(&p->lock); 02148 return 0; 02149 } 02150 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 02151 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name); 02152 ast_mutex_unlock(&p->lock); 02153 return -1; 02154 } 02155 p->dialednone = 0; 02156 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ 02157 { 02158 /* Special pseudo -- automatically up */ 02159 ast_setstate(ast, AST_STATE_UP); 02160 ast_mutex_unlock(&p->lock); 02161 return 0; 02162 } 02163 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE; 02164 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 02165 if (res) 02166 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno)); 02167 p->outgoing = 1; 02168 02169 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02170 02171 mysig = p->sig; 02172 if (p->outsigmod > -1) 02173 mysig = p->outsigmod; 02174 02175 switch (mysig) { 02176 case SIG_FXOLS: 02177 case SIG_FXOGS: 02178 case SIG_FXOKS: 02179 if (p->owner == ast) { 02180 /* Normal ring, on hook */ 02181 02182 /* Don't send audio while on hook, until the call is answered */ 02183 p->dialing = 1; 02184 if (p->use_callerid) { 02185 /* Generate the Caller-ID spill if desired */ 02186 if (p->cidspill) { 02187 ast_log(LOG_WARNING, "cidspill already exists??\n"); 02188 free(p->cidspill); 02189 } 02190 p->callwaitcas = 0; 02191 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) { 02192 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p)); 02193 p->cidpos = 0; 02194 send_callerid(p); 02195 } 02196 } 02197 /* Choose proper cadence */ 02198 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { 02199 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) 02200 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); 02201 p->cidrings = cidrings[p->distinctivering - 1]; 02202 } else { 02203 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) 02204 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); 02205 p->cidrings = p->sendcalleridafter; 02206 } 02207 02208 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */ 02209 c = strchr(dest, '/'); 02210 if (c) 02211 c++; 02212 if (c && (strlen(c) < p->stripmsd)) { 02213 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02214 c = NULL; 02215 } 02216 if (c) { 02217 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02218 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c); 02219 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c); 02220 } else { 02221 p->dop.dialstr[0] = '\0'; 02222 } 02223 x = DAHDI_RING; 02224 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) { 02225 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno)); 02226 ast_mutex_unlock(&p->lock); 02227 return -1; 02228 } 02229 p->dialing = 1; 02230 } else { 02231 /* Call waiting call */ 02232 p->callwaitrings = 0; 02233 if (ast->cid.cid_num) 02234 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num)); 02235 else 02236 p->callwait_num[0] = '\0'; 02237 if (ast->cid.cid_name) 02238 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name)); 02239 else 02240 p->callwait_name[0] = '\0'; 02241 /* Call waiting tone instead */ 02242 if (dahdi_callwait(ast)) { 02243 ast_mutex_unlock(&p->lock); 02244 return -1; 02245 } 02246 /* Make ring-back */ 02247 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE)) 02248 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name); 02249 02250 } 02251 n = ast->cid.cid_name; 02252 l = ast->cid.cid_num; 02253 if (l) 02254 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num)); 02255 else 02256 p->lastcid_num[0] = '\0'; 02257 if (n) 02258 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name)); 02259 else 02260 p->lastcid_name[0] = '\0'; 02261 ast_setstate(ast, AST_STATE_RINGING); 02262 index = dahdi_get_index(ast, p, 0); 02263 if (index > -1) { 02264 p->subs[index].needringing = 1; 02265 } 02266 break; 02267 case SIG_FXSLS: 02268 case SIG_FXSGS: 02269 case SIG_FXSKS: 02270 case SIG_EMWINK: 02271 case SIG_EM: 02272 case SIG_EM_E1: 02273 case SIG_FEATD: 02274 case SIG_FEATDMF: 02275 case SIG_E911: 02276 case SIG_FGC_CAMA: 02277 case SIG_FGC_CAMAMF: 02278 case SIG_FEATB: 02279 case SIG_SFWINK: 02280 case SIG_SF: 02281 case SIG_SF_FEATD: 02282 case SIG_SF_FEATDMF: 02283 case SIG_FEATDMF_TA: 02284 case SIG_SF_FEATB: 02285 c = strchr(dest, '/'); 02286 if (c) 02287 c++; 02288 else 02289 c = ""; 02290 if (strlen(c) < p->stripmsd) { 02291 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02292 ast_mutex_unlock(&p->lock); 02293 return -1; 02294 } 02295 #ifdef HAVE_PRI 02296 /* Start the trunk, if not GR-303 */ 02297 if (!p->pri) { 02298 #endif 02299 x = DAHDI_START; 02300 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02301 if (res < 0) { 02302 if (errno != EINPROGRESS) { 02303 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 02304 ast_mutex_unlock(&p->lock); 02305 return -1; 02306 } 02307 } 02308 #ifdef HAVE_PRI 02309 } 02310 #endif 02311 ast_log(LOG_DEBUG, "Dialing '%s'\n", c); 02312 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02313 02314 c += p->stripmsd; 02315 02316 switch (mysig) { 02317 case SIG_FEATD: 02318 l = ast->cid.cid_num; 02319 if (l) 02320 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c); 02321 else 02322 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c); 02323 break; 02324 case SIG_FEATDMF: 02325 l = ast->cid.cid_num; 02326 if (l) 02327 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c); 02328 else 02329 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c); 02330 break; 02331 case SIG_FEATDMF_TA: 02332 { 02333 const char *cic, *ozz; 02334 02335 /* If you have to go through a Tandem Access point you need to use this */ 02336 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ"); 02337 if (!ozz) 02338 ozz = defaultozz; 02339 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC"); 02340 if (!cic) 02341 cic = defaultcic; 02342 if (!ozz || !cic) { 02343 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n"); 02344 ast_mutex_unlock(&p->lock); 02345 return -1; 02346 } 02347 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic); 02348 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c); 02349 p->whichwink = 0; 02350 } 02351 break; 02352 case SIG_E911: 02353 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr)); 02354 break; 02355 case SIG_FGC_CAMA: 02356 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c); 02357 break; 02358 case SIG_FGC_CAMAMF: 02359 case SIG_FEATB: 02360 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c); 02361 break; 02362 default: 02363 if (p->pulse) 02364 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c); 02365 else 02366 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c); 02367 break; 02368 } 02369 02370 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) { 02371 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 02372 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 02373 p->echorest[sizeof(p->echorest) - 1] = '\0'; 02374 p->echobreak = 1; 02375 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 02376 } else 02377 p->echobreak = 0; 02378 if (!res) { 02379 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 02380 int saveerr = errno; 02381 02382 x = DAHDI_ONHOOK; 02383 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02384 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 02385 ast_mutex_unlock(&p->lock); 02386 return -1; 02387 } 02388 } else 02389 ast_log(LOG_DEBUG, "Deferring dialing...\n"); 02390 p->dialing = 1; 02391 if (ast_strlen_zero(c)) 02392 p->dialednone = 1; 02393 ast_setstate(ast, AST_STATE_DIALING); 02394 break; 02395 case 0: 02396 /* Special pseudo -- automatically up*/ 02397 ast_setstate(ast, AST_STATE_UP); 02398 break; 02399 case SIG_PRI: 02400 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */ 02401 p->dialdest[0] = '\0'; 02402 p->dialing = 1; 02403 break; 02404 default: 02405 ast_log(LOG_DEBUG, "not yet implemented\n"); 02406 ast_mutex_unlock(&p->lock); 02407 return -1; 02408 } 02409 #ifdef HAVE_PRI 02410 if (p->pri) { 02411 struct pri_sr *sr; 02412 #ifdef SUPPORT_USERUSER 02413 const char *useruser; 02414 #endif 02415 int pridialplan; 02416 int dp_strip; 02417 int prilocaldialplan; 02418 int ldp_strip; 02419 int exclusive; 02420 const char *rr_str; 02421 int redirect_reason; 02422 02423 c = strchr(dest, '/'); 02424 if (c) { 02425 c++; 02426 } else { 02427 c = ""; 02428 } 02429 02430 l = NULL; 02431 n = NULL; 02432 if (!p->hidecallerid) { 02433 l = ast->cid.cid_num; 02434 if (!p->hidecalleridname) { 02435 n = ast->cid.cid_name; 02436 } 02437 } 02438 02439 02440 if (strlen(c) < p->stripmsd) { 02441 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02442 ast_mutex_unlock(&p->lock); 02443 return -1; 02444 } 02445 if (mysig != SIG_FXSKS) { 02446 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02447 s = strchr(c + p->stripmsd, 'w'); 02448 if (s) { 02449 if (strlen(s) > 1) 02450 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s); 02451 else 02452 p->dop.dialstr[0] = '\0'; 02453 *s = '\0'; 02454 } else { 02455 p->dop.dialstr[0] = '\0'; 02456 } 02457 } 02458 if (pri_grab(p, p->pri)) { 02459 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 02460 ast_mutex_unlock(&p->lock); 02461 return -1; 02462 } 02463 if (!(p->call = pri_new_call(p->pri->pri))) { 02464 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel); 02465 pri_rel(p->pri); 02466 ast_mutex_unlock(&p->lock); 02467 return -1; 02468 } 02469 if (!(sr = pri_sr_new())) { 02470 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel); 02471 pri_destroycall(p->pri->pri, p->call); 02472 p->call = NULL; 02473 pri_rel(p->pri); 02474 ast_mutex_unlock(&p->lock); 02475 return -1; 02476 } 02477 if (p->bearer || (mysig == SIG_FXSKS)) { 02478 if (p->bearer) { 02479 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); 02480 p->bearer->call = p->call; 02481 } else 02482 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n"); 02483 pri_set_crv(p->pri->pri, p->call, p->channel, 0); 02484 } 02485 p->digital = IS_DIGITAL(ast->transfercapability); 02486 02487 /* Should the picked channel be used exclusively? */ 02488 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) { 02489 exclusive = 1; 02490 } else { 02491 exclusive = 0; 02492 } 02493 02494 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1); 02495 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 02496 (p->digital ? -1 : 02497 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW))); 02498 if (p->pri->facilityenable) 02499 pri_facility_enable(p->pri->pri); 02500 02501 if (option_verbose > 2) 02502 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability)); 02503 dp_strip = 0; 02504 pridialplan = p->pri->dialplan - 1; 02505 if (pridialplan == -2) { /* compute dynamically */ 02506 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 02507 dp_strip = strlen(p->pri->internationalprefix); 02508 pridialplan = PRI_INTERNATIONAL_ISDN; 02509 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 02510 dp_strip = strlen(p->pri->nationalprefix); 02511 pridialplan = PRI_NATIONAL_ISDN; 02512 } else { 02513 pridialplan = PRI_LOCAL_ISDN; 02514 } 02515 } 02516 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0); 02517 02518 ldp_strip = 0; 02519 prilocaldialplan = p->pri->localdialplan - 1; 02520 if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */ 02521 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 02522 ldp_strip = strlen(p->pri->internationalprefix); 02523 prilocaldialplan = PRI_INTERNATIONAL_ISDN; 02524 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 02525 ldp_strip = strlen(p->pri->nationalprefix); 02526 prilocaldialplan = PRI_NATIONAL_ISDN; 02527 } else { 02528 prilocaldialplan = PRI_LOCAL_ISDN; 02529 } 02530 } 02531 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan, 02532 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE)); 02533 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) { 02534 if (!strcasecmp(rr_str, "UNKNOWN")) 02535 redirect_reason = 0; 02536 else if (!strcasecmp(rr_str, "BUSY")) 02537 redirect_reason = 1; 02538 else if (!strcasecmp(rr_str, "NO_REPLY")) 02539 redirect_reason = 2; 02540 else if (!strcasecmp(rr_str, "UNCONDITIONAL")) 02541 redirect_reason = 15; 02542 else 02543 redirect_reason = PRI_REDIR_UNCONDITIONAL; 02544 } else 02545 redirect_reason = PRI_REDIR_UNCONDITIONAL; 02546 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason); 02547 02548 #ifdef SUPPORT_USERUSER 02549 /* User-user info */ 02550 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO"); 02551 02552 if (useruser) 02553 pri_sr_set_useruser(sr, useruser); 02554 #endif 02555 02556 if (pri_setup(p->pri->pri, p->call, sr)) { 02557 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 02558 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan)); 02559 pri_rel(p->pri); 02560 ast_mutex_unlock(&p->lock); 02561 pri_sr_free(sr); 02562 return -1; 02563 } 02564 pri_sr_free(sr); 02565 ast_setstate(ast, AST_STATE_DIALING); 02566 pri_rel(p->pri); 02567 } 02568 #endif 02569 ast_mutex_unlock(&p->lock); 02570 return 0; 02571 }
static int dahdi_callwait | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 2105 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().
02106 { 02107 struct dahdi_pvt *p = ast->tech_pvt; 02108 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 02109 if (p->cidspill) { 02110 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 02111 free(p->cidspill); 02112 } 02113 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 02114 return -1; 02115 save_conference(p); 02116 /* Silence */ 02117 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 02118 if (!p->callwaitrings && p->callwaitingcallerid) { 02119 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 02120 p->callwaitcas = 1; 02121 p->cidlen = 2400 + 680 + READ_SIZE * 4; 02122 } else { 02123 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 02124 p->callwaitcas = 0; 02125 p->cidlen = 2400 + READ_SIZE * 4; 02126 } 02127 p->cidpos = 0; 02128 send_callerid(p); 02129 02130 return 0; 02131 }
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 1989 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().
01990 { 01991 int x, y, res; 01992 x = muted; 01993 if (p->sig == SIG_PRI) { 01994 y = 1; 01995 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y); 01996 if (res) 01997 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno)); 01998 } 01999 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x); 02000 if (res < 0) 02001 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno)); 02002 return res; 02003 }
static int dahdi_destroy_channel | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 10407 of file chan_dahdi.c.
References dahdi_destroy_channel_bynum(), and RESULT_SHOWUSAGE.
10408 { 10409 int channel; 10410 10411 if (argc != 4) 10412 return RESULT_SHOWUSAGE; 10413 10414 channel = atoi(argv[3]); 10415 10416 return dahdi_destroy_channel_bynum(channel); 10417 }
static int dahdi_destroy_channel_bynum | ( | int | channel | ) | [static] |
Definition at line 7044 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().
07045 { 07046 struct dahdi_pvt *tmp = NULL; 07047 struct dahdi_pvt *prev = NULL; 07048 07049 tmp = iflist; 07050 while (tmp) { 07051 if (tmp->channel == channel) { 07052 int x = DAHDI_FLASH; 07053 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 */ 07054 destroy_channel(prev, tmp, 1); 07055 ast_module_unref(ast_module_info->self); 07056 return RESULT_SUCCESS; 07057 } 07058 prev = tmp; 07059 tmp = tmp->next; 07060 } 07061 return RESULT_FAILURE; 07062 }
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 1820 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().
01821 { 01822 int x; 01823 int res; 01824 if (p->echocancel) { 01825 x = 0; 01826 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x); 01827 if (res) 01828 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno)); 01829 else if (option_debug) 01830 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel); 01831 } 01832 p->echocanon = 0; 01833 }
static void dahdi_enable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1770 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().
01771 { 01772 int x; 01773 int res; 01774 if (!p) 01775 return; 01776 if (p->echocanon) { 01777 ast_log(LOG_DEBUG, "Echo cancellation already on\n"); 01778 return; 01779 } 01780 if (p->digital) { 01781 ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n"); 01782 return; 01783 } 01784 if (p->echocancel) { 01785 if (p->sig == SIG_PRI) { 01786 x = 1; 01787 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x); 01788 if (res) 01789 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno)); 01790 } 01791 x = p->echocancel; 01792 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x); 01793 if (res) 01794 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno)); 01795 else { 01796 p->echocanon = 1; 01797 if (option_debug) 01798 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel); 01799 } 01800 } else if (option_debug) 01801 ast_log(LOG_DEBUG, "No echo cancellation requested\n"); 01802 }
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 10937 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().
10938 { 10939 if (p) { 10940 switch (mode) { 10941 case TRANSFER: 10942 p->fake_event = DAHDI_EVENT_WINKFLASH; 10943 break; 10944 case HANGUP: 10945 p->fake_event = DAHDI_EVENT_ONHOOK; 10946 break; 10947 default: 10948 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name); 10949 } 10950 } 10951 return 0; 10952 }
static int dahdi_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 3850 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.
03851 { 03852 struct dahdi_pvt *p = newchan->tech_pvt; 03853 int x; 03854 ast_mutex_lock(&p->lock); 03855 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name); 03856 if (p->owner == oldchan) { 03857 p->owner = newchan; 03858 } 03859 for (x = 0; x < 3; x++) 03860 if (p->subs[x].owner == oldchan) { 03861 if (!x) 03862 dahdi_unlink(NULL, p, 0); 03863 p->subs[x].owner = newchan; 03864 } 03865 if (newchan->_state == AST_STATE_RINGING) 03866 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0); 03867 update_conf(p); 03868 ast_mutex_unlock(&p->lock); 03869 return 0; 03870 }
static int dahdi_func_read | ( | struct ast_channel * | chan, | |
char * | function, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 3422 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.
03423 { 03424 struct dahdi_pvt *p = chan->tech_pvt; 03425 03426 if (!strcasecmp(data, "rxgain")) { 03427 ast_mutex_lock(&p->lock); 03428 snprintf(buf, len, "%f", p->rxgain); 03429 ast_mutex_unlock(&p->lock); 03430 } else if (!strcasecmp(data, "txgain")) { 03431 ast_mutex_lock(&p->lock); 03432 snprintf(buf, len, "%f", p->txgain); 03433 ast_mutex_unlock(&p->lock); 03434 } else { 03435 ast_copy_string(buf, "", len); 03436 } 03437 return 0; 03438 }
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 4014 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().
04015 { 04016 struct dahdi_pvt *p = ast->tech_pvt; 04017 struct ast_frame *f = *dest; 04018 04019 if (option_debug) 04020 ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name); 04021 04022 if (p->confirmanswer) { 04023 if (option_debug) 04024 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name); 04025 /* Upon receiving a DTMF digit, consider this an answer confirmation instead 04026 of a DTMF digit */ 04027 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04028 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 04029 *dest = &p->subs[index].f; 04030 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */ 04031 p->confirmanswer = 0; 04032 } else if (p->callwaitcas) { 04033 if ((f->subclass == 'A') || (f->subclass == 'D')) { 04034 if (option_debug) 04035 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n"); 04036 if (p->cidspill) 04037 free(p->cidspill); 04038 send_cwcidspill(p); 04039 } 04040 if ((f->subclass != 'm') && (f->subclass != 'u')) 04041 p->callwaitcas = 0; 04042 p->subs[index].f.frametype = AST_FRAME_NULL; 04043 p->subs[index].f.subclass = 0; 04044 *dest = &p->subs[index].f; 04045 } else if (f->subclass == 'f') { 04046 /* Fax tone -- Handle and return NULL */ 04047 if ((p->callprogress & 0x6) && !p->faxhandled) { 04048 p->faxhandled = 1; 04049 if (strcmp(ast->exten, "fax")) { 04050 const char *target_context = S_OR(ast->macrocontext, ast->context); 04051 04052 /* We need to unlock 'ast' here because ast_exists_extension has the 04053 * potential to start autoservice on the channel. Such action is prone 04054 * to deadlock. 04055 */ 04056 ast_mutex_unlock(&p->lock); 04057 ast_channel_unlock(ast); 04058 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) { 04059 ast_channel_lock(ast); 04060 ast_mutex_lock(&p->lock); 04061 if (option_verbose > 2) 04062 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name); 04063 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 04064 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 04065 if (ast_async_goto(ast, target_context, "fax", 1)) 04066 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 04067 } else { 04068 ast_channel_lock(ast); 04069 ast_mutex_lock(&p->lock); 04070 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 04071 } 04072 } else if (option_debug) 04073 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n"); 04074 } else if (option_debug) 04075 ast_log(LOG_DEBUG, "Fax already handled\n"); 04076 dahdi_confmute(p, 0); 04077 p->subs[index].f.frametype = AST_FRAME_NULL; 04078 p->subs[index].f.subclass = 0; 04079 *dest = &p->subs[index].f; 04080 } else if (f->subclass == 'm') { 04081 /* Confmute request */ 04082 dahdi_confmute(p, 1); 04083 p->subs[index].f.frametype = AST_FRAME_NULL; 04084 p->subs[index].f.subclass = 0; 04085 *dest = &p->subs[index].f; 04086 } else if (f->subclass == 'u') { 04087 /* Unmute */ 04088 dahdi_confmute(p, 0); 04089 p->subs[index].f.frametype = AST_FRAME_NULL; 04090 p->subs[index].f.subclass = 0; 04091 *dest = &p->subs[index].f; 04092 } else 04093 dahdi_confmute(p, 0); 04094 }
static struct ast_frame* dahdi_handle_event | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 4116 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().
04117 { 04118 int res, x; 04119 int index, mysig; 04120 char *c; 04121 struct dahdi_pvt *p = ast->tech_pvt; 04122 pthread_t threadid; 04123 pthread_attr_t attr; 04124 struct ast_channel *chan; 04125 struct ast_frame *f; 04126 04127 index = dahdi_get_index(ast, p, 0); 04128 mysig = p->sig; 04129 if (p->outsigmod > -1) 04130 mysig = p->outsigmod; 04131 p->subs[index].f.frametype = AST_FRAME_NULL; 04132 p->subs[index].f.subclass = 0; 04133 p->subs[index].f.datalen = 0; 04134 p->subs[index].f.samples = 0; 04135 p->subs[index].f.mallocd = 0; 04136 p->subs[index].f.offset = 0; 04137 p->subs[index].f.src = "dahdi_handle_event"; 04138 p->subs[index].f.data = NULL; 04139 f = &p->subs[index].f; 04140 04141 if (index < 0) 04142 return &p->subs[index].f; 04143 if (p->fake_event) { 04144 res = p->fake_event; 04145 p->fake_event = 0; 04146 } else 04147 res = dahdi_get_event(p->subs[index].dfd); 04148 04149 if (option_debug) 04150 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index); 04151 04152 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) { 04153 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0; 04154 04155 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff); 04156 #ifdef HAVE_PRI 04157 if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) { 04158 /* absorb event */ 04159 } else { 04160 #endif 04161 p->subs[index].f.frametype = AST_FRAME_DTMF_END; 04162 p->subs[index].f.subclass = res & 0xff; 04163 #ifdef HAVE_PRI 04164 } 04165 #endif 04166 dahdi_handle_dtmfup(ast, index, &f); 04167 return f; 04168 } 04169 04170 if (res & DAHDI_EVENT_DTMFDOWN) { 04171 if (option_debug) 04172 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff); 04173 /* Mute conference */ 04174 dahdi_confmute(p, 1); 04175 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN; 04176 p->subs[index].f.subclass = res & 0xff; 04177 return &p->subs[index].f; 04178 } 04179 04180 switch (res) { 04181 #ifdef DAHDI_EVENT_EC_DISABLED 04182 case DAHDI_EVENT_EC_DISABLED: 04183 if (option_verbose > 2) 04184 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel); 04185 p->echocanon = 0; 04186 break; 04187 #endif 04188 case DAHDI_EVENT_BITSCHANGED: 04189 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig)); 04190 case DAHDI_EVENT_PULSE_START: 04191 /* Stop tone if there's a pulse start and the PBX isn't started */ 04192 if (!ast->pbx) 04193 tone_zone_play_tone(p->subs[index].dfd, -1); 04194 break; 04195 case DAHDI_EVENT_DIALCOMPLETE: 04196 if (p->inalarm) break; 04197 if ((p->radio || (p->oprmode < 0))) break; 04198 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) { 04199 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno)); 04200 return NULL; 04201 } 04202 if (!x) { /* if not still dialing in driver */ 04203 dahdi_enable_ec(p); 04204 if (p->echobreak) { 04205 dahdi_train_ec(p); 04206 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); 04207 p->dop.op = DAHDI_DIAL_OP_REPLACE; 04208 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 04209 p->echobreak = 0; 04210 } else { 04211 p->dialing = 0; 04212 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) { 04213 /* if thru with dialing after offhook */ 04214 if (ast->_state == AST_STATE_DIALING_OFFHOOK) { 04215 ast_setstate(ast, AST_STATE_UP); 04216 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04217 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 04218 break; 04219 } else { /* if to state wait for offhook to dial rest */ 04220 /* we now wait for off hook */ 04221 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK); 04222 } 04223 } 04224 if (ast->_state == AST_STATE_DIALING) { 04225 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 04226 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n"); 04227 } 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)))) { 04228 ast_setstate(ast, AST_STATE_RINGING); 04229 } else if (!p->answeronpolarityswitch) { 04230 ast_setstate(ast, AST_STATE_UP); 04231 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04232 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 04233 /* If aops=0 and hops=1, this is necessary */ 04234 p->polarity = POLARITY_REV; 04235 } else { 04236 /* Start clean, so we can catch the change to REV polarity when party answers */ 04237 p->polarity = POLARITY_IDLE; 04238 } 04239 } 04240 } 04241 } 04242 break; 04243 case DAHDI_EVENT_ALARM: 04244 #ifdef HAVE_PRI 04245 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) { 04246 /* T309 is not enabled : hangup calls when alarm occurs */ 04247 if (p->call) { 04248 if (p->pri && p->pri->pri) { 04249 if (!pri_grab(p, p->pri)) { 04250 pri_hangup(p->pri->pri, p->call, -1); 04251 pri_destroycall(p->pri->pri, p->call); 04252 p->call = NULL; 04253 pri_rel(p->pri); 04254 } else 04255 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 04256 } else 04257 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n"); 04258 } 04259 if (p->owner) 04260 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 04261 } 04262 if (p->bearer) 04263 p->bearer->inalarm = 1; 04264 else 04265 #endif 04266 p->inalarm = 1; 04267 res = get_alarms(p); 04268 handle_alarms(p, res); 04269 #ifdef HAVE_LIBPRI 04270 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 04271 /* fall through intentionally */ 04272 } else { 04273 break; 04274 } 04275 #endif 04276 case DAHDI_EVENT_ONHOOK: 04277 if (p->radio) { 04278 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04279 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY; 04280 break; 04281 } 04282 if (p->oprmode < 0) 04283 { 04284 if (p->oprmode != -1) break; 04285 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 04286 { 04287 /* Make sure it starts ringing */ 04288 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 04289 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING); 04290 save_conference(p->oprpeer); 04291 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04292 } 04293 break; 04294 } 04295 switch (p->sig) { 04296 case SIG_FXOLS: 04297 case SIG_FXOGS: 04298 case SIG_FXOKS: 04299 p->onhooktime = time(NULL); 04300 p->msgstate = -1; 04301 /* Check for some special conditions regarding call waiting */ 04302 if (index == SUB_REAL) { 04303 /* The normal line was hung up */ 04304 if (p->subs[SUB_CALLWAIT].owner) { 04305 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */ 04306 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 04307 if (option_verbose > 2) 04308 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel); 04309 unalloc_sub(p, SUB_CALLWAIT); 04310 #if 0 04311 p->subs[index].needanswer = 0; 04312 p->subs[index].needringing = 0; 04313 #endif 04314 p->callwaitingrepeat = 0; 04315 p->cidcwexpire = 0; 04316 p->owner = NULL; 04317 /* Don't start streaming audio yet if the incoming call isn't up yet */ 04318 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP) 04319 p->dialing = 1; 04320 dahdi_ring_phone(p); 04321 } else if (p->subs[SUB_THREEWAY].owner) { 04322 unsigned int mssinceflash; 04323 /* Here we have to retain the lock on both the main channel, the 3-way channel, and 04324 the private structure -- not especially easy or clean */ 04325 while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) { 04326 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */ 04327 ast_mutex_unlock(&p->lock); 04328 DEADLOCK_AVOIDANCE(&ast->lock); 04329 /* We can grab ast and p in that order, without worry. We should make sure 04330 nothing seriously bad has happened though like some sort of bizarre double 04331 masquerade! */ 04332 ast_mutex_lock(&p->lock); 04333 if (p->owner != ast) { 04334 ast_log(LOG_WARNING, "This isn't good...\n"); 04335 return NULL; 04336 } 04337 } 04338 if (!p->subs[SUB_THREEWAY].owner) { 04339 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n"); 04340 return NULL; 04341 } 04342 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime); 04343 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash); 04344 if (mssinceflash < MIN_MS_SINCE_FLASH) { 04345 /* It hasn't been long enough since the last flashook. This is probably a bounce on 04346 hanging up. Hangup both channels now */ 04347 if (p->subs[SUB_THREEWAY].owner) 04348 ast_queue_hangup(p->subs[SUB_THREEWAY].owner); 04349 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04350 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel); 04351 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04352 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) { 04353 if (p->transfer) { 04354 /* In any case this isn't a threeway call anymore */ 04355 p->subs[SUB_REAL].inthreeway = 0; 04356 p->subs[SUB_THREEWAY].inthreeway = 0; 04357 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */ 04358 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) { 04359 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04360 /* Swap subs and dis-own channel */ 04361 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04362 p->owner = NULL; 04363 /* Ring the phone */ 04364 dahdi_ring_phone(p); 04365 } else { 04366 if ((res = attempt_transfer(p)) < 0) { 04367 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04368 if (p->subs[SUB_THREEWAY].owner) 04369 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04370 } else if (res) { 04371 /* Don't actually hang up at this point */ 04372 if (p->subs[SUB_THREEWAY].owner) 04373 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04374 break; 04375 } 04376 } 04377 } else { 04378 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04379 if (p->subs[SUB_THREEWAY].owner) 04380 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04381 } 04382 } else { 04383 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04384 /* Swap subs and dis-own channel */ 04385 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04386 p->owner = NULL; 04387 /* Ring the phone */ 04388 dahdi_ring_phone(p); 04389 } 04390 } 04391 } else { 04392 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index); 04393 } 04394 /* Fall through */ 04395 default: 04396 dahdi_disable_ec(p); 04397 return NULL; 04398 } 04399 break; 04400 case DAHDI_EVENT_RINGOFFHOOK: 04401 if (p->inalarm) break; 04402 if (p->oprmode < 0) 04403 { 04404 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 04405 { 04406 /* Make sure it stops ringing */ 04407 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 04408 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1); 04409 restore_conference(p->oprpeer); 04410 } 04411 break; 04412 } 04413 if (p->radio) 04414 { 04415 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04416 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY; 04417 break; 04418 } 04419 /* for E911, its supposed to wait for offhook then dial 04420 the second half of the dial string */ 04421 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) { 04422 c = strchr(p->dialdest, '/'); 04423 if (c) 04424 c++; 04425 else 04426 c = p->dialdest; 04427 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c); 04428 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr)); 04429 if (strlen(p->dop.dialstr) > 4) { 04430 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 04431 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 04432 p->echorest[sizeof(p->echorest) - 1] = '\0'; 04433 p->echobreak = 1; 04434 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 04435 } else 04436 p->echobreak = 0; 04437 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 04438 int saveerr = errno; 04439 04440 x = DAHDI_ONHOOK; 04441 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04442 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 04443 return NULL; 04444 } 04445 p->dialing = 1; 04446 return &p->subs[index].f; 04447 } 04448 switch (p->sig) { 04449 case SIG_FXOLS: 04450 case SIG_FXOGS: 04451 case SIG_FXOKS: 04452 switch (ast->_state) { 04453 case AST_STATE_RINGING: 04454 dahdi_enable_ec(p); 04455 dahdi_train_ec(p); 04456 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04457 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 04458 /* Make sure it stops ringing */ 04459 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 04460 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel); 04461 if (p->cidspill) { 04462 /* Cancel any running CallerID spill */ 04463 free(p->cidspill); 04464 p->cidspill = NULL; 04465 } 04466 p->dialing = 0; 04467 p->callwaitcas = 0; 04468 if (p->confirmanswer) { 04469 /* Ignore answer if "confirm answer" is enabled */ 04470 p->subs[index].f.frametype = AST_FRAME_NULL; 04471 p->subs[index].f.subclass = 0; 04472 } else if (!ast_strlen_zero(p->dop.dialstr)) { 04473 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ 04474 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 04475 if (res < 0) { 04476 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 04477 p->dop.dialstr[0] = '\0'; 04478 return NULL; 04479 } else { 04480 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr); 04481 p->subs[index].f.frametype = AST_FRAME_NULL; 04482 p->subs[index].f.subclass = 0; 04483 p->dialing = 1; 04484 } 04485 p->dop.dialstr[0] = '\0'; 04486 ast_setstate(ast, AST_STATE_DIALING); 04487 } else 04488 ast_setstate(ast, AST_STATE_UP); 04489 return &p->subs[index].f; 04490 case AST_STATE_DOWN: 04491 ast_setstate(ast, AST_STATE_RING); 04492 ast->rings = 1; 04493 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04494 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK; 04495 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel); 04496 return &p->subs[index].f; 04497 case AST_STATE_UP: 04498 /* Make sure it stops ringing */ 04499 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 04500 /* Okay -- probably call waiting*/ 04501 if (ast_bridged_channel(p->owner)) 04502 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 04503 p->subs[index].needunhold = 1; 04504 break; 04505 case AST_STATE_RESERVED: 04506 /* Start up dialtone */ 04507 if (has_voicemail(p)) 04508 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 04509 else 04510 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 04511 break; 04512 default: 04513 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state); 04514 } 04515 break; 04516 case SIG_FXSLS: 04517 case SIG_FXSGS: 04518 case SIG_FXSKS: 04519 if (ast->_state == AST_STATE_RING) { 04520 p->ringt = p->ringt_base; 04521 } 04522 04523 /* Fall through */ 04524 case SIG_EM: 04525 case SIG_EM_E1: 04526 case SIG_EMWINK: 04527 case SIG_FEATD: 04528 case SIG_FEATDMF: 04529 case SIG_FEATDMF_TA: 04530 case SIG_E911: 04531 case SIG_FGC_CAMA: 04532 case SIG_FGC_CAMAMF: 04533 case SIG_FEATB: 04534 case SIG_SF: 04535 case SIG_SFWINK: 04536 case SIG_SF_FEATD: 04537 case SIG_SF_FEATDMF: 04538 case SIG_SF_FEATB: 04539 if (ast->_state == AST_STATE_PRERING) 04540 ast_setstate(ast, AST_STATE_RING); 04541 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) { 04542 if (option_debug) 04543 ast_log(LOG_DEBUG, "Ring detected\n"); 04544 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04545 p->subs[index].f.subclass = AST_CONTROL_RING; 04546 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) { 04547 if (option_debug) 04548 ast_log(LOG_DEBUG, "Line answered\n"); 04549 if (p->confirmanswer) { 04550 p->subs[index].f.frametype = AST_FRAME_NULL; 04551 p->subs[index].f.subclass = 0; 04552 } else { 04553 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04554 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 04555 ast_setstate(ast, AST_STATE_UP); 04556 } 04557 } else if (ast->_state != AST_STATE_RING) 04558 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel); 04559 break; 04560 default: 04561 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 04562 } 04563 break; 04564 #ifdef DAHDI_EVENT_RINGBEGIN 04565 case DAHDI_EVENT_RINGBEGIN: 04566 switch (p->sig) { 04567 case SIG_FXSLS: 04568 case SIG_FXSGS: 04569 case SIG_FXSKS: 04570 if (ast->_state == AST_STATE_RING) { 04571 p->ringt = p->ringt_base; 04572 } 04573 break; 04574 } 04575 break; 04576 #endif 04577 case DAHDI_EVENT_RINGEROFF: 04578 if (p->inalarm) break; 04579 if ((p->radio || (p->oprmode < 0))) break; 04580 ast->rings++; 04581 if ((ast->rings > p->cidrings) && (p->cidspill)) { 04582 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n"); 04583 free(p->cidspill); 04584 p->cidspill = NULL; 04585 p->callwaitcas = 0; 04586 } 04587 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04588 p->subs[index].f.subclass = AST_CONTROL_RINGING; 04589 break; 04590 case DAHDI_EVENT_RINGERON: 04591 break; 04592 case DAHDI_EVENT_NOALARM: 04593 p->inalarm = 0; 04594 #ifdef HAVE_PRI 04595 /* Extremely unlikely but just in case */ 04596 if (p->bearer) 04597 p->bearer->inalarm = 0; 04598 #endif 04599 if (!p->unknown_alarm) { 04600 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 04601 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 04602 "Channel: %d\r\n", p->channel); 04603 } else { 04604 p->unknown_alarm = 0; 04605 } 04606 break; 04607 case DAHDI_EVENT_WINKFLASH: 04608 if (p->inalarm) break; 04609 if (p->radio) break; 04610 if (p->oprmode < 0) break; 04611 if (p->oprmode > 1) 04612 { 04613 struct dahdi_params par; 04614 04615 memset(&par, 0, sizeof(par)); 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 2815 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().
02816 { 02817 int res; 02818 int index,x, law; 02819 /*static int restore_gains(struct dahdi_pvt *p);*/ 02820 struct dahdi_pvt *p = ast->tech_pvt; 02821 struct dahdi_pvt *tmp = NULL; 02822 struct dahdi_pvt *prev = NULL; 02823 struct dahdi_params par; 02824 02825 if (option_debug) 02826 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name); 02827 if (!ast->tech_pvt) { 02828 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 02829 return 0; 02830 } 02831 02832 ast_mutex_lock(&p->lock); 02833 02834 index = dahdi_get_index(ast, p, 1); 02835 02836 if (p->sig == SIG_PRI) { 02837 x = 1; 02838 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 02839 } 02840 02841 x = 0; 02842 dahdi_confmute(p, 0); 02843 restore_gains(p); 02844 if (p->origcid_num) { 02845 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num)); 02846 free(p->origcid_num); 02847 p->origcid_num = NULL; 02848 } 02849 if (p->origcid_name) { 02850 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name)); 02851 free(p->origcid_name); 02852 p->origcid_name = NULL; 02853 } 02854 if (p->dsp) 02855 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 02856 p->exten[0] = '\0'; 02857 02858 if (option_debug) 02859 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n", 02860 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 02861 p->ignoredtmf = 0; 02862 02863 if (index > -1) { 02864 /* Real channel, do some fixup */ 02865 p->subs[index].owner = NULL; 02866 p->subs[index].needanswer = 0; 02867 p->subs[index].needflash = 0; 02868 p->subs[index].needringing = 0; 02869 p->subs[index].needbusy = 0; 02870 p->subs[index].needcongestion = 0; 02871 p->subs[index].linear = 0; 02872 p->subs[index].needcallerid = 0; 02873 p->polarity = POLARITY_IDLE; 02874 dahdi_setlinear(p->subs[index].dfd, 0); 02875 if (index == SUB_REAL) { 02876 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) { 02877 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n"); 02878 if (p->subs[SUB_CALLWAIT].inthreeway) { 02879 /* We had flipped over to answer a callwait and now it's gone */ 02880 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n"); 02881 /* Move to the call-wait, but un-own us until they flip back. */ 02882 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 02883 unalloc_sub(p, SUB_CALLWAIT); 02884 p->owner = NULL; 02885 } else { 02886 /* The three way hung up, but we still have a call wait */ 02887 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n"); 02888 swap_subs(p, SUB_THREEWAY, SUB_REAL); 02889 unalloc_sub(p, SUB_THREEWAY); 02890 if (p->subs[SUB_REAL].inthreeway) { 02891 /* This was part of a three way call. Immediately make way for 02892 another call */ 02893 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n"); 02894 p->owner = p->subs[SUB_REAL].owner; 02895 } else { 02896 /* This call hasn't been completed yet... Set owner to NULL */ 02897 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n"); 02898 p->owner = NULL; 02899 } 02900 p->subs[SUB_REAL].inthreeway = 0; 02901 } 02902 } else if (p->subs[SUB_CALLWAIT].dfd > -1) { 02903 /* Move to the call-wait and switch back to them. */ 02904 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 02905 unalloc_sub(p, SUB_CALLWAIT); 02906 p->owner = p->subs[SUB_REAL].owner; 02907 if (p->owner->_state != AST_STATE_UP) 02908 p->subs[SUB_REAL].needanswer = 1; 02909 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 02910 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 02911 } else if (p->subs[SUB_THREEWAY].dfd > -1) { 02912 swap_subs(p, SUB_THREEWAY, SUB_REAL); 02913 unalloc_sub(p, SUB_THREEWAY); 02914 if (p->subs[SUB_REAL].inthreeway) { 02915 /* This was part of a three way call. Immediately make way for 02916 another call */ 02917 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n"); 02918 p->owner = p->subs[SUB_REAL].owner; 02919 } else { 02920 /* This call hasn't been completed yet... Set owner to NULL */ 02921 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n"); 02922 p->owner = NULL; 02923 } 02924 p->subs[SUB_REAL].inthreeway = 0; 02925 } 02926 } else if (index == SUB_CALLWAIT) { 02927 /* Ditch the holding callwait call, and immediately make it availabe */ 02928 if (p->subs[SUB_CALLWAIT].inthreeway) { 02929 /* This is actually part of a three way, placed on hold. Place the third part 02930 on music on hold now */ 02931 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 02932 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 02933 S_OR(p->mohsuggest, NULL), 02934 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 02935 } 02936 p->subs[SUB_THREEWAY].inthreeway = 0; 02937 /* Make it the call wait now */ 02938 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 02939 unalloc_sub(p, SUB_THREEWAY); 02940 } else 02941 unalloc_sub(p, SUB_CALLWAIT); 02942 } else if (index == SUB_THREEWAY) { 02943 if (p->subs[SUB_CALLWAIT].inthreeway) { 02944 /* The other party of the three way call is currently in a call-wait state. 02945 Start music on hold for them, and take the main guy out of the third call */ 02946 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 02947 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 02948 S_OR(p->mohsuggest, NULL), 02949 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 02950 } 02951 p->subs[SUB_CALLWAIT].inthreeway = 0; 02952 } 02953 p->subs[SUB_REAL].inthreeway = 0; 02954 /* If this was part of a three way call index, let us make 02955 another three way call */ 02956 unalloc_sub(p, SUB_THREEWAY); 02957 } else { 02958 /* This wasn't any sort of call, but how are we an index? */ 02959 ast_log(LOG_WARNING, "Index found but not any type of call?\n"); 02960 } 02961 } 02962 02963 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 02964 p->owner = NULL; 02965 p->ringt = 0; 02966 p->distinctivering = 0; 02967 p->confirmanswer = 0; 02968 p->cidrings = 1; 02969 p->outgoing = 0; 02970 p->digital = 0; 02971 p->faxhandled = 0; 02972 p->pulsedial = 0; 02973 p->onhooktime = time(NULL); 02974 #ifdef HAVE_PRI 02975 p->proceeding = 0; 02976 p->dialing = 0; 02977 p->progress = 0; 02978 p->alerting = 0; 02979 p->setup_ack = 0; 02980 #endif 02981 if (p->dsp) { 02982 ast_dsp_free(p->dsp); 02983 p->dsp = NULL; 02984 } 02985 02986 law = DAHDI_LAW_DEFAULT; 02987 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 02988 if (res < 0) 02989 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 02990 /* Perform low level hangup if no owner left */ 02991 #ifdef HAVE_PRI 02992 if (p->pri) { 02993 #ifdef SUPPORT_USERUSER 02994 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO"); 02995 #endif 02996 02997 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */ 02998 if (p->call && (!p->bearer || (p->bearer->call == p->call))) { 02999 if (!pri_grab(p, p->pri)) { 03000 if (p->alreadyhungup) { 03001 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n"); 03002 03003 #ifdef SUPPORT_USERUSER 03004 pri_call_set_useruser(p->call, useruser); 03005 #endif 03006 03007 pri_hangup(p->pri->pri, p->call, -1); 03008 p->call = NULL; 03009 if (p->bearer) 03010 p->bearer->call = NULL; 03011 } else { 03012 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE"); 03013 int icause = ast->hangupcause ? ast->hangupcause : -1; 03014 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n"); 03015 03016 #ifdef SUPPORT_USERUSER 03017 pri_call_set_useruser(p->call, useruser); 03018 #endif 03019 03020 p->alreadyhungup = 1; 03021 if (p->bearer) 03022 p->bearer->alreadyhungup = 1; 03023 if (cause) { 03024 if (atoi(cause)) 03025 icause = atoi(cause); 03026 } 03027 pri_hangup(p->pri->pri, p->call, icause); 03028 } 03029 if (res < 0) 03030 ast_log(LOG_WARNING, "pri_disconnect failed\n"); 03031 pri_rel(p->pri); 03032 } else { 03033 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 03034 res = -1; 03035 } 03036 } else { 03037 if (p->bearer) 03038 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call); 03039 p->call = NULL; 03040 res = 0; 03041 } 03042 } 03043 #endif 03044 if (p->sig && (p->sig != SIG_PRI)) 03045 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 03046 if (res < 0) { 03047 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name); 03048 } 03049 switch (p->sig) { 03050 case SIG_FXOGS: 03051 case SIG_FXOLS: 03052 case SIG_FXOKS: 03053 memset(&par, 0, sizeof(par)); 03054 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 03055 if (!res) { 03056 #if 0 03057 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook); 03058 #endif 03059 /* If they're off hook, try playing congestion */ 03060 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0)))) 03061 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 03062 else 03063 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03064 } 03065 break; 03066 case SIG_FXSGS: 03067 case SIG_FXSLS: 03068 case SIG_FXSKS: 03069 /* Make sure we're not made available for at least two seconds assuming 03070 we were actually used for an inbound or outbound call. */ 03071 if (ast->_state != AST_STATE_RESERVED) { 03072 time(&p->guardtime); 03073 p->guardtime += 2; 03074 } 03075 break; 03076 default: 03077 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03078 } 03079 if (p->cidspill) 03080 free(p->cidspill); 03081 if (p->sig) 03082 dahdi_disable_ec(p); 03083 x = 0; 03084 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); 03085 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0); 03086 p->didtdd = 0; 03087 p->cidspill = NULL; 03088 p->callwaitcas = 0; 03089 p->callwaiting = p->permcallwaiting; 03090 p->hidecallerid = p->permhidecallerid; 03091 p->dialing = 0; 03092 p->rdnis[0] = '\0'; 03093 update_conf(p); 03094 reset_conf(p); 03095 /* Restore data mode */ 03096 if (p->sig == SIG_PRI) { 03097 x = 0; 03098 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 03099 } 03100 #ifdef HAVE_PRI 03101 if (p->bearer) { 03102 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel); 03103 /* Free up the bearer channel as well, and 03104 don't use its file descriptor anymore */ 03105 update_conf(p->bearer); 03106 reset_conf(p->bearer); 03107 p->bearer->owner = NULL; 03108 p->bearer->realcall = NULL; 03109 p->bearer = NULL; 03110 p->subs[SUB_REAL].dfd = -1; 03111 p->pri = NULL; 03112 } 03113 #endif 03114 if (num_restart_pending == 0) 03115 restart_monitor(); 03116 } 03117 03118 p->callwaitingrepeat = 0; 03119 p->cidcwexpire = 0; 03120 p->oprmode = 0; 03121 ast->tech_pvt = NULL; 03122 ast_mutex_unlock(&p->lock); 03123 ast_module_unref(ast_module_info->self); 03124 if (option_verbose > 2) 03125 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name); 03126 03127 ast_mutex_lock(&iflock); 03128 03129 if (p->restartpending) { 03130 num_restart_pending--; 03131 } 03132 03133 tmp = iflist; 03134 prev = NULL; 03135 if (p->destroy) { 03136 while (tmp) { 03137 if (tmp == p) { 03138 destroy_channel(prev, tmp, 0); 03139 break; 03140 } else { 03141 prev = tmp; 03142 tmp = tmp->next; 03143 } 03144 } 03145 } 03146 ast_mutex_unlock(&iflock); 03147 return 0; 03148 }
static int dahdi_indicate | ( | struct ast_channel * | chan, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 5474 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, dahdi_pvt::alerting, AST_CAUSE_CONGESTION, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_USER_BUSY, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_SOFTHANGUP_DEV, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, dahdi_pvt::call, dahdi_get_index(), dahdi_set_hook(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::digital, dahdi_pvt::dop, errno, ast_channel::hangupcause, ISTRUNK, dahdi_pvt::lock, LOG_DEBUG, dahdi_pvt::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.
05475 { 05476 struct dahdi_pvt *p = chan->tech_pvt; 05477 int res=-1; 05478 int index; 05479 int func = DAHDI_FLASH; 05480 ast_mutex_lock(&p->lock); 05481 index = dahdi_get_index(chan, p, 0); 05482 if (option_debug) 05483 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name); 05484 if (index == SUB_REAL) { 05485 switch (condition) { 05486 case AST_CONTROL_BUSY: 05487 #ifdef HAVE_PRI 05488 if (p->priindication_oob && p->sig == SIG_PRI) { 05489 chan->hangupcause = AST_CAUSE_USER_BUSY; 05490 chan->_softhangup |= AST_SOFTHANGUP_DEV; 05491 res = 0; 05492 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 05493 if (p->pri->pri) { 05494 if (!pri_grab(p, p->pri)) { 05495 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 05496 pri_rel(p->pri); 05497 } 05498 else 05499 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05500 } 05501 p->progress = 1; 05502 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY); 05503 } else 05504 #endif 05505 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY); 05506 break; 05507 case AST_CONTROL_RINGING: 05508 #ifdef HAVE_PRI 05509 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) { 05510 if (p->pri->pri) { 05511 if (!pri_grab(p, p->pri)) { 05512 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 05513 pri_rel(p->pri); 05514 } 05515 else 05516 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05517 } 05518 p->alerting = 1; 05519 } 05520 #endif 05521 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE); 05522 if (chan->_state != AST_STATE_UP) { 05523 if ((chan->_state != AST_STATE_RING) || 05524 ((p->sig != SIG_FXSKS) && 05525 (p->sig != SIG_FXSLS) && 05526 (p->sig != SIG_FXSGS))) 05527 ast_setstate(chan, AST_STATE_RINGING); 05528 } 05529 break; 05530 case AST_CONTROL_PROCEEDING: 05531 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name); 05532 #ifdef HAVE_PRI 05533 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { 05534 if (p->pri->pri) { 05535 if (!pri_grab(p, p->pri)) { 05536 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 05537 pri_rel(p->pri); 05538 } 05539 else 05540 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05541 } 05542 p->proceeding = 1; 05543 p->dialing = 0; 05544 } 05545 #endif 05546 /* don't continue in ast_indicate */ 05547 res = 0; 05548 break; 05549 case AST_CONTROL_PROGRESS: 05550 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name); 05551 #ifdef HAVE_PRI 05552 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */ 05553 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 05554 if (p->pri->pri) { 05555 if (!pri_grab(p, p->pri)) { 05556 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 05557 pri_rel(p->pri); 05558 } 05559 else 05560 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05561 } 05562 p->progress = 1; 05563 } 05564 #endif 05565 /* don't continue in ast_indicate */ 05566 res = 0; 05567 break; 05568 case AST_CONTROL_CONGESTION: 05569 chan->hangupcause = AST_CAUSE_CONGESTION; 05570 #ifdef HAVE_PRI 05571 if (p->priindication_oob && p->sig == SIG_PRI) { 05572 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 05573 chan->_softhangup |= AST_SOFTHANGUP_DEV; 05574 res = 0; 05575 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 05576 if (p->pri) { 05577 if (!pri_grab(p, p->pri)) { 05578 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 05579 pri_rel(p->pri); 05580 } else 05581 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05582 } 05583 p->progress = 1; 05584 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 05585 } else 05586 #endif 05587 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 05588 break; 05589 case AST_CONTROL_HOLD: 05590 #ifdef HAVE_PRI 05591 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 05592 if (!pri_grab(p, p->pri)) { 05593 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD); 05594 pri_rel(p->pri); 05595 } else 05596 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05597 } else 05598 #endif 05599 ast_moh_start(chan, data, p->mohinterpret); 05600 break; 05601 case AST_CONTROL_UNHOLD: 05602 #ifdef HAVE_PRI 05603 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 05604 if (!pri_grab(p, p->pri)) { 05605 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL); 05606 pri_rel(p->pri); 05607 } else 05608 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05609 } else 05610 #endif 05611 ast_moh_stop(chan); 05612 break; 05613 case AST_CONTROL_RADIO_KEY: 05614 if (p->radio) 05615 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 05616 res = 0; 05617 break; 05618 case AST_CONTROL_RADIO_UNKEY: 05619 if (p->radio) 05620 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF); 05621 res = 0; 05622 break; 05623 case AST_CONTROL_FLASH: 05624 /* flash hookswitch */ 05625 if (ISTRUNK(p) && (p->sig != SIG_PRI)) { 05626 /* Clear out the dial buffer */ 05627 p->dop.dialstr[0] = '\0'; 05628 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 05629 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 05630 chan->name, strerror(errno)); 05631 } else 05632 res = 0; 05633 } else 05634 res = 0; 05635 break; 05636 case AST_CONTROL_SRCUPDATE: 05637 res = 0; 05638 break; 05639 case -1: 05640 res = tone_zone_play_tone(p->subs[index].dfd, -1); 05641 break; 05642 } 05643 } else 05644 res = 0; 05645 ast_mutex_unlock(&p->lock); 05646 return res; 05647 }
Definition at line 3497 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and master.
Referenced by dahdi_bridge().
03497 { 03498 int x; 03499 if (!slave || !master) { 03500 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n"); 03501 return; 03502 } 03503 for (x = 0; x < MAX_SLAVES; x++) { 03504 if (!master->slaves[x]) { 03505 master->slaves[x] = slave; 03506 break; 03507 } 03508 } 03509 if (x >= MAX_SLAVES) { 03510 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel); 03511 master->slaves[MAX_SLAVES - 1] = slave; 03512 } 03513 if (slave->master) 03514 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel); 03515 slave->master = master; 03516 03517 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x); 03518 }
static struct ast_channel * dahdi_new | ( | struct dahdi_pvt * | , | |
int | , | |||
int | , | |||
int | , | |||
int | , | |||
int | ||||
) | [static] |
Definition at line 5649 of file chan_dahdi.c.
References accountcode, dahdi_pvt::accountcode, dahdi_pvt::adsi, ast_channel::adsicpe, dahdi_pvt::alreadyhungup, ast_channel::amaflags, dahdi_pvt::amaflags, AST_ADSI_UNAVAILABLE, ast_channel_alloc(), ast_copy_string(), ast_dsp_digitmode(), ast_dsp_new(), ast_dsp_set_busy_compare(), ast_dsp_set_busy_count(), ast_dsp_set_busy_pattern(), ast_dsp_set_call_progress_zone(), ast_dsp_set_features(), ast_dsp_set_threshold(), AST_FORMAT_ALAW, AST_FORMAT_ULAW, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_random(), ast_safe_string_alloc(), AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_transfercapability2str(), dahdi_pvt::bearer, dahdi_pvt::busycompare, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::call_forward, dahdi_pvt::callgroup, ast_channel::callgroup, dahdi_pvt::callingpres, dahdi_pvt::callprogress, CANBUSYDETECT, CANPROGRESSDETECT, CHAN_PSEUDO, chan_tech, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, dahdi_pvt::cid_name, dahdi_pvt::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, dahdi_pvt::cid_ton, ast_callerid::cid_ton, ast_channel::context, dahdi_pvt::context, dahdi_chan_name, dahdi_chan_name_len, dahdi_confmute(), dahdi_setlinear(), dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::dnid, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, DSP_PROGRESS_TALK, dahdi_pvt::dtmfrelax, errno, ast_channel::exten, dahdi_pvt::exten, dahdi_pvt::fake_event, ast_channel::fds, free, global_jbconf, dahdi_pvt::hardwaredtmf, dahdi_pvt::isidlecall, language, dahdi_pvt::language, dahdi_subchannel::linear, LOG_DEBUG, 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().
05650 { 05651 struct ast_channel *tmp; 05652 int deflaw; 05653 int res; 05654 int x,y; 05655 int features; 05656 char *b2 = NULL; 05657 struct dahdi_params ps; 05658 char chanprefix[*dahdi_chan_name_len + 4]; 05659 05660 if (i->subs[index].owner) { 05661 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]); 05662 return NULL; 05663 } 05664 y = 1; 05665 do { 05666 if (b2) 05667 free(b2); 05668 #ifdef HAVE_PRI 05669 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS))) 05670 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y); 05671 else 05672 #endif 05673 if (i->channel == CHAN_PSEUDO) 05674 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random()); 05675 else 05676 b2 = ast_safe_string_alloc("%d-%d", i->channel, y); 05677 for (x = 0; x < 3; x++) { 05678 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6))) 05679 break; 05680 } 05681 y++; 05682 } while (x < 3); 05683 strcpy(chanprefix, dahdi_chan_name); 05684 strcat(chanprefix, "/%s"); 05685 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2); 05686 if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */ 05687 free(b2); 05688 if (!tmp) 05689 return NULL; 05690 tmp->tech = chan_tech; 05691 memset(&ps, 0, sizeof(ps)); 05692 ps.channo = i->channel; 05693 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps); 05694 if (res) { 05695 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno)); 05696 ps.curlaw = DAHDI_LAW_MULAW; 05697 } 05698 if (ps.curlaw == DAHDI_LAW_ALAW) 05699 deflaw = AST_FORMAT_ALAW; 05700 else 05701 deflaw = AST_FORMAT_ULAW; 05702 if (law) { 05703 if (law == DAHDI_LAW_ALAW) 05704 deflaw = AST_FORMAT_ALAW; 05705 else 05706 deflaw = AST_FORMAT_ULAW; 05707 } 05708 tmp->fds[0] = i->subs[index].dfd; 05709 tmp->nativeformats = deflaw; 05710 /* Start out assuming ulaw since it's smaller :) */ 05711 tmp->rawreadformat = deflaw; 05712 tmp->readformat = deflaw; 05713 tmp->rawwriteformat = deflaw; 05714 tmp->writeformat = deflaw; 05715 i->subs[index].linear = 0; 05716 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear); 05717 features = 0; 05718 if (index == SUB_REAL) { 05719 if (i->busydetect && CANBUSYDETECT(i)) 05720 features |= DSP_FEATURE_BUSY_DETECT; 05721 if ((i->callprogress & 1) && CANPROGRESSDETECT(i)) 05722 features |= DSP_FEATURE_CALL_PROGRESS; 05723 if ((!i->outgoing && (i->callprogress & 4)) || 05724 (i->outgoing && (i->callprogress & 2))) { 05725 features |= DSP_FEATURE_FAX_DETECT; 05726 } 05727 #ifdef DAHDI_TONEDETECT 05728 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 05729 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) { 05730 #endif 05731 i->hardwaredtmf = 0; 05732 features |= DSP_FEATURE_DTMF_DETECT; 05733 #ifdef DAHDI_TONEDETECT 05734 } else if (NEED_MFDETECT(i)) { 05735 i->hardwaredtmf = 1; 05736 features |= DSP_FEATURE_DTMF_DETECT; 05737 } 05738 #endif 05739 } 05740 if (features) { 05741 if (i->dsp) { 05742 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name); 05743 } else { 05744 if (i->channel != CHAN_PSEUDO) 05745 i->dsp = ast_dsp_new(); 05746 else 05747 i->dsp = NULL; 05748 if (i->dsp) { 05749 i->dsp_features = features; 05750 #ifdef HAVE_PRI 05751 /* We cannot do progress detection until receives PROGRESS message */ 05752 if (i->outgoing && (i->sig == SIG_PRI)) { 05753 /* Remember requested DSP features, don't treat 05754 talking as ANSWER */ 05755 i->dsp_features = features & ~DSP_PROGRESS_TALK; 05756 features = 0; 05757 } 05758 #endif 05759 ast_dsp_set_features(i->dsp, features); 05760 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax); 05761 if (!ast_strlen_zero(progzone)) 05762 ast_dsp_set_call_progress_zone(i->dsp, progzone); 05763 if (i->busydetect && CANBUSYDETECT(i)) { 05764 if(i->silencethreshold > 0) 05765 ast_dsp_set_threshold(i->dsp, i->silencethreshold); 05766 ast_dsp_set_busy_count(i->dsp, i->busycount); 05767 if(i->busytonelength > 0) 05768 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness); 05769 if((i->busytonelength == i->busyquietlength) && i->busycompare) 05770 ast_dsp_set_busy_compare(i->dsp, i->busycompare); 05771 } 05772 } 05773 } 05774 } 05775 05776 if (state == AST_STATE_RING) 05777 tmp->rings = 1; 05778 tmp->tech_pvt = i; 05779 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) { 05780 /* Only FXO signalled stuff can be picked up */ 05781 tmp->callgroup = i->callgroup; 05782 tmp->pickupgroup = i->pickupgroup; 05783 } 05784 if (!ast_strlen_zero(i->language)) 05785 ast_string_field_set(tmp, language, i->language); 05786 if (!i->owner) 05787 i->owner = tmp; 05788 if (!ast_strlen_zero(i->accountcode)) 05789 ast_string_field_set(tmp, accountcode, i->accountcode); 05790 if (i->amaflags) 05791 tmp->amaflags = i->amaflags; 05792 i->subs[index].owner = tmp; 05793 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 05794 ast_string_field_set(tmp, call_forward, i->call_forward); 05795 /* If we've been told "no ADSI" then enforce it */ 05796 if (!i->adsi) 05797 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 05798 if (!ast_strlen_zero(i->exten)) 05799 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 05800 if (!ast_strlen_zero(i->rdnis)) 05801 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 05802 if (!ast_strlen_zero(i->dnid)) 05803 tmp->cid.cid_dnid = ast_strdup(i->dnid); 05804 05805 /* Don't use ast_set_callerid() here because it will 05806 * generate a needless NewCallerID event */ 05807 #ifdef PRI_ANI 05808 if (!ast_strlen_zero(i->cid_ani)) 05809 tmp->cid.cid_ani = ast_strdup(i->cid_ani); 05810 else 05811 tmp->cid.cid_ani = ast_strdup(i->cid_num); 05812 #else 05813 tmp->cid.cid_ani = ast_strdup(i->cid_num); 05814 #endif 05815 tmp->cid.cid_pres = i->callingpres; 05816 tmp->cid.cid_ton = i->cid_ton; 05817 #ifdef HAVE_PRI 05818 tmp->transfercapability = transfercapability; 05819 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability)); 05820 if (transfercapability & PRI_TRANS_CAP_DIGITAL) 05821 i->digital = 1; 05822 /* Assume calls are not idle calls unless we're told differently */ 05823 i->isidlecall = 0; 05824 i->alreadyhungup = 0; 05825 #endif 05826 /* clear the fake event in case we posted one before we had ast_channel */ 05827 i->fake_event = 0; 05828 /* Assure there is no confmute on this channel */ 05829 dahdi_confmute(i, 0); 05830 /* Configure the new channel jb */ 05831 ast_jb_configure(tmp, &global_jbconf); 05832 if (startpbx) { 05833 if (ast_pbx_start(tmp)) { 05834 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 05835 ast_hangup(tmp); 05836 i->owner = NULL; 05837 return NULL; 05838 } 05839 } 05840 05841 ast_module_ref(ast_module_info->self); 05842 05843 return tmp; 05844 }
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 8744 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().
08745 { 08746 int x, y; 08747 int dchan = -1, span = -1; 08748 int dchancount = 0; 08749 08750 if (pri) { 08751 for (x = 0; x < NUM_SPANS; x++) { 08752 for (y = 0; y < NUM_DCHANS; y++) { 08753 if (pris[x].dchans[y]) 08754 dchancount++; 08755 08756 if (pris[x].dchans[y] == pri) 08757 dchan = y; 08758 } 08759 if (dchan >= 0) { 08760 span = x; 08761 break; 08762 } 08763 dchancount = 0; 08764 } 08765 if ((dchan >= 0) && (span >= 0)) { 08766 if (dchancount > 1) 08767 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s); 08768 else 08769 ast_log(LOG_ERROR, "%s", s); 08770 } else 08771 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n"); 08772 } else 08773 ast_log(LOG_ERROR, "%s", s); 08774 08775 ast_mutex_lock(&pridebugfdlock); 08776 08777 if (pridebugfd >= 0) { 08778 if (write(pridebugfd, s, strlen(s)) < 0) { 08779 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 08780 } 08781 } 08782 08783 ast_mutex_unlock(&pridebugfdlock); 08784 }
static void dahdi_pri_message | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 8702 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().
08703 { 08704 int x, y; 08705 int dchan = -1, span = -1; 08706 int dchancount = 0; 08707 08708 if (pri) { 08709 for (x = 0; x < NUM_SPANS; x++) { 08710 for (y = 0; y < NUM_DCHANS; y++) { 08711 if (pris[x].dchans[y]) 08712 dchancount++; 08713 08714 if (pris[x].dchans[y] == pri) 08715 dchan = y; 08716 } 08717 if (dchan >= 0) { 08718 span = x; 08719 break; 08720 } 08721 dchancount = 0; 08722 } 08723 if ((dchan >= 0) && (span >= 0)) { 08724 if (dchancount > 1) 08725 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s); 08726 else 08727 ast_verbose("%s", s); 08728 } else 08729 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n"); 08730 } else 08731 ast_verbose("%s", s); 08732 08733 ast_mutex_lock(&pridebugfdlock); 08734 08735 if (pridebugfd >= 0) { 08736 if (write(pridebugfd, s, strlen(s)) < 0) { 08737 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 08738 } 08739 } 08740 08741 ast_mutex_unlock(&pridebugfdlock); 08742 }
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 memset(&ps, 0, sizeof(ps)); 05116 ps.channo = p->channel; 05117 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 05118 ast_mutex_unlock(&p->lock); 05119 return NULL; 05120 } 05121 p->firstradio = 1; 05122 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05123 if (ps.rxisoffhook) 05124 { 05125 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY; 05126 } 05127 else 05128 { 05129 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY; 05130 } 05131 ast_mutex_unlock(&p->lock); 05132 return &p->subs[index].f; 05133 } 05134 if (p->ringt == 1) { 05135 ast_mutex_unlock(&p->lock); 05136 return NULL; 05137 } 05138 else if (p->ringt > 0) 05139 p->ringt--; 05140 05141 if (p->subs[index].needringing) { 05142 /* Send ringing frame if requested */ 05143 p->subs[index].needringing = 0; 05144 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05145 p->subs[index].f.subclass = AST_CONTROL_RINGING; 05146 ast_setstate(ast, AST_STATE_RINGING); 05147 ast_mutex_unlock(&p->lock); 05148 return &p->subs[index].f; 05149 } 05150 05151 if (p->subs[index].needbusy) { 05152 /* Send busy frame if requested */ 05153 p->subs[index].needbusy = 0; 05154 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05155 p->subs[index].f.subclass = AST_CONTROL_BUSY; 05156 ast_mutex_unlock(&p->lock); 05157 return &p->subs[index].f; 05158 } 05159 05160 if (p->subs[index].needcongestion) { 05161 /* Send congestion frame if requested */ 05162 p->subs[index].needcongestion = 0; 05163 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05164 p->subs[index].f.subclass = AST_CONTROL_CONGESTION; 05165 ast_mutex_unlock(&p->lock); 05166 return &p->subs[index].f; 05167 } 05168 05169 if (p->subs[index].needcallerid) { 05170 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL), 05171 S_OR(p->lastcid_name, NULL), 05172 S_OR(p->lastcid_num, NULL) 05173 ); 05174 p->subs[index].needcallerid = 0; 05175 } 05176 05177 if (p->subs[index].needanswer) { 05178 /* Send answer frame if requested */ 05179 p->subs[index].needanswer = 0; 05180 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05181 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05182 ast_mutex_unlock(&p->lock); 05183 return &p->subs[index].f; 05184 } 05185 05186 if (p->subs[index].needflash) { 05187 /* Send answer frame if requested */ 05188 p->subs[index].needflash = 0; 05189 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05190 p->subs[index].f.subclass = AST_CONTROL_FLASH; 05191 ast_mutex_unlock(&p->lock); 05192 return &p->subs[index].f; 05193 } 05194 05195 if (p->subs[index].needhold) { 05196 /* Send answer frame if requested */ 05197 p->subs[index].needhold = 0; 05198 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05199 p->subs[index].f.subclass = AST_CONTROL_HOLD; 05200 ast_mutex_unlock(&p->lock); 05201 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name); 05202 return &p->subs[index].f; 05203 } 05204 05205 if (p->subs[index].needunhold) { 05206 /* Send answer frame if requested */ 05207 p->subs[index].needunhold = 0; 05208 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05209 p->subs[index].f.subclass = AST_CONTROL_UNHOLD; 05210 ast_mutex_unlock(&p->lock); 05211 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name); 05212 return &p->subs[index].f; 05213 } 05214 05215 if (ast->rawreadformat == AST_FORMAT_SLINEAR) { 05216 if (!p->subs[index].linear) { 05217 p->subs[index].linear = 1; 05218 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 05219 if (res) 05220 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index); 05221 } 05222 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) || 05223 (ast->rawreadformat == AST_FORMAT_ALAW)) { 05224 if (p->subs[index].linear) { 05225 p->subs[index].linear = 0; 05226 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 05227 if (res) 05228 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index); 05229 } 05230 } else { 05231 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat)); 05232 ast_mutex_unlock(&p->lock); 05233 return NULL; 05234 } 05235 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET; 05236 CHECK_BLOCKING(ast); 05237 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE); 05238 ast_clear_flag(ast, AST_FLAG_BLOCKING); 05239 /* Check for hangup */ 05240 if (res < 0) { 05241 f = NULL; 05242 if (res == -1) { 05243 if (errno == EAGAIN) { 05244 /* Return "NULL" frame if there is nobody there */ 05245 ast_mutex_unlock(&p->lock); 05246 return &p->subs[index].f; 05247 } else if (errno == ELAST) { 05248 f = __dahdi_exception(ast); 05249 } else 05250 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno)); 05251 } 05252 ast_mutex_unlock(&p->lock); 05253 return f; 05254 } 05255 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) { 05256 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE); 05257 f = __dahdi_exception(ast); 05258 ast_mutex_unlock(&p->lock); 05259 return f; 05260 } 05261 if (p->tdd) { /* if in TDD mode, see if we receive that */ 05262 int c; 05263 05264 c = tdd_feed(p->tdd,readbuf,READ_SIZE); 05265 if (c < 0) { 05266 ast_log(LOG_DEBUG,"tdd_feed failed\n"); 05267 ast_mutex_unlock(&p->lock); 05268 return NULL; 05269 } 05270 if (c) { /* if a char to return */ 05271 p->subs[index].f.subclass = 0; 05272 p->subs[index].f.frametype = AST_FRAME_TEXT; 05273 p->subs[index].f.mallocd = 0; 05274 p->subs[index].f.offset = AST_FRIENDLY_OFFSET; 05275 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET; 05276 p->subs[index].f.datalen = 1; 05277 *((char *) p->subs[index].f.data) = c; 05278 ast_mutex_unlock(&p->lock); 05279 return &p->subs[index].f; 05280 } 05281 } 05282 /* Ensure the CW timer decrements only on a single subchannel */ 05283 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) { 05284 p->callwaitingrepeat--; 05285 } 05286 if (p->cidcwexpire) 05287 p->cidcwexpire--; 05288 /* Repeat callwaiting */ 05289 if (p->callwaitingrepeat == 1) { 05290 p->callwaitrings++; 05291 dahdi_callwait(ast); 05292 } 05293 /* Expire CID/CW */ 05294 if (p->cidcwexpire == 1) { 05295 if (option_verbose > 2) 05296 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n"); 05297 restore_conference(p); 05298 } 05299 if (p->subs[index].linear) { 05300 p->subs[index].f.datalen = READ_SIZE * 2; 05301 } else 05302 p->subs[index].f.datalen = READ_SIZE; 05303 05304 /* Handle CallerID Transmission */ 05305 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) { 05306 send_callerid(p); 05307 } 05308 05309 p->subs[index].f.frametype = AST_FRAME_VOICE; 05310 p->subs[index].f.subclass = ast->rawreadformat; 05311 p->subs[index].f.samples = READ_SIZE; 05312 p->subs[index].f.mallocd = 0; 05313 p->subs[index].f.offset = AST_FRIENDLY_OFFSET; 05314 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]); 05315 #if 0 05316 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name); 05317 #endif 05318 if (p->dialing || /* Transmitting something */ 05319 (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */ 05320 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */ 05321 ) { 05322 /* Whoops, we're still dialing, or in a state where we shouldn't transmit.... 05323 don't send anything */ 05324 p->subs[index].f.frametype = AST_FRAME_NULL; 05325 p->subs[index].f.subclass = 0; 05326 p->subs[index].f.samples = 0; 05327 p->subs[index].f.mallocd = 0; 05328 p->subs[index].f.offset = 0; 05329 p->subs[index].f.data = NULL; 05330 p->subs[index].f.datalen= 0; 05331 } 05332 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) { 05333 /* Perform busy detection. etc on the dahdi line */ 05334 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f); 05335 if (f) { 05336 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) { 05337 if ((ast->_state == AST_STATE_UP) && !p->outgoing) { 05338 /* Treat this as a "hangup" instead of a "busy" on the assumption that 05339 a busy */ 05340 f = NULL; 05341 } 05342 } else if (f->frametype == AST_FRAME_DTMF) { 05343 #ifdef HAVE_PRI 05344 if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) { 05345 /* Don't accept in-band DTMF when in overlap dial mode */ 05346 f->frametype = AST_FRAME_NULL; 05347 f->subclass = 0; 05348 } 05349 #endif 05350 /* DSP clears us of being pulse */ 05351 p->pulsedial = 0; 05352 } 05353 } 05354 } else 05355 f = &p->subs[index].f; 05356 05357 if (f && (f->frametype == AST_FRAME_DTMF)) 05358 dahdi_handle_dtmfup(ast, index, &f); 05359 05360 /* If we have a fake_event, trigger exception to handle it */ 05361 if (p->fake_event) 05362 ast_set_flag(ast, AST_FLAG_EXCEPTION); 05363 05364 ast_mutex_unlock(&p->lock); 05365 return f; 05366 }
static struct ast_channel * dahdi_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 8282 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().
08283 { 08284 ast_group_t groupmatch = 0; 08285 int channelmatch = -1; 08286 int roundrobin = 0; 08287 int callwait = 0; 08288 int busy = 0; 08289 struct dahdi_pvt *p; 08290 struct ast_channel *tmp = NULL; 08291 char *dest=NULL; 08292 int x; 08293 char *s; 08294 char opt=0; 08295 int res=0, y=0; 08296 int backwards = 0; 08297 #ifdef HAVE_PRI 08298 int crv; 08299 int bearer = -1; 08300 int trunkgroup; 08301 struct dahdi_pri *pri=NULL; 08302 #endif 08303 struct dahdi_pvt *exit, *start, *end; 08304 ast_mutex_t *lock; 08305 int channelmatched = 0; 08306 int groupmatched = 0; 08307 08308 /* 08309 * data is ---v 08310 * Dial(DAHDI/pseudo[/extension]) 08311 * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension]) 08312 * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension]) 08313 * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension]) 08314 * 08315 * g - channel group allocation search forward 08316 * G - channel group allocation search backward 08317 * r - channel group allocation round robin search forward 08318 * R - channel group allocation round robin search backward 08319 * 08320 * c - Wait for DTMF digit to confirm answer 08321 * r<cadance#> - Set distintive ring cadance number 08322 * d - Force bearer capability for ISDN call to digital. 08323 */ 08324 08325 /* Assume we're locking the iflock */ 08326 lock = &iflock; 08327 start = iflist; 08328 end = ifend; 08329 if (data) { 08330 dest = ast_strdupa((char *)data); 08331 } else { 08332 ast_log(LOG_WARNING, "Channel requested with no data\n"); 08333 return NULL; 08334 } 08335 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') { 08336 /* Retrieve the group number */ 08337 char *stringp; 08338 08339 stringp = dest + 1; 08340 s = strsep(&stringp, "/"); 08341 if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) { 08342 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data); 08343 return NULL; 08344 } 08345 groupmatch = ((ast_group_t) 1 << x); 08346 if (toupper(dest[0]) == 'G') { 08347 if (dest[0] == 'G') { 08348 backwards = 1; 08349 p = ifend; 08350 } else 08351 p = iflist; 08352 } else { 08353 if (dest[0] == 'R') { 08354 backwards = 1; 08355 p = round_robin[x]?round_robin[x]->prev:ifend; 08356 if (!p) 08357 p = ifend; 08358 } else { 08359 p = round_robin[x]?round_robin[x]->next:iflist; 08360 if (!p) 08361 p = iflist; 08362 } 08363 roundrobin = 1; 08364 } 08365 } else { 08366 char *stringp; 08367 08368 stringp = dest; 08369 s = strsep(&stringp, "/"); 08370 p = iflist; 08371 if (!strcasecmp(s, "pseudo")) { 08372 /* Special case for pseudo */ 08373 x = CHAN_PSEUDO; 08374 channelmatch = x; 08375 } 08376 #ifdef HAVE_PRI 08377 else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) { 08378 if ((trunkgroup < 1) || (crv < 1)) { 08379 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data); 08380 return NULL; 08381 } 08382 res--; 08383 for (x = 0; x < NUM_SPANS; x++) { 08384 if (pris[x].trunkgroup == trunkgroup) { 08385 pri = pris + x; 08386 lock = &pri->lock; 08387 start = pri->crvs; 08388 end = pri->crvend; 08389 break; 08390 } 08391 } 08392 if (!pri) { 08393 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup); 08394 return NULL; 08395 } 08396 channelmatch = crv; 08397 p = pris[x].crvs; 08398 } 08399 #endif 08400 else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) { 08401 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data); 08402 return NULL; 08403 } else { 08404 channelmatch = x; 08405 } 08406 } 08407 /* Search for an unowned channel */ 08408 ast_mutex_lock(lock); 08409 exit = p; 08410 while (p && !tmp) { 08411 if (roundrobin) 08412 round_robin[x] = p; 08413 #if 0 08414 ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch); 08415 #endif 08416 08417 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) { 08418 if (option_debug) 08419 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel); 08420 if (p->inalarm) 08421 goto next; 08422 08423 callwait = (p->owner != NULL); 08424 #ifdef HAVE_PRI 08425 if (pri && (p->subs[SUB_REAL].dfd < 0)) { 08426 if (p->sig != SIG_FXSKS) { 08427 /* Gotta find an actual channel to use for this 08428 CRV if this isn't a callwait */ 08429 bearer = pri_find_empty_chan(pri, 0); 08430 if (bearer < 0) { 08431 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv); 08432 p = NULL; 08433 break; 08434 } 08435 pri_assign_bearer(p, pri, pri->pvts[bearer]); 08436 } else { 08437 if (alloc_sub(p, 0)) { 08438 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n"); 08439 p = NULL; 08440 break; 08441 } else 08442 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n"); 08443 p->pri = pri; 08444 } 08445 } 08446 #endif 08447 if (p->channel == CHAN_PSEUDO) { 08448 p = chandup(p); 08449 if (!p) { 08450 break; 08451 } 08452 } 08453 if (p->owner) { 08454 if (alloc_sub(p, SUB_CALLWAIT)) { 08455 p = NULL; 08456 break; 08457 } 08458 } 08459 p->outgoing = 1; 08460 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0); 08461 #ifdef HAVE_PRI 08462 if (p->bearer) { 08463 /* Log owner to bearer channel, too */ 08464 p->bearer->owner = tmp; 08465 } 08466 #endif 08467 /* Make special notes */ 08468 if (res > 1) { 08469 if (opt == 'c') { 08470 /* Confirm answer */ 08471 p->confirmanswer = 1; 08472 } else if (opt == 'r') { 08473 /* Distinctive ring */ 08474 if (res < 3) 08475 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data); 08476 else 08477 p->distinctivering = y; 08478 } else if (opt == 'd') { 08479 /* If this is an ISDN call, make it digital */ 08480 p->digital = 1; 08481 if (tmp) 08482 tmp->transfercapability = AST_TRANS_CAP_DIGITAL; 08483 } else { 08484 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data); 08485 } 08486 } 08487 /* Note if the call is a call waiting call */ 08488 if (tmp && callwait) 08489 tmp->cdrflags |= AST_CDR_CALLWAIT; 08490 break; 08491 } 08492 next: 08493 if (backwards) { 08494 p = p->prev; 08495 if (!p) 08496 p = end; 08497 } else { 08498 p = p->next; 08499 if (!p) 08500 p = start; 08501 } 08502 /* stop when you roll to the one that we started from */ 08503 if (p == exit) 08504 break; 08505 } 08506 ast_mutex_unlock(lock); 08507 restart_monitor(); 08508 if (callwait) 08509 *cause = AST_CAUSE_BUSY; 08510 else if (!tmp) { 08511 if (channelmatched) { 08512 if (busy) 08513 *cause = AST_CAUSE_BUSY; 08514 } else if (groupmatched) { 08515 *cause = AST_CAUSE_CONGESTION; 08516 } 08517 } 08518 08519 return tmp; 08520 }
static int dahdi_restart | ( | void | ) | [static] |
Definition at line 10448 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().
10449 { 10450 #if defined(HAVE_PRI) 10451 int i, j; 10452 #endif 10453 int cancel_code; 10454 struct dahdi_pvt *p; 10455 10456 ast_mutex_lock(&restart_lock); 10457 10458 if (option_verbose) 10459 ast_verbose("Destroying channels and reloading DAHDI configuration.\n"); 10460 dahdi_softhangup_all(); 10461 if (option_verbose > 3) 10462 ast_verbose("Initial softhangup of all DAHDI channels complete.\n"); 10463 10464 #if defined(HAVE_PRI) 10465 for (i = 0; i < NUM_SPANS; i++) { 10466 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) { 10467 cancel_code = pthread_cancel(pris[i].master); 10468 pthread_kill(pris[i].master, SIGURG); 10469 if (option_debug > 3) 10470 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code); 10471 pthread_join(pris[i].master, NULL); 10472 if (option_debug > 3) 10473 ast_verbose("Joined thread of span %d\n", i); 10474 } 10475 } 10476 #endif 10477 10478 ast_mutex_lock(&monlock); 10479 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 10480 cancel_code = pthread_cancel(monitor_thread); 10481 pthread_kill(monitor_thread, SIGURG); 10482 if (option_debug > 3) 10483 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code); 10484 pthread_join(monitor_thread, NULL); 10485 if (option_debug > 3) 10486 ast_verbose("Joined monitor thread\n"); 10487 } 10488 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */ 10489 10490 ast_mutex_lock(&ss_thread_lock); 10491 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */ 10492 int x = DAHDI_FLASH; 10493 if (option_debug > 2) 10494 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count); 10495 10496 for (p = iflist; p; p = p->next) { 10497 if (p->owner) 10498 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 */ 10499 } 10500 ast_cond_wait(&ss_thread_complete, &ss_thread_lock); 10501 } 10502 10503 /* ensure any created channels before monitor threads were stopped are hungup */ 10504 dahdi_softhangup_all(); 10505 if (option_verbose > 3) 10506 ast_verbose("Final softhangup of all DAHDI channels complete.\n"); 10507 destroy_all_channels(); 10508 if (option_debug) 10509 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels()); 10510 10511 ast_mutex_unlock(&monlock); 10512 10513 #ifdef HAVE_PRI 10514 for (i = 0; i < NUM_SPANS; i++) { 10515 for (j = 0; j < NUM_DCHANS; j++) 10516 dahdi_close_pri_fd(&(pris[i]), j); 10517 } 10518 10519 memset(pris, 0, sizeof(pris)); 10520 for (i = 0; i < NUM_SPANS; i++) { 10521 ast_mutex_init(&pris[i].lock); 10522 pris[i].offset = -1; 10523 pris[i].master = AST_PTHREADT_NULL; 10524 for (j = 0; j < NUM_DCHANS; j++) 10525 pris[i].fds[j] = -1; 10526 } 10527 pri_set_error(dahdi_pri_error); 10528 pri_set_message(dahdi_pri_message); 10529 #endif 10530 10531 if (setup_dahdi(2) != 0) { 10532 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n"); 10533 ast_mutex_unlock(&ss_thread_lock); 10534 return 1; 10535 } 10536 ast_mutex_unlock(&ss_thread_lock); 10537 ast_mutex_unlock(&restart_lock); 10538 return 0; 10539 }
static int dahdi_restart_cmd | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 10541 of file chan_dahdi.c.
References dahdi_restart(), RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
10542 { 10543 if (argc != 2) { 10544 return RESULT_SHOWUSAGE; 10545 } 10546 10547 if (dahdi_restart() != 0) 10548 return RESULT_FAILURE; 10549 return RESULT_SUCCESS; 10550 }
static int dahdi_ring_phone | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3872 of file chan_dahdi.c.
References ast_log(), errno, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), and dahdi_handle_event().
03873 { 03874 int x; 03875 int res; 03876 /* Make sure our transmit state is on hook */ 03877 x = 0; 03878 x = DAHDI_ONHOOK; 03879 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 03880 do { 03881 x = DAHDI_RING; 03882 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 03883 if (res) { 03884 switch (errno) { 03885 case EBUSY: 03886 case EINTR: 03887 /* Wait just in case */ 03888 usleep(10000); 03889 continue; 03890 case EINPROGRESS: 03891 res = 0; 03892 break; 03893 default: 03894 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno)); 03895 res = 0; 03896 } 03897 } 03898 } while (res); 03899 return res; 03900 }
static int dahdi_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 2725 of file chan_dahdi.c.
References send_keypad_facility_exec().
Referenced by load_module().
02726 { 02727 return send_keypad_facility_exec(chan, data); 02728 }
static int dahdi_sendtext | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 12275 of file chan_dahdi.c.
References ASCII_BYTES_PER_CHAR, ast_check_hangup(), ast_free, AST_LAW, ast_log(), ast_malloc, dahdi_pvt::channel, dahdi_get_index(), dahdi_subchannel::dfd, END_SILENCE_LEN, errno, free, HEADER_LEN, HEADER_MS, len(), LOG_ERROR, dahdi_pvt::mate, option_debug, PUT_CLID, PUT_CLID_MARKMS, READ_SIZE, dahdi_pvt::subs, dahdi_pvt::tdd, TDD_BYTES_PER_CHAR, tdd_generate(), ast_channel::tech_pvt, and TRAILER_MS.
12276 { 12277 #define END_SILENCE_LEN 400 12278 #define HEADER_MS 50 12279 #define TRAILER_MS 5 12280 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) 12281 #define ASCII_BYTES_PER_CHAR 80 12282 12283 unsigned char *buf,*mybuf; 12284 struct dahdi_pvt *p = c->tech_pvt; 12285 struct pollfd fds[1]; 12286 int size,res,fd,len,x; 12287 int bytes=0; 12288 /* Initial carrier (imaginary) */ 12289 float cr = 1.0; 12290 float ci = 0.0; 12291 float scont = 0.0; 12292 int index; 12293 12294 index = dahdi_get_index(c, p, 0); 12295 if (index < 0) { 12296 ast_log(LOG_WARNING, "Huh? I don't exist?\n"); 12297 return -1; 12298 } 12299 if (!text[0]) return(0); /* if nothing to send, dont */ 12300 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */ 12301 if (p->mate) 12302 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN); 12303 else 12304 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN); 12305 if (!buf) 12306 return -1; 12307 mybuf = buf; 12308 if (p->mate) { 12309 int codec = AST_LAW(p); 12310 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */ 12311 PUT_CLID_MARKMS; 12312 } 12313 /* Put actual message */ 12314 for (x = 0; text[x]; x++) { 12315 PUT_CLID(text[x]); 12316 } 12317 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */ 12318 PUT_CLID_MARKMS; 12319 } 12320 len = bytes; 12321 buf = mybuf; 12322 } else { 12323 len = tdd_generate(p->tdd, buf, text); 12324 if (len < 1) { 12325 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text)); 12326 free(mybuf); 12327 return -1; 12328 } 12329 } 12330 memset(buf + len, 0x7f, END_SILENCE_LEN); 12331 len += END_SILENCE_LEN; 12332 fd = p->subs[index].dfd; 12333 while (len) { 12334 if (ast_check_hangup(c)) { 12335 free(mybuf); 12336 return -1; 12337 } 12338 size = len; 12339 if (size > READ_SIZE) 12340 size = READ_SIZE; 12341 fds[0].fd = fd; 12342 fds[0].events = POLLOUT | POLLPRI; 12343 fds[0].revents = 0; 12344 res = poll(fds, 1, -1); 12345 if (!res) { 12346 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel); 12347 continue; 12348 } 12349 /* if got exception */ 12350 if (fds[0].revents & POLLPRI) { 12351 ast_free(mybuf); 12352 return -1; 12353 } 12354 if (!(fds[0].revents & POLLOUT)) { 12355 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel); 12356 continue; 12357 } 12358 res = write(fd, buf, size); 12359 if (res != size) { 12360 if (res == -1) { 12361 free(mybuf); 12362 return -1; 12363 } 12364 if (option_debug) 12365 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 12366 break; 12367 } 12368 len -= size; 12369 buf += size; 12370 } 12371 free(mybuf); 12372 return(0); 12373 }
static int dahdi_set_hook | ( | int | fd, | |
int | hs | |||
) | [inline, static] |
Definition at line 1972 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().
01973 { 01974 int x, res; 01975 01976 x = hs; 01977 res = ioctl(fd, DAHDI_HOOK, &x); 01978 01979 if (res < 0) { 01980 if (errno == EINPROGRESS) 01981 return 0; 01982 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno)); 01983 /* will expectedly fail if phone is off hook during operation, such as during a restart */ 01984 } 01985 01986 return res; 01987 }
static int dahdi_setlaw | ( | int | dfd, | |
int | law | |||
) | [static] |
Definition at line 8876 of file chan_dahdi.c.
08877 { 08878 int res; 08879 res = ioctl(dfd, DAHDI_SETLAW, &law); 08880 if (res) 08881 return res; 08882 return 0; 08883 }
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 3236 of file chan_dahdi.c.
References ast_check_hangup(), ast_dsp_digitmode(), ast_log(), AST_OPTION_AUDIO_MODE, AST_OPTION_ECHOCAN, AST_OPTION_OPRMODE, AST_OPTION_RELAXDTMF, AST_OPTION_RXGAIN, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, AST_OPTION_TXGAIN, ast_tdd_gen_ecdisa(), dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_subchannel::dfd, dahdi_pvt::didtdd, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, errno, dahdi_pvt::law, len(), LOG_DEBUG, LOG_WARNING, dahdi_pvt::mate, oprmode::mode, ast_channel::name, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, option_debug, oprmode::peer, READ_SIZE, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_free(), tdd_new(), ast_channel::tech_pvt, and dahdi_pvt::txgain.
03237 { 03238 char *cp; 03239 signed char *scp; 03240 int x; 03241 int index; 03242 struct dahdi_pvt *p = chan->tech_pvt, *pp; 03243 struct oprmode *oprmode; 03244 03245 03246 /* all supported options require data */ 03247 if (!data || (datalen < 1)) { 03248 errno = EINVAL; 03249 return -1; 03250 } 03251 03252 switch (option) { 03253 case AST_OPTION_TXGAIN: 03254 scp = (signed char *) data; 03255 index = dahdi_get_index(chan, p, 0); 03256 if (index < 0) { 03257 ast_log(LOG_WARNING, "No index in TXGAIN?\n"); 03258 return -1; 03259 } 03260 if (option_debug) 03261 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp); 03262 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law); 03263 case AST_OPTION_RXGAIN: 03264 scp = (signed char *) data; 03265 index = dahdi_get_index(chan, p, 0); 03266 if (index < 0) { 03267 ast_log(LOG_WARNING, "No index in RXGAIN?\n"); 03268 return -1; 03269 } 03270 if (option_debug) 03271 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp); 03272 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law); 03273 case AST_OPTION_TONE_VERIFY: 03274 if (!p->dsp) 03275 break; 03276 cp = (char *) data; 03277 switch (*cp) { 03278 case 1: 03279 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name); 03280 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */ 03281 break; 03282 case 2: 03283 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name); 03284 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */ 03285 break; 03286 default: 03287 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name); 03288 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */ 03289 break; 03290 } 03291 break; 03292 case AST_OPTION_TDD: 03293 /* turn on or off TDD */ 03294 cp = (char *) data; 03295 p->mate = 0; 03296 if (!*cp) { /* turn it off */ 03297 if (option_debug) 03298 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name); 03299 if (p->tdd) 03300 tdd_free(p->tdd); 03301 p->tdd = 0; 03302 break; 03303 } 03304 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n", 03305 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name); 03306 dahdi_disable_ec(p); 03307 /* otherwise, turn it on */ 03308 if (!p->didtdd) { /* if havent done it yet */ 03309 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */ 03310 unsigned char *buf; 03311 int size, res, fd, len; 03312 struct pollfd fds[1]; 03313 03314 buf = mybuf; 03315 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */ 03316 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */ 03317 len = 40000; 03318 index = dahdi_get_index(chan, p, 0); 03319 if (index < 0) { 03320 ast_log(LOG_WARNING, "No index in TDD?\n"); 03321 return -1; 03322 } 03323 fd = p->subs[index].dfd; 03324 while (len) { 03325 if (ast_check_hangup(chan)) 03326 return -1; 03327 size = len; 03328 if (size > READ_SIZE) 03329 size = READ_SIZE; 03330 fds[0].fd = fd; 03331 fds[0].events = POLLPRI | POLLOUT; 03332 fds[0].revents = 0; 03333 res = poll(fds, 1, -1); 03334 if (!res) { 03335 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel); 03336 continue; 03337 } 03338 /* if got exception */ 03339 if (fds[0].revents & POLLPRI) 03340 return -1; 03341 if (!(fds[0].revents & POLLOUT)) { 03342 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel); 03343 continue; 03344 } 03345 res = write(fd, buf, size); 03346 if (res != size) { 03347 if (res == -1) return -1; 03348 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 03349 break; 03350 } 03351 len -= size; 03352 buf += size; 03353 } 03354 p->didtdd = 1; /* set to have done it now */ 03355 } 03356 if (*cp == 2) { /* Mate mode */ 03357 if (p->tdd) 03358 tdd_free(p->tdd); 03359 p->tdd = 0; 03360 p->mate = 1; 03361 break; 03362 } 03363 if (!p->tdd) { /* if we dont have one yet */ 03364 p->tdd = tdd_new(); /* allocate one */ 03365 } 03366 break; 03367 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */ 03368 if (!p->dsp) 03369 break; 03370 cp = (char *) data; 03371 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n", 03372 *cp ? "ON" : "OFF", (int) *cp, chan->name); 03373 p->dtmfrelax = 0; 03374 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 03375 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 03376 break; 03377 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */ 03378 cp = (char *) data; 03379 if (!*cp) { 03380 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name); 03381 x = 0; 03382 dahdi_disable_ec(p); 03383 } else { 03384 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name); 03385 x = 1; 03386 } 03387 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1) 03388 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno)); 03389 break; 03390 case AST_OPTION_OPRMODE: /* Operator services mode */ 03391 oprmode = (struct oprmode *) data; 03392 pp = oprmode->peer->tech_pvt; 03393 p->oprmode = pp->oprmode = 0; 03394 /* setup peers */ 03395 p->oprpeer = pp; 03396 pp->oprpeer = p; 03397 /* setup modes, if any */ 03398 if (oprmode->mode) 03399 { 03400 pp->oprmode = oprmode->mode; 03401 p->oprmode = -oprmode->mode; 03402 } 03403 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n", 03404 oprmode->mode, chan->name,oprmode->peer->name);; 03405 break; 03406 case AST_OPTION_ECHOCAN: 03407 cp = (char *) data; 03408 if (*cp) { 03409 ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name); 03410 dahdi_enable_ec(p); 03411 } else { 03412 ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name); 03413 dahdi_disable_ec(p); 03414 } 03415 break; 03416 } 03417 errno = 0; 03418 03419 return 0; 03420 }
static int dahdi_show_channel | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 10613 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.
10614 { 10615 int channel; 10616 struct dahdi_pvt *tmp = NULL; 10617 struct dahdi_confinfo ci; 10618 struct dahdi_params ps; 10619 int x; 10620 ast_mutex_t *lock; 10621 struct dahdi_pvt *start; 10622 #ifdef HAVE_PRI 10623 char *c; 10624 int trunkgroup; 10625 struct dahdi_pri *pri=NULL; 10626 #endif 10627 10628 lock = &iflock; 10629 start = iflist; 10630 10631 if (argc != 4) 10632 return RESULT_SHOWUSAGE; 10633 #ifdef HAVE_PRI 10634 if ((c = strchr(argv[3], ':'))) { 10635 if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2) 10636 return RESULT_SHOWUSAGE; 10637 if ((trunkgroup < 1) || (channel < 1)) 10638 return RESULT_SHOWUSAGE; 10639 for (x = 0; x < NUM_SPANS; x++) { 10640 if (pris[x].trunkgroup == trunkgroup) { 10641 pri = pris + x; 10642 break; 10643 } 10644 } 10645 if (pri) { 10646 start = pri->crvs; 10647 lock = &pri->lock; 10648 } else { 10649 ast_cli(fd, "No such trunk group %d\n", trunkgroup); 10650 return RESULT_FAILURE; 10651 } 10652 } else 10653 #endif 10654 channel = atoi(argv[3]); 10655 10656 ast_mutex_lock(lock); 10657 tmp = start; 10658 while (tmp) { 10659 if (tmp->channel == channel) { 10660 #ifdef HAVE_PRI 10661 if (pri) 10662 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel); 10663 else 10664 #endif 10665 ast_cli(fd, "Channel: %d\n", tmp->channel); 10666 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd); 10667 ast_cli(fd, "Span: %d\n", tmp->span); 10668 ast_cli(fd, "Extension: %s\n", tmp->exten); 10669 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no"); 10670 ast_cli(fd, "Context: %s\n", tmp->context); 10671 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num); 10672 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton); 10673 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name); 10674 ast_cli(fd, "Destroy: %d\n", tmp->destroy); 10675 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm); 10676 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig)); 10677 ast_cli(fd, "Radio: %d\n", tmp->radio); 10678 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>"); 10679 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)" : ""); 10680 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)" : ""); 10681 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)" : ""); 10682 ast_cli(fd, "Confno: %d\n", tmp->confno); 10683 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno); 10684 ast_cli(fd, "Real in conference: %d\n", tmp->inconference); 10685 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no"); 10686 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no"); 10687 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas); 10688 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown"); 10689 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no"); 10690 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no"); 10691 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF"); 10692 if (tmp->master) 10693 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel); 10694 for (x = 0; x < MAX_SLAVES; x++) { 10695 if (tmp->slaves[x]) 10696 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel); 10697 } 10698 #ifdef HAVE_PRI 10699 if (tmp->pri) { 10700 ast_cli(fd, "PRI Flags: "); 10701 if (tmp->resetting) 10702 ast_cli(fd, "Resetting "); 10703 if (tmp->call) 10704 ast_cli(fd, "Call "); 10705 if (tmp->bearer) 10706 ast_cli(fd, "Bearer "); 10707 ast_cli(fd, "\n"); 10708 if (tmp->logicalspan) 10709 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan); 10710 else 10711 ast_cli(fd, "PRI Logical Span: Implicit\n"); 10712 } 10713 10714 #endif 10715 memset(&ci, 0, sizeof(ci)); 10716 ps.channo = tmp->channel; 10717 if (tmp->subs[SUB_REAL].dfd > -1) { 10718 memset(&ci, 0, sizeof(ci)); 10719 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 10720 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode); 10721 } 10722 #ifdef DAHDI_GETCONFMUTE 10723 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) { 10724 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No"); 10725 } 10726 #endif 10727 memset(&ps, 0, sizeof(ps)); 10728 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 10729 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno)); 10730 } else { 10731 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook"); 10732 } 10733 } 10734 if (ISTRUNK(tmp)) { 10735 ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no"); 10736 if (!ast_strlen_zero(progzone)) 10737 ast_cli(fd, "Progress Zone: %s\n", progzone); 10738 ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no"); 10739 if(tmp->busydetect) { 10740 ast_cli(fd, "Busy Count: %d\n", tmp->busycount); 10741 if(tmp->busytonelength > 0) { 10742 ast_cli(fd, "Busy Pattern:\n"); 10743 ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength); 10744 if (tmp->busyquietlength > 0) 10745 ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength); 10746 else 10747 ast_cli(fd, " -- Detect Tone Only\n"); 10748 if(tmp->busyfuzziness > 0) 10749 ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness); 10750 } 10751 } 10752 } 10753 ast_mutex_unlock(lock); 10754 return RESULT_SUCCESS; 10755 } 10756 tmp = tmp->next; 10757 } 10758 10759 ast_cli(fd, "Unable to find given channel %d\n", channel); 10760 ast_mutex_unlock(lock); 10761 return RESULT_FAILURE; 10762 }
static int dahdi_show_channels | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 10552 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.
10553 { 10554 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" 10555 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" 10556 struct dahdi_pvt *tmp = NULL; 10557 char tmps[20] = ""; 10558 ast_mutex_t *lock; 10559 struct dahdi_pvt *start; 10560 #ifdef HAVE_PRI 10561 int trunkgroup; 10562 struct dahdi_pri *pri = NULL; 10563 int x; 10564 #endif 10565 10566 lock = &iflock; 10567 start = iflist; 10568 10569 #ifdef HAVE_PRI 10570 if (argc == 4) { 10571 if ((trunkgroup = atoi(argv[3])) < 1) 10572 return RESULT_SHOWUSAGE; 10573 for (x = 0; x < NUM_SPANS; x++) { 10574 if (pris[x].trunkgroup == trunkgroup) { 10575 pri = pris + x; 10576 break; 10577 } 10578 } 10579 if (pri) { 10580 start = pri->crvs; 10581 lock = &pri->lock; 10582 } else { 10583 ast_cli(fd, "No such trunk group %d\n", trunkgroup); 10584 return RESULT_FAILURE; 10585 } 10586 } else 10587 #endif 10588 if (argc != 3) 10589 return RESULT_SHOWUSAGE; 10590 10591 ast_mutex_lock(lock); 10592 #ifdef HAVE_PRI 10593 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret"); 10594 #else 10595 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret"); 10596 #endif 10597 10598 tmp = start; 10599 while (tmp) { 10600 if (tmp->channel > 0) { 10601 snprintf(tmps, sizeof(tmps), "%d", tmp->channel); 10602 } else 10603 ast_copy_string(tmps, "pseudo", sizeof(tmps)); 10604 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret); 10605 tmp = tmp->next; 10606 } 10607 ast_mutex_unlock(lock); 10608 return RESULT_SUCCESS; 10609 #undef FORMAT 10610 #undef FORMAT2 10611 }
static int dahdi_show_status | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10795 of file chan_dahdi.c.
References alarms, ast_cli(), ast_log(), DAHDI_FILE_CTL, errno, FORMAT, FORMAT2, RESULT_FAILURE, and dahdi_pri::span.
10795 { 10796 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n" 10797 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n" 10798 10799 int span; 10800 int res; 10801 char alarms[50]; 10802 10803 int ctl; 10804 struct dahdi_spaninfo s; 10805 10806 if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) { 10807 ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno)); 10808 ast_cli(fd, "No " DAHDI_NAME " interface found.\n"); 10809 return RESULT_FAILURE; 10810 } 10811 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4"); 10812 10813 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 10814 s.spanno = span; 10815 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 10816 if (res) { 10817 continue; 10818 } 10819 alarms[0] = '\0'; 10820 if (s.alarms > 0) { 10821 if (s.alarms & DAHDI_ALARM_BLUE) 10822 strcat(alarms, "BLU/"); 10823 if (s.alarms & DAHDI_ALARM_YELLOW) 10824 strcat(alarms, "YEL/"); 10825 if (s.alarms & DAHDI_ALARM_RED) 10826 strcat(alarms, "RED/"); 10827 if (s.alarms & DAHDI_ALARM_LOOPBACK) 10828 strcat(alarms, "LB/"); 10829 if (s.alarms & DAHDI_ALARM_RECOVER) 10830 strcat(alarms, "REC/"); 10831 if (s.alarms & DAHDI_ALARM_NOTOPEN) 10832 strcat(alarms, "NOP/"); 10833 if (!strlen(alarms)) 10834 strcat(alarms, "UUU/"); 10835 if (strlen(alarms)) { 10836 /* Strip trailing / */ 10837 alarms[strlen(alarms) - 1] = '\0'; 10838 } 10839 } else { 10840 if (s.numchans) 10841 strcpy(alarms, "OK"); 10842 else 10843 strcpy(alarms, "UNCONFIGURED"); 10844 } 10845 10846 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count); 10847 } 10848 close(ctl); 10849 10850 return RESULT_SUCCESS; 10851 #undef FORMAT 10852 #undef FORMAT2 10853 }
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 10419 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().
10420 { 10421 struct dahdi_pvt *p; 10422 retry: 10423 ast_mutex_lock(&iflock); 10424 for (p = iflist; p; p = p->next) { 10425 ast_mutex_lock(&p->lock); 10426 if (p->owner && !p->restartpending) { 10427 if (ast_channel_trylock(p->owner)) { 10428 if (option_debug > 2) 10429 ast_verbose("Avoiding deadlock\n"); 10430 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */ 10431 ast_mutex_unlock(&p->lock); 10432 ast_mutex_unlock(&iflock); 10433 goto retry; 10434 } 10435 if (option_debug > 2) 10436 ast_verbose("Softhanging up on %s\n", p->owner->name); 10437 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT); 10438 p->restartpending = 1; 10439 num_restart_pending++; 10440 ast_channel_unlock(p->owner); 10441 } 10442 ast_mutex_unlock(&p->lock); 10443 } 10444 ast_mutex_unlock(&iflock); 10445 }
static void dahdi_train_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1804 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().
01805 { 01806 int x; 01807 int res; 01808 if (p && p->echocancel && p->echotraining) { 01809 x = p->echotraining; 01810 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x); 01811 if (res) 01812 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno)); 01813 else { 01814 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel); 01815 } 01816 } else 01817 ast_log(LOG_DEBUG, "No echo training requested\n"); 01818 }
static void dahdi_unlink | ( | struct dahdi_pvt * | slave, | |
struct dahdi_pvt * | master, | |||
int | needlock | |||
) | [static] |
Definition at line 3441 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().
03442 { 03443 /* Unlink a specific slave or all slaves/masters from a given master */ 03444 int x; 03445 int hasslaves; 03446 if (!master) 03447 return; 03448 if (needlock) { 03449 ast_mutex_lock(&master->lock); 03450 if (slave) { 03451 while (ast_mutex_trylock(&slave->lock)) { 03452 DEADLOCK_AVOIDANCE(&master->lock); 03453 } 03454 } 03455 } 03456 hasslaves = 0; 03457 for (x = 0; x < MAX_SLAVES; x++) { 03458 if (master->slaves[x]) { 03459 if (!slave || (master->slaves[x] == slave)) { 03460 /* Take slave out of the conference */ 03461 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel); 03462 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL); 03463 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL); 03464 master->slaves[x]->master = NULL; 03465 master->slaves[x] = NULL; 03466 } else 03467 hasslaves = 1; 03468 } 03469 if (!hasslaves) 03470 master->inconference = 0; 03471 } 03472 if (!slave) { 03473 if (master->master) { 03474 /* Take master out of the conference */ 03475 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL); 03476 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL); 03477 hasslaves = 0; 03478 for (x = 0; x < MAX_SLAVES; x++) { 03479 if (master->master->slaves[x] == master) 03480 master->master->slaves[x] = NULL; 03481 else if (master->master->slaves[x]) 03482 hasslaves = 1; 03483 } 03484 if (!hasslaves) 03485 master->master->inconference = 0; 03486 } 03487 master->master = NULL; 03488 } 03489 update_conf(master); 03490 if (needlock) { 03491 if (slave) 03492 ast_mutex_unlock(&slave->lock); 03493 ast_mutex_unlock(&master->lock); 03494 } 03495 }
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 5866 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by ss_thread().
05867 { 05868 int j; 05869 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK); 05870 for (;;) 05871 { 05872 /* set bits of interest */ 05873 j = DAHDI_IOMUX_SIGEVENT; 05874 /* wait for some happening */ 05875 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1); 05876 /* exit loop if we have it */ 05877 if (j & DAHDI_IOMUX_SIGEVENT) break; 05878 } 05879 /* get the event info */ 05880 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1); 05881 return 0; 05882 }
static int dahdi_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 5391 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.
05392 { 05393 struct dahdi_pvt *p = ast->tech_pvt; 05394 int res; 05395 int index; 05396 index = dahdi_get_index(ast, p, 0); 05397 if (index < 0) { 05398 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name); 05399 return -1; 05400 } 05401 05402 #if 0 05403 #ifdef HAVE_PRI 05404 ast_mutex_lock(&p->lock); 05405 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { 05406 if (p->pri->pri) { 05407 if (!pri_grab(p, p->pri)) { 05408 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 05409 pri_rel(p->pri); 05410 } else 05411 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05412 } 05413 p->proceeding=1; 05414 } 05415 ast_mutex_unlock(&p->lock); 05416 #endif 05417 #endif 05418 /* Write a frame of (presumably voice) data */ 05419 if (frame->frametype != AST_FRAME_VOICE) { 05420 if (frame->frametype != AST_FRAME_IMAGE) 05421 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); 05422 return 0; 05423 } 05424 if ((frame->subclass != AST_FORMAT_SLINEAR) && 05425 (frame->subclass != AST_FORMAT_ULAW) && 05426 (frame->subclass != AST_FORMAT_ALAW)) { 05427 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass); 05428 return -1; 05429 } 05430 if (p->dialing) { 05431 if (option_debug) 05432 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name); 05433 return 0; 05434 } 05435 if (!p->owner) { 05436 if (option_debug) 05437 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name); 05438 return 0; 05439 } 05440 if (p->cidspill) { 05441 if (option_debug) 05442 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n"); 05443 return 0; 05444 } 05445 /* Return if it's not valid data */ 05446 if (!frame->data || !frame->datalen) 05447 return 0; 05448 05449 if (frame->subclass == AST_FORMAT_SLINEAR) { 05450 if (!p->subs[index].linear) { 05451 p->subs[index].linear = 1; 05452 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 05453 if (res) 05454 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel); 05455 } 05456 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1); 05457 } else { 05458 /* x-law already */ 05459 if (p->subs[index].linear) { 05460 p->subs[index].linear = 0; 05461 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 05462 if (res) 05463 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel); 05464 } 05465 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0); 05466 } 05467 if (res < 0) { 05468 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 05469 return -1; 05470 } 05471 return 0; 05472 }
static void destroy_all_channels | ( | void | ) | [static] |
Definition at line 2641 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().
02642 { 02643 int x; 02644 struct dahdi_pvt *p, *pl; 02645 02646 while (num_restart_pending) { 02647 usleep(1); 02648 } 02649 02650 ast_mutex_lock(&iflock); 02651 /* Destroy all the interfaces and free their memory */ 02652 p = iflist; 02653 while (p) { 02654 /* Free any callerid */ 02655 if (p->cidspill) 02656 ast_free(p->cidspill); 02657 pl = p; 02658 p = p->next; 02659 x = pl->channel; 02660 /* Free associated memory */ 02661 if (pl) 02662 destroy_dahdi_pvt(&pl); 02663 if (option_verbose > 2) 02664 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x); 02665 } 02666 iflist = NULL; 02667 ifcount = 0; 02668 ast_mutex_unlock(&iflock); 02669 }
Definition at line 2591 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().
02592 { 02593 int owned = 0; 02594 int i = 0; 02595 02596 if (!now) { 02597 if (cur->owner) { 02598 owned = 1; 02599 } 02600 02601 for (i = 0; i < 3; i++) { 02602 if (cur->subs[i].owner) { 02603 owned = 1; 02604 } 02605 } 02606 if (!owned) { 02607 if (prev) { 02608 prev->next = cur->next; 02609 if (prev->next) 02610 prev->next->prev = prev; 02611 else 02612 ifend = prev; 02613 } else { 02614 iflist = cur->next; 02615 if (iflist) 02616 iflist->prev = NULL; 02617 else 02618 ifend = NULL; 02619 } 02620 destroy_dahdi_pvt(&cur); 02621 } 02622 } else { 02623 if (prev) { 02624 prev->next = cur->next; 02625 if (prev->next) 02626 prev->next->prev = prev; 02627 else 02628 ifend = prev; 02629 } else { 02630 iflist = cur->next; 02631 if (iflist) 02632 iflist->prev = NULL; 02633 else 02634 ifend = NULL; 02635 } 02636 destroy_dahdi_pvt(&cur); 02637 } 02638 return 0; 02639 }
static void destroy_dahdi_pvt | ( | struct dahdi_pvt ** | pvt | ) | [static] |
Definition at line 2573 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().
02574 { 02575 struct dahdi_pvt *p = *pvt; 02576 /* Remove channel from the list */ 02577 if (p->prev) 02578 p->prev->next = p->next; 02579 if (p->next) 02580 p->next->prev = p->prev; 02581 if (p->use_smdi) 02582 ast_smdi_interface_unref(p->smdi_iface); 02583 ast_mutex_destroy(&p->lock); 02584 dahdi_close_sub(p, SUB_REAL); 02585 if (p->owner) 02586 p->owner->tech_pvt = NULL; 02587 free(p); 02588 *pvt = NULL; 02589 }
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 3520 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().
03521 { 03522 #ifdef DAHDI_TONEDETECT 03523 int val; 03524 #endif 03525 03526 p->ignoredtmf = 1; 03527 03528 #ifdef DAHDI_TONEDETECT 03529 val = 0; 03530 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 03531 #endif 03532 if (!p->hardwaredtmf && p->dsp) { 03533 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT; 03534 ast_dsp_set_features(p->dsp, p->dsp_features); 03535 } 03536 }
static void* do_idle_thread | ( | void * | vchan | ) | [static] |
Definition at line 8647 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().
08648 { 08649 struct ast_channel *chan = vchan; 08650 struct dahdi_pvt *pvt = chan->tech_pvt; 08651 struct ast_frame *f; 08652 char ex[80]; 08653 /* Wait up to 30 seconds for an answer */ 08654 int newms, ms = 30000; 08655 if (option_verbose > 2) 08656 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name); 08657 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial); 08658 if (ast_call(chan, ex, 0)) { 08659 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex); 08660 ast_hangup(chan); 08661 return NULL; 08662 } 08663 while ((newms = ast_waitfor(chan, ms)) > 0) { 08664 f = ast_read(chan); 08665 if (!f) { 08666 /* Got hangup */ 08667 break; 08668 } 08669 if (f->frametype == AST_FRAME_CONTROL) { 08670 switch (f->subclass) { 08671 case AST_CONTROL_ANSWER: 08672 /* Launch the PBX */ 08673 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten)); 08674 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context)); 08675 chan->priority = 1; 08676 if (option_verbose > 3) 08677 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context); 08678 ast_pbx_run(chan); 08679 /* It's already hungup, return immediately */ 08680 return NULL; 08681 case AST_CONTROL_BUSY: 08682 if (option_verbose > 3) 08683 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name); 08684 break; 08685 case AST_CONTROL_CONGESTION: 08686 if (option_verbose > 3) 08687 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name); 08688 break; 08689 }; 08690 } 08691 ast_frfree(f); 08692 ms = newms; 08693 } 08694 /* Hangup the channel since nothing happend */ 08695 ast_hangup(chan); 08696 return NULL; 08697 }
static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 7272 of file chan_dahdi.c.
References ast_calloc, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::cidspill, free, iflist, iflock, last, LOG_DEBUG, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::radio, dahdi_pvt::sig, SUB_REAL, and dahdi_pvt::subs.
Referenced by restart_monitor().
07273 { 07274 int count, res, res2, spoint, pollres=0; 07275 struct dahdi_pvt *i; 07276 struct dahdi_pvt *last = NULL; 07277 time_t thispass = 0, lastpass = 0; 07278 int found; 07279 char buf[1024]; 07280 struct pollfd *pfds=NULL; 07281 int lastalloc = -1; 07282 /* This thread monitors all the frame relay interfaces which are not yet in use 07283 (and thus do not have a separate thread) indefinitely */ 07284 /* From here on out, we die whenever asked */ 07285 #if 0 07286 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 07287 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 07288 return NULL; 07289 } 07290 ast_log(LOG_DEBUG, "Monitor starting...\n"); 07291 #endif 07292 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 07293 07294 for (;;) { 07295 /* Lock the interface list */ 07296 ast_mutex_lock(&iflock); 07297 if (!pfds || (lastalloc != ifcount)) { 07298 if (pfds) { 07299 free(pfds); 07300 pfds = NULL; 07301 } 07302 if (ifcount) { 07303 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) { 07304 ast_mutex_unlock(&iflock); 07305 return NULL; 07306 } 07307 } 07308 lastalloc = ifcount; 07309 } 07310 /* Build the stuff we're going to poll on, that is the socket of every 07311 dahdi_pvt that does not have an associated owner channel */ 07312 count = 0; 07313 i = iflist; 07314 while (i) { 07315 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) { 07316 if (!i->owner && !i->subs[SUB_REAL].owner) { 07317 /* This needs to be watched, as it lacks an owner */ 07318 pfds[count].fd = i->subs[SUB_REAL].dfd; 07319 pfds[count].events = POLLPRI; 07320 pfds[count].revents = 0; 07321 /* Message waiting or r2 channels also get watched for reading */ 07322 if (i->cidspill) 07323 pfds[count].events |= POLLIN; 07324 count++; 07325 } 07326 } 07327 i = i->next; 07328 } 07329 /* Okay, now that we know what to do, release the interface lock */ 07330 ast_mutex_unlock(&iflock); 07331 07332 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 07333 pthread_testcancel(); 07334 /* Wait at least a second for something to happen */ 07335 res = poll(pfds, count, 1000); 07336 pthread_testcancel(); 07337 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 07338 07339 /* Okay, poll has finished. Let's see what happened. */ 07340 if (res < 0) { 07341 if ((errno != EAGAIN) && (errno != EINTR)) 07342 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno)); 07343 continue; 07344 } 07345 /* Alright, lock the interface list again, and let's look and see what has 07346 happened */ 07347 ast_mutex_lock(&iflock); 07348 found = 0; 07349 spoint = 0; 07350 lastpass = thispass; 07351 thispass = time(NULL); 07352 i = iflist; 07353 while (i) { 07354 if (thispass != lastpass) { 07355 if (!found && ((i == last) || ((i == iflist) && !last))) { 07356 last = i; 07357 if (last) { 07358 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) && 07359 (last->sig & __DAHDI_SIG_FXO)) { 07360 res = ast_app_has_voicemail(last->mailbox, NULL); 07361 if (last->msgstate != res) { 07362 int x; 07363 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel); 07364 x = DAHDI_FLUSH_BOTH; 07365 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 07366 if (res2) 07367 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno)); 07368 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) { 07369 /* Turn on on hook transfer for 4 seconds */ 07370 x = 4000; 07371 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x); 07372 last->cidlen = ast_callerid_vmwi_generate(last->cidspill, res, 1, AST_LAW(last)); 07373 last->cidpos = 0; 07374 last->msgstate = res; 07375 last->onhooktime = thispass; 07376 } 07377 found ++; 07378 } 07379 } 07380 last = last->next; 07381 } 07382 } 07383 } 07384 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) { 07385 if (i->radio && !i->owner) 07386 { 07387 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 07388 if (res) 07389 { 07390 if (option_debug) 07391 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel); 07392 /* Don't hold iflock while handling init events */ 07393 ast_mutex_unlock(&iflock); 07394 handle_init_event(i, res); 07395 ast_mutex_lock(&iflock); 07396 } 07397 i = i->next; 07398 continue; 07399 } 07400 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint); 07401 if (pollres & POLLIN) { 07402 if (i->owner || i->subs[SUB_REAL].owner) { 07403 #ifdef HAVE_PRI 07404 if (!i->pri) 07405 #endif 07406 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd); 07407 i = i->next; 07408 continue; 07409 } 07410 if (!i->cidspill) { 07411 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd); 07412 i = i->next; 07413 continue; 07414 } 07415 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf)); 07416 if (res > 0) { 07417 /* We read some number of bytes. Write an equal amount of data */ 07418 if (res > i->cidlen - i->cidpos) 07419 res = i->cidlen - i->cidpos; 07420 res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res); 07421 if (res2 > 0) { 07422 i->cidpos += res2; 07423 if (i->cidpos >= i->cidlen) { 07424 free(i->cidspill); 07425 i->cidspill = 0; 07426 i->cidpos = 0; 07427 i->cidlen = 0; 07428 } 07429 } else { 07430 ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno)); 07431 i->msgstate = -1; 07432 } 07433 } else { 07434 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno)); 07435 } 07436 } 07437 if (pollres & POLLPRI) { 07438 if (i->owner || i->subs[SUB_REAL].owner) { 07439 #ifdef HAVE_PRI 07440 if (!i->pri) 07441 #endif 07442 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd); 07443 i = i->next; 07444 continue; 07445 } 07446 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 07447 if (option_debug) 07448 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel); 07449 /* Don't hold iflock while handling init events */ 07450 ast_mutex_unlock(&iflock); 07451 handle_init_event(i, res); 07452 ast_mutex_lock(&iflock); 07453 } 07454 } 07455 i=i->next; 07456 } 07457 ast_mutex_unlock(&iflock); 07458 } 07459 /* Never reached */ 07460 return NULL; 07461 07462 }
static void enable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3538 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().
03539 { 03540 #ifdef DAHDI_TONEDETECT 03541 int val; 03542 #endif 03543 03544 if (p->channel == CHAN_PSEUDO) 03545 return; 03546 03547 p->ignoredtmf = 0; 03548 03549 #ifdef DAHDI_TONEDETECT 03550 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 03551 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 03552 #endif 03553 if (!p->hardwaredtmf && p->dsp) { 03554 p->dsp_features |= DSP_FEATURE_DTMF_DETECT; 03555 ast_dsp_set_features(p->dsp, p->dsp_features); 03556 } 03557 }
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 1869 of file chan_dahdi.c.
References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_rxgain().
01870 { 01871 int j; 01872 int k; 01873 float linear_gain = pow(10.0, gain / 20.0); 01874 01875 switch (law) { 01876 case DAHDI_LAW_ALAW: 01877 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) { 01878 if (gain) { 01879 k = (int) (((float) AST_ALAW(j)) * linear_gain); 01880 if (k > 32767) k = 32767; 01881 if (k < -32767) k = -32767; 01882 g->rxgain[j] = AST_LIN2A(k); 01883 } else { 01884 g->rxgain[j] = j; 01885 } 01886 } 01887 break; 01888 case DAHDI_LAW_MULAW: 01889 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) { 01890 if (gain) { 01891 k = (int) (((float) AST_MULAW(j)) * linear_gain); 01892 if (k > 32767) k = 32767; 01893 if (k < -32767) k = -32767; 01894 g->rxgain[j] = AST_LIN2MU(k); 01895 } else { 01896 g->rxgain[j] = j; 01897 } 01898 } 01899 break; 01900 } 01901 }
static void fill_txgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 1835 of file chan_dahdi.c.
References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_txgain().
01836 { 01837 int j; 01838 int k; 01839 float linear_gain = pow(10.0, gain / 20.0); 01840 01841 switch (law) { 01842 case DAHDI_LAW_ALAW: 01843 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) { 01844 if (gain) { 01845 k = (int) (((float) AST_ALAW(j)) * linear_gain); 01846 if (k > 32767) k = 32767; 01847 if (k < -32767) k = -32767; 01848 g->txgain[j] = AST_LIN2A(k); 01849 } else { 01850 g->txgain[j] = j; 01851 } 01852 } 01853 break; 01854 case DAHDI_LAW_MULAW: 01855 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) { 01856 if (gain) { 01857 k = (int) (((float) AST_MULAW(j)) * linear_gain); 01858 if (k > 32767) k = 32767; 01859 if (k < -32767) k = -32767; 01860 g->txgain[j] = AST_LIN2MU(k); 01861 } else { 01862 g->txgain[j] = j; 01863 } 01864 } 01865 break; 01866 } 01867 }
static struct dahdi_pvt* find_channel | ( | int | channel | ) | [static] |
Definition at line 10953 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().
10954 { 10955 struct dahdi_pvt *p = iflist; 10956 while (p) { 10957 if (p->channel == channel) { 10958 break; 10959 } 10960 p = p->next; 10961 } 10962 return p; 10963 }
static int get_alarms | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3980 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().
03981 { 03982 int res; 03983 struct dahdi_spaninfo zi; 03984 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS) 03985 /* 03986 * The conditional compilation is needed only in asterisk-1.4 for 03987 * backward compatibility with old zaptel drivers that don't have 03988 * a DAHDI_PARAMS.chan_alarms field. 03989 */ 03990 struct dahdi_params params; 03991 #endif 03992 03993 memset(&zi, 0, sizeof(zi)); 03994 zi.spanno = p->span; 03995 03996 /* First check for span alarms */ 03997 if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) { 03998 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno)); 03999 return 0; 04000 } 04001 if (zi.alarms != DAHDI_ALARM_NONE) 04002 return zi.alarms; 04003 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS) 04004 /* No alarms on the span. Check for channel alarms. */ 04005 memset(¶ms, 0, sizeof(params)); 04006 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0) 04007 return params.chan_alarms; 04008 /* ioctl failed */ 04009 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel); 04010 #endif 04011 return DAHDI_ALARM_NONE; 04012 }
static void handle_alarms | ( | struct dahdi_pvt * | p, | |
int | alarms | |||
) | [static] |
Definition at line 4096 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().
04097 { 04098 const char *alarm_str = alarm2str(alarms); 04099 04100 /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code 04101 * doesn't know what to do with it. Don't confuse users with log messages. */ 04102 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) { 04103 p->unknown_alarm = 1; 04104 return; 04105 } else { 04106 p->unknown_alarm = 0; 04107 } 04108 04109 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); 04110 manager_event(EVENT_FLAG_SYSTEM, "Alarm", 04111 "Alarm: %s\r\n" 04112 "Channel: %d\r\n", 04113 alarm_str, p->channel); 04114 }
static int handle_dahdi_show_cadences | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10768 of file chan_dahdi.c.
References ast_cli(), COLOR_BLACK, COLOR_GREEN, COLOR_MAGENTA, and term_color().
10769 { 10770 int i, j; 10771 for (i = 0; i < num_cadence; i++) { 10772 char output[1024]; 10773 char tmp[16], tmp2[64]; 10774 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1); 10775 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output)); 10776 10777 for (j = 0; j < 16; j++) { 10778 if (cadences[i].ringcadence[j] == 0) 10779 break; 10780 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]); 10781 if (cidrings[i] * 2 - 1 == j) 10782 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1); 10783 else 10784 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1); 10785 if (j != 0) 10786 strncat(output, ",", sizeof(output) - strlen(output) - 1); 10787 strncat(output, tmp2, sizeof(output) - strlen(output) - 1); 10788 } 10789 ast_cli(fd,"%s\n",output); 10790 } 10791 return 0; 10792 }
static int handle_init_event | ( | struct dahdi_pvt * | i, | |
int | event | |||
) | [static] |
Definition at line 7064 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.
07065 { 07066 int res; 07067 pthread_t threadid; 07068 pthread_attr_t attr; 07069 struct ast_channel *chan; 07070 pthread_attr_init(&attr); 07071 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 07072 /* Handle an event on a given channel for the monitor thread. */ 07073 switch (event) { 07074 case DAHDI_EVENT_NONE: 07075 case DAHDI_EVENT_BITSCHANGED: 07076 break; 07077 case DAHDI_EVENT_WINKFLASH: 07078 case DAHDI_EVENT_RINGOFFHOOK: 07079 if (i->inalarm) break; 07080 if (i->radio) break; 07081 /* Got a ring/answer. What kind of channel are we? */ 07082 switch (i->sig) { 07083 case SIG_FXOLS: 07084 case SIG_FXOGS: 07085 case SIG_FXOKS: 07086 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07087 if (res && (errno == EBUSY)) 07088 break; 07089 if (i->cidspill) { 07090 /* Cancel VMWI spill */ 07091 free(i->cidspill); 07092 i->cidspill = NULL; 07093 } 07094 if (i->immediate) { 07095 dahdi_enable_ec(i); 07096 /* The channel is immediately up. Start right away */ 07097 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 07098 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0); 07099 if (!chan) { 07100 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel); 07101 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07102 if (res < 0) 07103 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 07104 } 07105 } else { 07106 /* Check for callerid, digits, etc */ 07107 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0); 07108 if (chan) { 07109 if (has_voicemail(i)) 07110 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 07111 else 07112 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 07113 if (res < 0) 07114 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel); 07115 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 07116 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 07117 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07118 if (res < 0) 07119 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 07120 ast_hangup(chan); 07121 } 07122 } else 07123 ast_log(LOG_WARNING, "Unable to create channel\n"); 07124 } 07125 break; 07126 case SIG_FXSLS: 07127 case SIG_FXSGS: 07128 case SIG_FXSKS: 07129 i->ringt = i->ringt_base; 07130 /* Fall through */ 07131 case SIG_EMWINK: 07132 case SIG_FEATD: 07133 case SIG_FEATDMF: 07134 case SIG_FEATDMF_TA: 07135 case SIG_E911: 07136 case SIG_FGC_CAMA: 07137 case SIG_FGC_CAMAMF: 07138 case SIG_FEATB: 07139 case SIG_EM: 07140 case SIG_EM_E1: 07141 case SIG_SFWINK: 07142 case SIG_SF_FEATD: 07143 case SIG_SF_FEATDMF: 07144 case SIG_SF_FEATB: 07145 case SIG_SF: 07146 /* Check for callerid, digits, etc */ 07147 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0); 07148 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 07149 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 07150 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07151 if (res < 0) 07152 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 07153 ast_hangup(chan); 07154 } else if (!chan) { 07155 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 07156 } 07157 break; 07158 default: 07159 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 07160 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07161 if (res < 0) 07162 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 07163 return -1; 07164 } 07165 break; 07166 case DAHDI_EVENT_NOALARM: 07167 i->inalarm = 0; 07168 if (!i->unknown_alarm) { 07169 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel); 07170 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 07171 "Channel: %d\r\n", i->channel); 07172 } else { 07173 i->unknown_alarm = 0; 07174 } 07175 break; 07176 case DAHDI_EVENT_ALARM: 07177 i->inalarm = 1; 07178 res = get_alarms(i); 07179 handle_alarms(i, res); 07180 /* fall thru intentionally */ 07181 case DAHDI_EVENT_ONHOOK: 07182 if (i->radio) 07183 break; 07184 /* Back on hook. Hang up. */ 07185 switch (i->sig) { 07186 case SIG_FXOLS: 07187 case SIG_FXOGS: 07188 case SIG_FEATD: 07189 case SIG_FEATDMF: 07190 case SIG_FEATDMF_TA: 07191 case SIG_E911: 07192 case SIG_FGC_CAMA: 07193 case SIG_FGC_CAMAMF: 07194 case SIG_FEATB: 07195 case SIG_EM: 07196 case SIG_EM_E1: 07197 case SIG_EMWINK: 07198 case SIG_SF_FEATD: 07199 case SIG_SF_FEATDMF: 07200 case SIG_SF_FEATB: 07201 case SIG_SF: 07202 case SIG_SFWINK: 07203 case SIG_FXSLS: 07204 case SIG_FXSGS: 07205 case SIG_FXSKS: 07206 case SIG_GR303FXSKS: 07207 dahdi_disable_ec(i); 07208 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 07209 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 07210 break; 07211 case SIG_GR303FXOKS: 07212 case SIG_FXOKS: 07213 dahdi_disable_ec(i); 07214 /* Diddle the battery for the zhone */ 07215 #ifdef ZHONE_HACK 07216 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07217 usleep(1); 07218 #endif 07219 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 07220 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 07221 break; 07222 case SIG_PRI: 07223 dahdi_disable_ec(i); 07224 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 07225 break; 07226 default: 07227 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 07228 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 07229 return -1; 07230 } 07231 break; 07232 case DAHDI_EVENT_POLARITY: 07233 switch (i->sig) { 07234 case SIG_FXSLS: 07235 case SIG_FXSKS: 07236 case SIG_FXSGS: 07237 /* We have already got a PR before the channel was 07238 created, but it wasn't handled. We need polarity 07239 to be REV for remote hangup detection to work. 07240 At least in Spain */ 07241 if (i->hanguponpolarityswitch) 07242 i->polarity = POLARITY_REV; 07243 07244 if (i->cid_start == CID_START_POLARITY) { 07245 i->polarity = POLARITY_REV; 07246 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity " 07247 "CID detection on channel %d\n", 07248 i->channel); 07249 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 07250 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 07251 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 07252 } 07253 } 07254 break; 07255 default: 07256 ast_log(LOG_WARNING, "handle_init_event detected " 07257 "polarity reversal on non-FXO (SIG_FXS) " 07258 "interface %d\n", i->channel); 07259 } 07260 break; 07261 case DAHDI_EVENT_REMOVED: /* destroy channel */ 07262 ast_log(LOG_NOTICE, 07263 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 07264 i->channel); 07265 dahdi_destroy_channel_bynum(i->channel); 07266 break; 07267 } 07268 pthread_attr_destroy(&attr); 07269 return 0; 07270 }
static int handle_pri_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10162 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
10163 { 10164 int span; 10165 int x; 10166 if (argc < 4) { 10167 return RESULT_SHOWUSAGE; 10168 } 10169 span = atoi(argv[3]); 10170 if ((span < 1) || (span > NUM_SPANS)) { 10171 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS); 10172 return RESULT_SUCCESS; 10173 } 10174 if (!pris[span-1].pri) { 10175 ast_cli(fd, "No PRI running on span %d\n", span); 10176 return RESULT_SUCCESS; 10177 } 10178 for (x = 0; x < NUM_DCHANS; x++) { 10179 if (pris[span-1].dchans[x]) 10180 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 10181 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 10182 PRI_DEBUG_Q921_STATE); 10183 } 10184 ast_cli(fd, "Enabled debugging on span %d\n", span); 10185 return RESULT_SUCCESS; 10186 }
static int handle_pri_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10190 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
10191 { 10192 int span; 10193 int x; 10194 if (argc < 5) 10195 return RESULT_SHOWUSAGE; 10196 span = atoi(argv[4]); 10197 if ((span < 1) || (span > NUM_SPANS)) { 10198 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS); 10199 return RESULT_SUCCESS; 10200 } 10201 if (!pris[span-1].pri) { 10202 ast_cli(fd, "No PRI running on span %d\n", span); 10203 return RESULT_SUCCESS; 10204 } 10205 for (x = 0; x < NUM_DCHANS; x++) { 10206 if (pris[span-1].dchans[x]) 10207 pri_set_debug(pris[span-1].dchans[x], 0); 10208 } 10209 ast_cli(fd, "Disabled debugging on span %d\n", span); 10210 return RESULT_SUCCESS; 10211 }
static int handle_pri_really_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10213 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
10214 { 10215 int span; 10216 int x; 10217 if (argc < 5) 10218 return RESULT_SHOWUSAGE; 10219 span = atoi(argv[4]); 10220 if ((span < 1) || (span > NUM_SPANS)) { 10221 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS); 10222 return RESULT_SUCCESS; 10223 } 10224 if (!pris[span-1].pri) { 10225 ast_cli(fd, "No PRI running on span %d\n", span); 10226 return RESULT_SUCCESS; 10227 } 10228 for (x = 0; x < NUM_DCHANS; x++) { 10229 if (pris[span-1].dchans[x]) 10230 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 10231 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 10232 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE); 10233 } 10234 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span); 10235 return RESULT_SUCCESS; 10236 }
static int handle_pri_set_debug_file | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 10115 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.
10116 { 10117 int myfd; 10118 10119 if (!strncasecmp(argv[1], "set", 3)) { 10120 if (argc < 5) 10121 return RESULT_SHOWUSAGE; 10122 10123 if (ast_strlen_zero(argv[4])) 10124 return RESULT_SHOWUSAGE; 10125 10126 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600); 10127 if (myfd < 0) { 10128 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]); 10129 return RESULT_SUCCESS; 10130 } 10131 10132 ast_mutex_lock(&pridebugfdlock); 10133 10134 if (pridebugfd >= 0) 10135 close(pridebugfd); 10136 10137 pridebugfd = myfd; 10138 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename)); 10139 10140 ast_mutex_unlock(&pridebugfdlock); 10141 10142 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]); 10143 } else { 10144 /* Assume it is unset */ 10145 ast_mutex_lock(&pridebugfdlock); 10146 close(pridebugfd); 10147 pridebugfd = -1; 10148 ast_cli(fd, "PRI debug output to file disabled\n"); 10149 ast_mutex_unlock(&pridebugfdlock); 10150 } 10151 10152 return RESULT_SUCCESS; 10153 }
static int handle_pri_show_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10319 of file chan_dahdi.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), debug, NUM_SPANS, pridebugfdlock, pris, and RESULT_SUCCESS.
10320 { 10321 int x; 10322 int span; 10323 int count=0; 10324 int debug=0; 10325 10326 for (span = 0; span < NUM_SPANS; span++) { 10327 if (pris[span].pri) { 10328 for (x = 0; x < NUM_DCHANS; x++) { 10329 debug = 0; 10330 if (pris[span].dchans[x]) { 10331 debug = pri_get_debug(pris[span].dchans[x]); 10332 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" ); 10333 count++; 10334 } 10335 } 10336 } 10337 10338 } 10339 ast_mutex_lock(&pridebugfdlock); 10340 if (pridebugfd >= 0) 10341 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename); 10342 ast_mutex_unlock(&pridebugfdlock); 10343 10344 if (!count) 10345 ast_cli(fd, "No debug set or no PRI running\n"); 10346 return RESULT_SUCCESS; 10347 }
static int handle_pri_show_span | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10280 of file chan_dahdi.c.
References ast_cli(), build_status(), free, NUM_SPANS, pri_order(), pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
10281 { 10282 int span; 10283 int x; 10284 char status[256]; 10285 if (argc < 4) 10286 return RESULT_SHOWUSAGE; 10287 span = atoi(argv[3]); 10288 if ((span < 1) || (span > NUM_SPANS)) { 10289 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS); 10290 return RESULT_SUCCESS; 10291 } 10292 if (!pris[span-1].pri) { 10293 ast_cli(fd, "No PRI running on span %d\n", span); 10294 return RESULT_SUCCESS; 10295 } 10296 for (x = 0; x < NUM_DCHANS; x++) { 10297 if (pris[span-1].dchannels[x]) { 10298 #ifdef PRI_DUMP_INFO_STR 10299 char *info_str = NULL; 10300 #endif 10301 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]); 10302 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri); 10303 ast_cli(fd, "Status: %s\n", status); 10304 #ifdef PRI_DUMP_INFO_STR 10305 info_str = pri_dump_info_str(pris[span-1].pri); 10306 if (info_str) { 10307 ast_cli(fd, "%s", info_str); 10308 free(info_str); 10309 } 10310 #else 10311 pri_dump_info(pris[span-1].pri); 10312 #endif 10313 ast_cli(fd, "\n"); 10314 } 10315 } 10316 return RESULT_SUCCESS; 10317 }
static int handle_pri_show_spans | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10259 of file chan_dahdi.c.
References ast_cli(), build_status(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
10260 { 10261 int span; 10262 int x; 10263 char status[256]; 10264 if (argc != 3) 10265 return RESULT_SHOWUSAGE; 10266 10267 for (span = 0; span < NUM_SPANS; span++) { 10268 if (pris[span].pri) { 10269 for (x = 0; x < NUM_DCHANS; x++) { 10270 if (pris[span].dchannels[x]) { 10271 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri); 10272 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status); 10273 } 10274 } 10275 } 10276 } 10277 return RESULT_SUCCESS; 10278 }
static int handle_pri_version | ( | int | fd, | |
int | agc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10156 of file chan_dahdi.c.
References ast_cli(), and RESULT_SUCCESS.
10156 { 10157 ast_cli(fd, "libpri version: %s\n", pri_get_version()); 10158 return RESULT_SUCCESS; 10159 }
static int has_voicemail | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2066 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().
02067 { 02068 02069 return ast_app_has_voicemail(p->mailbox, NULL); 02070 }
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 1655 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().
01656 { 01657 int x; 01658 int useslavenative; 01659 struct dahdi_pvt *slave = NULL; 01660 /* Start out optimistic */ 01661 useslavenative = 1; 01662 /* Update conference state in a stateless fashion */ 01663 for (x = 0; x < 3; x++) { 01664 /* Any three-way calling makes slave native mode *definitely* out 01665 of the question */ 01666 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) 01667 useslavenative = 0; 01668 } 01669 /* If we don't have any 3-way calls, check to see if we have 01670 precisely one slave */ 01671 if (useslavenative) { 01672 for (x = 0; x < MAX_SLAVES; x++) { 01673 if (p->slaves[x]) { 01674 if (slave) { 01675 /* Whoops already have a slave! No 01676 slave native and stop right away */ 01677 slave = NULL; 01678 useslavenative = 0; 01679 break; 01680 } else { 01681 /* We have one slave so far */ 01682 slave = p->slaves[x]; 01683 } 01684 } 01685 } 01686 } 01687 /* If no slave, slave native definitely out */ 01688 if (!slave) 01689 useslavenative = 0; 01690 else if (slave->law != p->law) { 01691 useslavenative = 0; 01692 slave = NULL; 01693 } 01694 if (out) 01695 *out = slave; 01696 return useslavenative; 01697 }
static int load_module | ( | void | ) | [static] |
Definition at line 12218 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.
12219 { 12220 int res; 12221 12222 #ifdef HAVE_PRI 12223 int y,i; 12224 memset(pris, 0, sizeof(pris)); 12225 for (y = 0; y < NUM_SPANS; y++) { 12226 ast_mutex_init(&pris[y].lock); 12227 pris[y].offset = -1; 12228 pris[y].master = AST_PTHREADT_NULL; 12229 for (i = 0; i < NUM_DCHANS; i++) 12230 pris[y].fds[i] = -1; 12231 } 12232 pri_set_error(dahdi_pri_error); 12233 pri_set_message(dahdi_pri_message); 12234 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 12235 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec, 12236 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip); 12237 } 12238 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec, 12239 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip); 12240 #endif 12241 if ((res = setup_dahdi(0))) { 12242 return AST_MODULE_LOAD_DECLINE; 12243 } 12244 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 12245 chan_tech = &dahdi_tech; 12246 } else { 12247 chan_tech = &zap_tech; 12248 } 12249 if (ast_channel_register(chan_tech)) { 12250 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type); 12251 __unload_module(); 12252 return -1; 12253 } 12254 #ifdef HAVE_PRI 12255 ast_string_field_init(&inuse, 16); 12256 ast_string_field_set(&inuse, name, "GR-303InUse"); 12257 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry)); 12258 #endif 12259 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 12260 12261 memset(round_robin, 0, sizeof(round_robin)); 12262 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel"); 12263 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel"); 12264 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook"); 12265 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON"); 12266 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF"); 12267 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels"); 12268 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)"); 12269 12270 ast_cond_init(&ss_thread_complete, NULL); 12271 12272 return res; 12273 }
static struct dahdi_pvt* mkintf | ( | int | channel, | |
const struct dahdi_chan_conf * | conf, | |||
struct dahdi_pri * | pri, | |||
int | reloading | |||
) | [static] |
Definition at line 7618 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().
07619 { 07620 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */ 07621 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL; 07622 char fn[80]; 07623 #if 1 07624 struct dahdi_bufferinfo bi; 07625 #endif 07626 int res; 07627 int span=0; 07628 int here = 0; 07629 int x; 07630 struct dahdi_pvt **wlist; 07631 struct dahdi_pvt **wend; 07632 struct dahdi_params p; 07633 07634 wlist = &iflist; 07635 wend = &ifend; 07636 07637 #ifdef HAVE_PRI 07638 if (pri) { 07639 wlist = &pri->crvs; 07640 wend = &pri->crvend; 07641 } 07642 #endif 07643 07644 tmp2 = *wlist; 07645 prev = NULL; 07646 07647 while (tmp2) { 07648 if (!tmp2->destroy) { 07649 if (tmp2->channel == channel) { 07650 tmp = tmp2; 07651 here = 1; 07652 break; 07653 } 07654 if (tmp2->channel > channel) { 07655 break; 07656 } 07657 } 07658 prev = tmp2; 07659 tmp2 = tmp2->next; 07660 } 07661 07662 if (!here && reloading != 1) { 07663 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { 07664 if (tmp) 07665 free(tmp); 07666 return NULL; 07667 } 07668 ast_mutex_init(&tmp->lock); 07669 ifcount++; 07670 for (x = 0; x < 3; x++) 07671 tmp->subs[x].dfd = -1; 07672 tmp->channel = channel; 07673 } 07674 07675 if (tmp) { 07676 int chan_sig = conf->chan.sig; 07677 if (!here) { 07678 if ((channel != CHAN_PSEUDO) && !pri) { 07679 int count = 0; 07680 snprintf(fn, sizeof(fn), "%d", channel); 07681 /* Open non-blocking */ 07682 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 07683 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 */ 07684 usleep(1); 07685 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 07686 count++; 07687 } 07688 /* Allocate a DAHDI structure */ 07689 if (tmp->subs[SUB_REAL].dfd < 0) { 07690 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); 07691 destroy_dahdi_pvt(&tmp); 07692 return NULL; 07693 } 07694 memset(&p, 0, sizeof(p)); 07695 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 07696 if (res < 0) { 07697 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno)); 07698 destroy_dahdi_pvt(&tmp); 07699 return NULL; 07700 } 07701 if (p.sigtype != (conf->chan.sig & 0x3ffff)) { 07702 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)); 07703 destroy_dahdi_pvt(&tmp); 07704 return NULL; 07705 } 07706 tmp->law = p.curlaw; 07707 tmp->span = p.spanno; 07708 span = p.spanno - 1; 07709 } else { 07710 if (channel == CHAN_PSEUDO) 07711 chan_sig = 0; 07712 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) { 07713 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n"); 07714 return NULL; 07715 } 07716 } 07717 #ifdef HAVE_PRI 07718 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) { 07719 int offset; 07720 int myswitchtype; 07721 int matchesdchan; 07722 int x,y; 07723 offset = 0; 07724 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) { 07725 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 07726 destroy_dahdi_pvt(&tmp); 07727 return NULL; 07728 } 07729 if (span >= NUM_SPANS) { 07730 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span); 07731 destroy_dahdi_pvt(&tmp); 07732 return NULL; 07733 } else { 07734 struct dahdi_spaninfo si; 07735 si.spanno = 0; 07736 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) { 07737 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); 07738 destroy_dahdi_pvt(&tmp); 07739 return NULL; 07740 } 07741 /* Store the logical span first based upon the real span */ 07742 tmp->logicalspan = pris[span].prilogicalspan; 07743 pri_resolve_span(&span, channel, (channel - p.chanpos), &si); 07744 if (span < 0) { 07745 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel); 07746 destroy_dahdi_pvt(&tmp); 07747 return NULL; 07748 } 07749 if (chan_sig == SIG_PRI) 07750 myswitchtype = conf->pri.switchtype; 07751 else 07752 myswitchtype = PRI_SWITCH_GR303_TMC; 07753 /* Make sure this isn't a d-channel */ 07754 matchesdchan=0; 07755 for (x = 0; x < NUM_SPANS; x++) { 07756 for (y = 0; y < NUM_DCHANS; y++) { 07757 if (pris[x].dchannels[y] == tmp->channel) { 07758 matchesdchan = 1; 07759 break; 07760 } 07761 } 07762 } 07763 offset = p.chanpos; 07764 if (!matchesdchan) { 07765 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) { 07766 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype)); 07767 destroy_dahdi_pvt(&tmp); 07768 return NULL; 07769 } 07770 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) { 07771 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype)); 07772 destroy_dahdi_pvt(&tmp); 07773 return NULL; 07774 } 07775 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) { 07776 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan)); 07777 destroy_dahdi_pvt(&tmp); 07778 return NULL; 07779 } 07780 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) { 07781 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial); 07782 destroy_dahdi_pvt(&tmp); 07783 return NULL; 07784 } 07785 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) { 07786 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext); 07787 destroy_dahdi_pvt(&tmp); 07788 return NULL; 07789 } 07790 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) { 07791 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused); 07792 destroy_dahdi_pvt(&tmp); 07793 return NULL; 07794 } 07795 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) { 07796 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle); 07797 destroy_dahdi_pvt(&tmp); 07798 return NULL; 07799 } 07800 if (pris[span].numchans >= MAX_CHANNELS) { 07801 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, 07802 pris[span].trunkgroup); 07803 destroy_dahdi_pvt(&tmp); 07804 return NULL; 07805 } 07806 pris[span].nodetype = conf->pri.nodetype; 07807 pris[span].switchtype = myswitchtype; 07808 pris[span].nsf = conf->pri.nsf; 07809 pris[span].dialplan = conf->pri.dialplan; 07810 pris[span].localdialplan = conf->pri.localdialplan; 07811 pris[span].pvts[pris[span].numchans++] = tmp; 07812 pris[span].minunused = conf->pri.minunused; 07813 pris[span].minidle = conf->pri.minidle; 07814 pris[span].overlapdial = conf->pri.overlapdial; 07815 #ifdef HAVE_PRI_INBANDDISCONNECT 07816 pris[span].inbanddisconnect = conf->pri.inbanddisconnect; 07817 #endif 07818 pris[span].facilityenable = conf->pri.facilityenable; 07819 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial)); 07820 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext)); 07821 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix)); 07822 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix)); 07823 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix)); 07824 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix)); 07825 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix)); 07826 pris[span].resetinterval = conf->pri.resetinterval; 07827 07828 tmp->pri = &pris[span]; 07829 tmp->prioffset = offset; 07830 tmp->call = NULL; 07831 } else { 07832 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset); 07833 destroy_dahdi_pvt(&tmp); 07834 return NULL; 07835 } 07836 } 07837 } else { 07838 tmp->prioffset = 0; 07839 } 07840 #endif 07841 } else { 07842 chan_sig = tmp->sig; 07843 if (tmp->subs[SUB_REAL].dfd > -1) { 07844 memset(&p, 0, sizeof(p)); 07845 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 07846 } 07847 } 07848 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */ 07849 switch (chan_sig) { 07850 case SIG_FXSKS: 07851 case SIG_FXSLS: 07852 case SIG_EM: 07853 case SIG_EM_E1: 07854 case SIG_EMWINK: 07855 case SIG_FEATD: 07856 case SIG_FEATDMF: 07857 case SIG_FEATDMF_TA: 07858 case SIG_FEATB: 07859 case SIG_E911: 07860 case SIG_SF: 07861 case SIG_SFWINK: 07862 case SIG_FGC_CAMA: 07863 case SIG_FGC_CAMAMF: 07864 case SIG_SF_FEATD: 07865 case SIG_SF_FEATDMF: 07866 case SIG_SF_FEATB: 07867 p.starttime = 250; 07868 break; 07869 } 07870 07871 if (tmp->radio) { 07872 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */ 07873 p.channo = channel; 07874 p.rxwinktime = 1; 07875 p.rxflashtime = 1; 07876 p.starttime = 1; 07877 p.debouncetime = 5; 07878 } 07879 if (!tmp->radio) { 07880 p.channo = channel; 07881 /* Override timing settings based on config file */ 07882 if (conf->timing.prewinktime >= 0) 07883 p.prewinktime = conf->timing.prewinktime; 07884 if (conf->timing.preflashtime >= 0) 07885 p.preflashtime = conf->timing.preflashtime; 07886 if (conf->timing.winktime >= 0) 07887 p.winktime = conf->timing.winktime; 07888 if (conf->timing.flashtime >= 0) 07889 p.flashtime = conf->timing.flashtime; 07890 if (conf->timing.starttime >= 0) 07891 p.starttime = conf->timing.starttime; 07892 if (conf->timing.rxwinktime >= 0) 07893 p.rxwinktime = conf->timing.rxwinktime; 07894 if (conf->timing.rxflashtime >= 0) 07895 p.rxflashtime = conf->timing.rxflashtime; 07896 if (conf->timing.debouncetime >= 0) 07897 p.debouncetime = conf->timing.debouncetime; 07898 } 07899 07900 /* dont set parms on a pseudo-channel (or CRV) */ 07901 if (tmp->subs[SUB_REAL].dfd >= 0) 07902 { 07903 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p); 07904 if (res < 0) { 07905 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno)); 07906 destroy_dahdi_pvt(&tmp); 07907 return NULL; 07908 } 07909 } 07910 #if 1 07911 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) { 07912 memset(&bi, 0, sizeof(bi)); 07913 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 07914 if (!res) { 07915 bi.txbufpolicy = conf->chan.buf_policy; 07916 bi.rxbufpolicy = conf->chan.buf_policy; 07917 bi.numbufs = conf->chan.buf_no; 07918 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 07919 if (res < 0) { 07920 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno)); 07921 } 07922 } else 07923 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno)); 07924 } 07925 #endif 07926 tmp->immediate = conf->chan.immediate; 07927 tmp->transfertobusy = conf->chan.transfertobusy; 07928 tmp->sig = chan_sig; 07929 tmp->outsigmod = conf->chan.outsigmod; 07930 tmp->ringt_base = ringt_base; 07931 tmp->firstradio = 0; 07932 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS)) 07933 tmp->permcallwaiting = conf->chan.callwaiting; 07934 else 07935 tmp->permcallwaiting = 0; 07936 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */ 07937 tmp->destroy = 0; 07938 tmp->drings = drings; 07939 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection; 07940 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid; 07941 tmp->threewaycalling = conf->chan.threewaycalling; 07942 tmp->adsi = conf->chan.adsi; 07943 tmp->use_smdi = conf->chan.use_smdi; 07944 tmp->permhidecallerid = conf->chan.hidecallerid; 07945 tmp->callreturn = conf->chan.callreturn; 07946 tmp->echocancel = conf->chan.echocancel; 07947 tmp->echotraining = conf->chan.echotraining; 07948 tmp->pulse = conf->chan.pulse; 07949 if (tmp->echocancel) 07950 tmp->echocanbridged = conf->chan.echocanbridged; 07951 else { 07952 if (conf->chan.echocanbridged) 07953 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n"); 07954 tmp->echocanbridged = 0; 07955 } 07956 tmp->busydetect = conf->chan.busydetect; 07957 tmp->busycount = conf->chan.busycount; 07958 tmp->busycompare = conf->chan.busycompare; 07959 tmp->busytonelength = conf->chan.busytonelength; 07960 tmp->busyquietlength = conf->chan.busyquietlength; 07961 tmp->busyfuzziness = conf->chan.busyfuzziness; 07962 tmp->silencethreshold = conf->chan.silencethreshold; 07963 tmp->callprogress = conf->chan.callprogress; 07964 tmp->cancallforward = conf->chan.cancallforward; 07965 tmp->dtmfrelax = conf->chan.dtmfrelax; 07966 tmp->callwaiting = tmp->permcallwaiting; 07967 tmp->hidecallerid = tmp->permhidecallerid; 07968 tmp->channel = channel; 07969 tmp->stripmsd = conf->chan.stripmsd; 07970 tmp->use_callerid = conf->chan.use_callerid; 07971 tmp->cid_signalling = conf->chan.cid_signalling; 07972 tmp->cid_start = conf->chan.cid_start; 07973 tmp->dahditrcallerid = conf->chan.dahditrcallerid; 07974 tmp->restrictcid = conf->chan.restrictcid; 07975 tmp->use_callingpres = conf->chan.use_callingpres; 07976 tmp->priindication_oob = conf->chan.priindication_oob; 07977 tmp->priexclusive = conf->chan.priexclusive; 07978 if (tmp->usedistinctiveringdetection) { 07979 if (!tmp->use_callerid) { 07980 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n"); 07981 tmp->use_callerid = 1; 07982 } 07983 } 07984 07985 if (tmp->cid_signalling == CID_SIG_SMDI) { 07986 if (!tmp->use_smdi) { 07987 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n"); 07988 tmp->use_smdi = 1; 07989 } 07990 } 07991 if (tmp->use_smdi) { 07992 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port); 07993 if (!(tmp->smdi_iface)) { 07994 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n"); 07995 tmp->use_smdi = 0; 07996 } 07997 } 07998 07999 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode)); 08000 tmp->amaflags = conf->chan.amaflags; 08001 if (!here) { 08002 tmp->confno = -1; 08003 tmp->propconfno = -1; 08004 } 08005 tmp->canpark = conf->chan.canpark; 08006 tmp->transfer = conf->chan.transfer; 08007 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext)); 08008 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language)); 08009 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret)); 08010 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest)); 08011 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context)); 08012 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num)); 08013 tmp->cid_ton = 0; 08014 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name)); 08015 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox)); 08016 tmp->msgstate = -1; 08017 tmp->group = conf->chan.group; 08018 tmp->callgroup = conf->chan.callgroup; 08019 tmp->pickupgroup= conf->chan.pickupgroup; 08020 tmp->rxgain = conf->chan.rxgain; 08021 tmp->txgain = conf->chan.txgain; 08022 tmp->tonezone = conf->chan.tonezone; 08023 tmp->onhooktime = time(NULL); 08024 if (tmp->subs[SUB_REAL].dfd > -1) { 08025 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law); 08026 if (tmp->dsp) 08027 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax); 08028 update_conf(tmp); 08029 if (!here) { 08030 if (chan_sig != SIG_PRI) 08031 /* Hang it up to be sure it's good */ 08032 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08033 } 08034 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone); 08035 #ifdef HAVE_PRI 08036 /* the dchannel is down so put the channel in alarm */ 08037 if (tmp->pri && !pri_is_up(tmp->pri)) { 08038 tmp->inalarm = 1; 08039 } 08040 #endif 08041 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) { 08042 tmp->inalarm = 1; 08043 handle_alarms(tmp, res); 08044 } else { 08045 /* yes, this looks strange... the unknown_alarm flag is only used to 08046 control whether an 'alarm cleared' message gets generated when we 08047 get an indication that the channel is no longer in alarm status. 08048 however, the channel *could* be in an alarm status that we aren't 08049 aware of (since get_alarms() only reports span alarms, not channel 08050 alarms). setting this flag will cause any potential 'alarm cleared' 08051 message to be suppressed, but if a real alarm occurs before that 08052 happens, this flag will get cleared by it and the situation will 08053 be normal. 08054 */ 08055 tmp->unknown_alarm = 1; 08056 } 08057 } 08058 08059 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 08060 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 08061 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 08062 tmp->sendcalleridafter = conf->chan.sendcalleridafter; 08063 08064 } 08065 if (tmp && !here) { 08066 /* nothing on the iflist */ 08067 if (!*wlist) { 08068 *wlist = tmp; 08069 tmp->prev = NULL; 08070 tmp->next = NULL; 08071 *wend = tmp; 08072 } else { 08073 /* at least one member on the iflist */ 08074 struct dahdi_pvt *working = *wlist; 08075 08076 /* check if we maybe have to put it on the begining */ 08077 if (working->channel > tmp->channel) { 08078 tmp->next = *wlist; 08079 tmp->prev = NULL; 08080 (*wlist)->prev = tmp; 08081 *wlist = tmp; 08082 } else { 08083 /* go through all the members and put the member in the right place */ 08084 while (working) { 08085 /* in the middle */ 08086 if (working->next) { 08087 if (working->channel < tmp->channel && working->next->channel > tmp->channel) { 08088 tmp->next = working->next; 08089 tmp->prev = working; 08090 working->next->prev = tmp; 08091 working->next = tmp; 08092 break; 08093 } 08094 } else { 08095 /* the last */ 08096 if (working->channel < tmp->channel) { 08097 working->next = tmp; 08098 tmp->next = NULL; 08099 tmp->prev = working; 08100 *wend = tmp; 08101 break; 08102 } 08103 } 08104 working = working->next; 08105 } 08106 } 08107 } 08108 } 08109 return tmp; 08110 }
static int my_dahdi_write | ( | struct dahdi_pvt * | p, | |
unsigned char * | buf, | |||
int | len, | |||
int | index, | |||
int | linear | |||
) | [static] |
Definition at line 5368 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().
05369 { 05370 int sent=0; 05371 int size; 05372 int res; 05373 int fd; 05374 fd = p->subs[index].dfd; 05375 while (len) { 05376 size = len; 05377 if (size > (linear ? READ_SIZE * 2 : READ_SIZE)) 05378 size = (linear ? READ_SIZE * 2 : READ_SIZE); 05379 res = write(fd, buf, size); 05380 if (res != size) { 05381 if (option_debug) 05382 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 05383 return sent; 05384 } 05385 len -= size; 05386 buf += size; 05387 } 05388 return sent; 05389 }
static int my_getsigstr | ( | struct ast_channel * | chan, | |
char * | str, | |||
const char * | term, | |||
int | ms | |||
) | [static] |
Definition at line 5847 of file chan_dahdi.c.
References ast_waitfordigit().
Referenced by ss_thread().
05848 { 05849 char c; 05850 05851 *str = 0; /* start with empty output buffer */ 05852 for (;;) 05853 { 05854 /* Wait for the first digit (up to specified ms). */ 05855 c = ast_waitfordigit(chan, ms); 05856 /* if timeout, hangup or error, return as such */ 05857 if (c < 1) 05858 return c; 05859 *str++ = c; 05860 *str = 0; 05861 if (strchr(term, c)) 05862 return 1; 05863 } 05864 }
static int pri_active_dchan_fd | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 2776 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().
02777 { 02778 int x = -1; 02779 02780 for (x = 0; x < NUM_DCHANS; x++) { 02781 if ((pri->dchans[x] == pri->pri)) 02782 break; 02783 } 02784 02785 return pri->fds[x]; 02786 }
static int pri_assign_bearer | ( | struct dahdi_pvt * | crv, | |
struct dahdi_pri * | pri, | |||
struct dahdi_pvt * | bearer | |||
) | [static] |
Definition at line 2746 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().
02747 { 02748 bearer->owner = &inuse; 02749 bearer->realcall = crv; 02750 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd; 02751 if (crv->subs[SUB_REAL].owner) 02752 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd; 02753 crv->bearer = bearer; 02754 crv->call = bearer->call; 02755 crv->pri = pri; 02756 return 0; 02757 }
static int pri_check_restart | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 8786 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().
08787 { 08788 do { 08789 pri->resetpos++; 08790 } while ((pri->resetpos < pri->numchans) && 08791 (!pri->pvts[pri->resetpos] || 08792 pri->pvts[pri->resetpos]->call || 08793 pri->pvts[pri->resetpos]->resetting)); 08794 if (pri->resetpos < pri->numchans) { 08795 /* Mark the channel as resetting and restart it */ 08796 pri->pvts[pri->resetpos]->resetting = 1; 08797 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos])); 08798 } else { 08799 pri->resetting = 0; 08800 time(&pri->lastreset); 08801 } 08802 return 0; 08803 }
static int pri_create_spanmap | ( | int | span, | |
int | trunkgroup, | |||
int | logicalspan | |||
) | [static] |
Definition at line 7605 of file chan_dahdi.c.
References ast_log(), dahdi_pri::mastertrunkgroup, dahdi_pri::prilogicalspan, and pris.
Referenced by setup_dahdi().
07606 { 07607 if (pris[span].mastertrunkgroup) { 07608 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); 07609 return -1; 07610 } 07611 pris[span].mastertrunkgroup = trunkgroup; 07612 pris[span].prilogicalspan = logicalspan; 07613 return 0; 07614 }
static int pri_create_trunkgroup | ( | int | trunkgroup, | |
int * | channels | |||
) | [static] |
Definition at line 7542 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().
07543 { 07544 struct dahdi_spaninfo si; 07545 struct dahdi_params p; 07546 int fd; 07547 int span; 07548 int ospan=0; 07549 int x,y; 07550 for (x = 0; x < NUM_SPANS; x++) { 07551 if (pris[x].trunkgroup == trunkgroup) { 07552 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]); 07553 return -1; 07554 } 07555 } 07556 for (y = 0; y < NUM_DCHANS; y++) { 07557 if (!channels[y]) 07558 break; 07559 memset(&si, 0, sizeof(si)); 07560 memset(&p, 0, sizeof(p)); 07561 fd = open(DAHDI_FILE_CHANNEL, O_RDWR); 07562 if (fd < 0) { 07563 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno)); 07564 return -1; 07565 } 07566 x = channels[y]; 07567 if (ioctl(fd, DAHDI_SPECIFY, &x)) { 07568 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno)); 07569 close(fd); 07570 return -1; 07571 } 07572 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) { 07573 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno)); 07574 return -1; 07575 } 07576 if (ioctl(fd, DAHDI_SPANSTAT, &si)) { 07577 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno)); 07578 close(fd); 07579 return -1; 07580 } 07581 span = p.spanno - 1; 07582 if (pris[span].trunkgroup) { 07583 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup); 07584 close(fd); 07585 return -1; 07586 } 07587 if (pris[span].pvts[0]) { 07588 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1); 07589 close(fd); 07590 return -1; 07591 } 07592 if (!y) { 07593 pris[span].trunkgroup = trunkgroup; 07594 pris[span].offset = channels[y] - p.chanpos; 07595 ospan = span; 07596 } 07597 pris[ospan].dchannels[y] = channels[y]; 07598 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED; 07599 pris[span].span = span + 1; 07600 close(fd); 07601 } 07602 return 0; 07603 }
static void* pri_dchannel | ( | void * | vpri | ) | [static] |
Definition at line 8885 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_copy_string(), ast_exists_extension(), AST_FORMAT_ULAW, ast_log(), ast_mutex_lock(), ast_pthread_create_background, AST_SOFTHANGUP_DEV, ast_strlen_zero(), ast_tv(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), dahdi_pvt::call, dahdi_pvt::channel, dahdi_chan_name, dahdi_hangup(), dahdi_request(), dahdi_pri::dchannels, dahdi_pri::dchans, do_idle_thread(), dahdi_pri::fds, dahdi_pri::idlecontext, dahdi_pri::idledial, dahdi_pri::idleext, dahdi_pvt::isidlecall, dahdi_pri::lastreset, dahdi_pri::lock, dahdi_pri::minidle, dahdi_pri::minunused, ast_channel::name, dahdi_pri::numchans, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pri::pri, pri_check_restart(), pri_is_up(), dahdi_pri::pvts, dahdi_pri::resetinterval, dahdi_pri::resetpos, dahdi_pvt::resetting, dahdi_pri::resetting, dahdi_pri::switchtype, and t.
08886 { 08887 struct dahdi_pri *pri = vpri; 08888 pri_event *e; 08889 struct pollfd fds[NUM_DCHANS]; 08890 int res; 08891 int chanpos = 0; 08892 int x; 08893 int haveidles; 08894 int activeidles; 08895 int nextidle = -1; 08896 struct ast_channel *c; 08897 struct timeval tv, lowest, *next; 08898 struct timeval lastidle = { 0, 0 }; 08899 int doidling=0; 08900 char *cc; 08901 char idlen[80]; 08902 struct ast_channel *idle; 08903 pthread_t p; 08904 time_t t; 08905 int i, which=-1; 08906 int numdchans; 08907 int cause=0; 08908 struct dahdi_pvt *crv; 08909 pthread_t threadid; 08910 pthread_attr_t attr; 08911 char ani2str[6]; 08912 char plancallingnum[256]; 08913 char plancallingani[256]; 08914 char calledtonstr[10]; 08915 08916 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08917 08918 gettimeofday(&lastidle, NULL); 08919 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) { 08920 /* Need to do idle dialing, check to be sure though */ 08921 cc = strchr(pri->idleext, '@'); 08922 if (cc) { 08923 *cc = '\0'; 08924 cc++; 08925 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext)); 08926 #if 0 08927 /* Extensions may not be loaded yet */ 08928 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL)) 08929 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext); 08930 else 08931 #endif 08932 doidling = 1; 08933 } else 08934 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext); 08935 } 08936 for (;;) { 08937 for (i = 0; i < NUM_DCHANS; i++) { 08938 if (!pri->dchannels[i]) 08939 break; 08940 fds[i].fd = pri->fds[i]; 08941 fds[i].events = POLLIN | POLLPRI; 08942 fds[i].revents = 0; 08943 } 08944 numdchans = i; 08945 time(&t); 08946 ast_mutex_lock(&pri->lock); 08947 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) { 08948 if (pri->resetting && pri_is_up(pri)) { 08949 if (pri->resetpos < 0) 08950 pri_check_restart(pri); 08951 } else { 08952 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) { 08953 pri->resetting = 1; 08954 pri->resetpos = -1; 08955 } 08956 } 08957 } 08958 /* Look for any idle channels if appropriate */ 08959 if (doidling && pri_is_up(pri)) { 08960 nextidle = -1; 08961 haveidles = 0; 08962 activeidles = 0; 08963 for (x = pri->numchans; x >= 0; x--) { 08964 if (pri->pvts[x] && !pri->pvts[x]->owner && 08965 !pri->pvts[x]->call) { 08966 if (haveidles < pri->minunused) { 08967 haveidles++; 08968 } else if (!pri->pvts[x]->resetting) { 08969 nextidle = x; 08970 break; 08971 } 08972 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) 08973 activeidles++; 08974 } 08975 if (nextidle > -1) { 08976 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) { 08977 /* Don't create a new idle call more than once per second */ 08978 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial); 08979 idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause); 08980 if (idle) { 08981 pri->pvts[nextidle]->isidlecall = 1; 08982 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) { 08983 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name); 08984 dahdi_hangup(idle); 08985 } 08986 } else 08987 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen); 08988 gettimeofday(&lastidle, NULL); 08989 } 08990 } else if ((haveidles < pri->minunused) && 08991 (activeidles > pri->minidle)) { 08992 /* Mark something for hangup if there is something 08993 that can be hungup */ 08994 for (x = pri->numchans; x >= 0; x--) { 08995 /* find a candidate channel */ 08996 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) { 08997 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 08998 haveidles++; 08999 /* Stop if we have enough idle channels or 09000 can't spare any more active idle ones */ 09001 if ((haveidles >= pri->minunused) || 09002 (activeidles <= pri->minidle)) 09003 break; 09004 } 09005 } 09006 } 09007 } 09008 /* Start with reasonable max */ 09009 lowest = ast_tv(60, 0); 09010 for (i = 0; i < NUM_DCHANS; i++) { 09011 /* Find lowest available d-channel */ 09012 if (!pri->dchannels[i]) 09013 break; 09014 if ((next = pri_schedule_next(pri->dchans[i]))) { 09015 /* We need relative time here */ 09016 tv = ast_tvsub(*next, ast_tvnow()); 09017 if (tv.tv_sec < 0) { 09018 tv = ast_tv(0,0); 09019 } 09020 if (doidling || pri->resetting) { 09021 if (tv.tv_sec > 1) { 09022 tv = ast_tv(1, 0); 09023 } 09024 } else { 09025 if (tv.tv_sec > 60) { 09026 tv = ast_tv(60, 0); 09027 } 09028 } 09029 } else if (doidling || pri->resetting) { 09030 /* Make sure we stop at least once per second if we're 09031 monitoring idle channels */ 09032 tv = ast_tv(1,0); 09033 } else { 09034 /* Don't poll for more than 60 seconds */ 09035 tv = ast_tv(60, 0); 09036 } 09037 if (!i || ast_tvcmp(tv, lowest) < 0) { 09038 lowest = tv; 09039 } 09040 } 09041 ast_mutex_unlock(&pri->lock); 09042 09043 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 09044 pthread_testcancel(); 09045 e = NULL; 09046 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000); 09047 pthread_testcancel(); 09048 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 09049 09050 ast_mutex_lock(&pri->lock); 09051 if (!res) { 09052 for (which = 0; which < NUM_DCHANS; which++) { 09053 if (!pri->dchans[which]) 09054 break; 09055 /* Just a timeout, run the scheduler */ 09056 e = pri_schedule_run(pri->dchans[which]); 09057 if (e) 09058 break; 09059 } 09060 } else if (res > -1) { 09061 for (which = 0; which < NUM_DCHANS; which++) { 09062 if (!pri->dchans[which]) 09063 break; 09064 if (fds[which].revents & POLLPRI) { 09065 /* Check for an event */ 09066 x = 0; 09067 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x); 09068 if (x) 09069 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); 09070 /* Keep track of alarm state */ 09071 if (x == DAHDI_EVENT_ALARM) { 09072 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP); 09073 pri_find_dchan(pri); 09074 } else if (x == DAHDI_EVENT_NOALARM) { 09075 pri->dchanavail[which] |= DCHAN_NOTINALARM; 09076 pri_restart(pri->dchans[which]); 09077 } 09078 09079 if (option_debug) 09080 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span); 09081 } else if (fds[which].revents & POLLIN) { 09082 e = pri_check_event(pri->dchans[which]); 09083 } 09084 if (e) 09085 break; 09086 } 09087 } else if (errno != EINTR) 09088 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno)); 09089 09090 if (e) { 09091 if (pri->debug) 09092 pri_dump_event(pri->dchans[which], e); 09093 09094 if (e->e != PRI_EVENT_DCHAN_DOWN) { 09095 if (!(pri->dchanavail[which] & DCHAN_UP)) { 09096 if (option_verbose > 1) 09097 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span); 09098 } 09099 pri->dchanavail[which] |= DCHAN_UP; 09100 } else { 09101 if (pri->dchanavail[which] & DCHAN_UP) { 09102 if (option_verbose > 1) 09103 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span); 09104 } 09105 pri->dchanavail[which] &= ~DCHAN_UP; 09106 } 09107 09108 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which])) 09109 /* Must be an NFAS group that has the secondary dchan active */ 09110 pri->pri = pri->dchans[which]; 09111 09112 switch (e->e) { 09113 case PRI_EVENT_DCHAN_UP: 09114 if (!pri->pri) pri_find_dchan(pri); 09115 09116 /* Note presense of D-channel */ 09117 time(&pri->lastreset); 09118 09119 /* Restart in 5 seconds */ 09120 if (pri->resetinterval > -1) { 09121 pri->lastreset -= pri->resetinterval; 09122 pri->lastreset += 5; 09123 } 09124 pri->resetting = 0; 09125 /* Take the channels from inalarm condition */ 09126 for (i = 0; i < pri->numchans; i++) 09127 if (pri->pvts[i]) { 09128 pri->pvts[i]->inalarm = 0; 09129 } 09130 break; 09131 case PRI_EVENT_DCHAN_DOWN: 09132 pri_find_dchan(pri); 09133 if (!pri_is_up(pri)) { 09134 pri->resetting = 0; 09135 /* Hangup active channels and put them in alarm mode */ 09136 for (i = 0; i < pri->numchans; i++) { 09137 struct dahdi_pvt *p = pri->pvts[i]; 09138 if (p) { 09139 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 09140 /* T309 is not enabled : hangup calls when alarm occurs */ 09141 if (p->call) { 09142 if (p->pri && p->pri->pri) { 09143 pri_hangup(p->pri->pri, p->call, -1); 09144 pri_destroycall(p->pri->pri, p->call); 09145 p->call = NULL; 09146 } else 09147 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n"); 09148 } 09149 if (p->realcall) { 09150 pri_hangup_all(p->realcall, pri); 09151 } else if (p->owner) 09152 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09153 } 09154 p->inalarm = 1; 09155 } 09156 } 09157 } 09158 break; 09159 case PRI_EVENT_RESTART: 09160 if (e->restart.channel > -1) { 09161 chanpos = pri_find_principle(pri, e->restart.channel); 09162 if (chanpos < 0) 09163 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 09164 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 09165 else { 09166 if (option_verbose > 2) 09167 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n", 09168 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 09169 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09170 if (pri->pvts[chanpos]->call) { 09171 pri_destroycall(pri->pri, pri->pvts[chanpos]->call); 09172 pri->pvts[chanpos]->call = NULL; 09173 } 09174 /* Force soft hangup if appropriate */ 09175 if (pri->pvts[chanpos]->realcall) 09176 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 09177 else if (pri->pvts[chanpos]->owner) 09178 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09179 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09180 } 09181 } else { 09182 if (option_verbose > 2) 09183 ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span); 09184 for (x = 0; x < pri->numchans; x++) 09185 if (pri->pvts[x]) { 09186 ast_mutex_lock(&pri->pvts[x]->lock); 09187 if (pri->pvts[x]->call) { 09188 pri_destroycall(pri->pri, pri->pvts[x]->call); 09189 pri->pvts[x]->call = NULL; 09190 } 09191 if (pri->pvts[chanpos]->realcall) 09192 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 09193 else if (pri->pvts[x]->owner) 09194 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09195 ast_mutex_unlock(&pri->pvts[x]->lock); 09196 } 09197 } 09198 break; 09199 case PRI_EVENT_KEYPAD_DIGIT: 09200 chanpos = pri_find_principle(pri, e->digit.channel); 09201 if (chanpos < 0) { 09202 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 09203 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span); 09204 } else { 09205 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call); 09206 if (chanpos > -1) { 09207 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09208 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */ 09209 if (pri->overlapdial && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) { 09210 /* how to do that */ 09211 int digitlen = strlen(e->digit.digits); 09212 char digit; 09213 int i; 09214 for (i = 0; i < digitlen; i++) { 09215 digit = e->digit.digits[i]; 09216 { 09217 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 09218 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 09219 } 09220 } 09221 } 09222 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09223 } 09224 } 09225 break; 09226 09227 case PRI_EVENT_INFO_RECEIVED: 09228 chanpos = pri_find_principle(pri, e->ring.channel); 09229 if (chanpos < 0) { 09230 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 09231 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 09232 } else { 09233 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call); 09234 if (chanpos > -1) { 09235 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09236 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */ 09237 if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) { 09238 /* how to do that */ 09239 int digitlen = strlen(e->ring.callednum); 09240 char digit; 09241 int i; 09242 for (i = 0; i < digitlen; i++) { 09243 digit = e->ring.callednum[i]; 09244 { 09245 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 09246 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 09247 } 09248 } 09249 } 09250 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09251 } 09252 } 09253 break; 09254 case PRI_EVENT_RING: 09255 crv = NULL; 09256 if (e->ring.channel == -1) 09257 chanpos = pri_find_empty_chan(pri, 1); 09258 else 09259 chanpos = pri_find_principle(pri, e->ring.channel); 09260 /* if no channel specified find one empty */ 09261 if (chanpos < 0) { 09262 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 09263 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 09264 } else { 09265 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09266 if (pri->pvts[chanpos]->owner) { 09267 if (pri->pvts[chanpos]->call == e->ring.call) { 09268 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 09269 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 09270 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09271 break; 09272 } else { 09273 /* This is where we handle initial glare */ 09274 ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n", 09275 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 09276 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09277 chanpos = -1; 09278 } 09279 } 09280 if (chanpos > -1) 09281 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09282 } 09283 if ((chanpos < 0) && (e->ring.flexible)) 09284 chanpos = pri_find_empty_chan(pri, 1); 09285 if (chanpos > -1) { 09286 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09287 if (pri->switchtype == PRI_SWITCH_GR303_TMC) { 09288 /* Should be safe to lock CRV AFAIK while bearer is still locked */ 09289 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL)); 09290 if (crv) 09291 ast_mutex_lock(&crv->lock); 09292 if (!crv || crv->owner) { 09293 pri->pvts[chanpos]->call = NULL; 09294 if (crv) { 09295 if (crv->owner) 09296 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09297 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); 09298 } else 09299 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); 09300 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE); 09301 if (crv) 09302 ast_mutex_unlock(&crv->lock); 09303 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09304 break; 09305 } 09306 } 09307 pri->pvts[chanpos]->call = e->ring.call; 09308 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan); 09309 if (pri->pvts[chanpos]->use_callerid) { 09310 ast_shrink_phone_number(plancallingnum); 09311 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num)); 09312 #ifdef PRI_ANI 09313 if (!ast_strlen_zero(e->ring.callingani)) { 09314 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani); 09315 ast_shrink_phone_number(plancallingani); 09316 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani)); 09317 } else { 09318 pri->pvts[chanpos]->cid_ani[0] = '\0'; 09319 } 09320 #endif 09321 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name)); 09322 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */ 09323 } else { 09324 pri->pvts[chanpos]->cid_num[0] = '\0'; 09325 pri->pvts[chanpos]->cid_ani[0] = '\0'; 09326 pri->pvts[chanpos]->cid_name[0] = '\0'; 09327 pri->pvts[chanpos]->cid_ton = 0; 09328 } 09329 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri, 09330 e->ring.redirectingnum, e->ring.callingplanrdnis); 09331 /* If immediate=yes go to s|1 */ 09332 if (pri->pvts[chanpos]->immediate) { 09333 if (option_verbose > 2) 09334 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n"); 09335 pri->pvts[chanpos]->exten[0] = 's'; 09336 pri->pvts[chanpos]->exten[1] = '\0'; 09337 } 09338 /* Get called number */ 09339 else if (!ast_strlen_zero(e->ring.callednum)) { 09340 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten)); 09341 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 09342 } else if (pri->overlapdial) 09343 pri->pvts[chanpos]->exten[0] = '\0'; 09344 else { 09345 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */ 09346 pri->pvts[chanpos]->exten[0] = 's'; 09347 pri->pvts[chanpos]->exten[1] = '\0'; 09348 } 09349 /* Set DNID on all incoming calls -- even immediate */ 09350 if (!ast_strlen_zero(e->ring.callednum)) 09351 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 09352 /* No number yet, but received "sending complete"? */ 09353 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) { 09354 if (option_verbose > 2) 09355 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n"); 09356 pri->pvts[chanpos]->exten[0] = 's'; 09357 pri->pvts[chanpos]->exten[1] = '\0'; 09358 } 09359 /* Make sure extension exists (or in overlap dial mode, can exist) */ 09360 if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) || 09361 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 09362 /* Setup law */ 09363 int law; 09364 if (pri->switchtype != PRI_SWITCH_GR303_TMC) { 09365 /* Set to audio mode at this point */ 09366 law = 1; 09367 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1) 09368 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno)); 09369 } 09370 if (e->ring.layer1 == PRI_LAYER_1_ALAW) 09371 law = DAHDI_LAW_ALAW; 09372 else 09373 law = DAHDI_LAW_MULAW; 09374 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law); 09375 if (res < 0) 09376 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel); 09377 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law); 09378 if (res < 0) 09379 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel); 09380 if (e->ring.complete || !pri->overlapdial) { 09381 /* Just announce proceeding */ 09382 pri->pvts[chanpos]->proceeding = 1; 09383 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0); 09384 } else { 09385 if (pri->switchtype != PRI_SWITCH_GR303_TMC) 09386 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 09387 else 09388 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 09389 } 09390 /* Get the use_callingpres state */ 09391 pri->pvts[chanpos]->callingpres = e->ring.callingpres; 09392 09393 /* Start PBX */ 09394 if (!e->ring.complete && pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 09395 /* Release the PRI lock while we create the channel */ 09396 ast_mutex_unlock(&pri->lock); 09397 if (crv) { 09398 /* Set bearer and such */ 09399 pri_assign_bearer(crv, pri, pri->pvts[chanpos]); 09400 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 09401 pri->pvts[chanpos]->owner = &inuse; 09402 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel); 09403 } else { 09404 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 09405 } 09406 09407 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09408 09409 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 09410 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 09411 } 09412 if (e->ring.ani2 >= 0) { 09413 snprintf(ani2str, 5, "%.2d", e->ring.ani2); 09414 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 09415 } 09416 09417 #ifdef SUPPORT_USERUSER 09418 if (!ast_strlen_zero(e->ring.useruserinfo)) { 09419 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 09420 } 09421 #endif 09422 09423 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan); 09424 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 09425 if (e->ring.redirectingreason >= 0) 09426 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 09427 09428 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09429 ast_mutex_lock(&pri->lock); 09430 09431 pthread_attr_init(&attr); 09432 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 09433 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) { 09434 if (option_verbose > 2) 09435 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n", 09436 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"), 09437 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 09438 } else { 09439 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 09440 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 09441 if (c) 09442 ast_hangup(c); 09443 else { 09444 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 09445 pri->pvts[chanpos]->call = NULL; 09446 } 09447 } 09448 pthread_attr_destroy(&attr); 09449 } else { 09450 ast_mutex_unlock(&pri->lock); 09451 /* Release PRI lock while we create the channel */ 09452 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype); 09453 if (c) { 09454 char calledtonstr[10]; 09455 09456 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09457 09458 if (e->ring.ani2 >= 0) { 09459 snprintf(ani2str, 5, "%d", e->ring.ani2); 09460 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 09461 } 09462 09463 #ifdef SUPPORT_USERUSER 09464 if (!ast_strlen_zero(e->ring.useruserinfo)) { 09465 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 09466 } 09467 #endif 09468 09469 if (e->ring.redirectingreason >= 0) 09470 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 09471 09472 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan); 09473 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 09474 09475 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09476 ast_mutex_lock(&pri->lock); 09477 09478 if (option_verbose > 2) 09479 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n", 09480 plancallingnum, pri->pvts[chanpos]->exten, 09481 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 09482 dahdi_enable_ec(pri->pvts[chanpos]); 09483 } else { 09484 09485 ast_mutex_lock(&pri->lock); 09486 09487 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 09488 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 09489 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 09490 pri->pvts[chanpos]->call = NULL; 09491 } 09492 } 09493 } else { 09494 if (option_verbose > 2) 09495 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n", 09496 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 09497 pri->pvts[chanpos]->prioffset, pri->span); 09498 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED); 09499 pri->pvts[chanpos]->call = NULL; 09500 pri->pvts[chanpos]->exten[0] = '\0'; 09501 } 09502 if (crv) 09503 ast_mutex_unlock(&crv->lock); 09504 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09505 } else { 09506 if (e->ring.flexible) 09507 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION); 09508 else 09509 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL); 09510 } 09511 break; 09512 case PRI_EVENT_RINGING: 09513 chanpos = pri_find_principle(pri, e->ringing.channel); 09514 if (chanpos < 0) { 09515 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 09516 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 09517 } else { 09518 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call); 09519 if (chanpos < 0) { 09520 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 09521 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 09522 } else { 09523 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09524 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 09525 dahdi_enable_ec(pri->pvts[chanpos]); 09526 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1; 09527 pri->pvts[chanpos]->alerting = 1; 09528 } else 09529 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n"); 09530 #ifdef PRI_PROGRESS_MASK 09531 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) { 09532 #else 09533 if (e->ringing.progress == 8) { 09534 #endif 09535 /* Now we can do call progress detection */ 09536 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 09537 /* RINGING detection isn't required because we got ALERTING signal */ 09538 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING); 09539 pri->pvts[chanpos]->dsp_features = 0; 09540 } 09541 } 09542 09543 #ifdef SUPPORT_USERUSER 09544 if (!ast_strlen_zero(e->ringing.useruserinfo)) { 09545 struct ast_channel *owner = pri->pvts[chanpos]->owner; 09546 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09547 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo); 09548 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09549 } 09550 #endif 09551 09552 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09553 } 09554 } 09555 break; 09556 case PRI_EVENT_PROGRESS: 09557 /* Get chan value if e->e is not PRI_EVNT_RINGING */ 09558 chanpos = pri_find_principle(pri, e->proceeding.channel); 09559 if (chanpos > -1) { 09560 #ifdef PRI_PROGRESS_MASK 09561 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) { 09562 #else 09563 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) { 09564 #endif 09565 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, }; 09566 09567 if (e->proceeding.cause > -1) { 09568 if (option_verbose > 2) 09569 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause); 09570 09571 /* Work around broken, out of spec USER_BUSY cause in a progress message */ 09572 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) { 09573 if (pri->pvts[chanpos]->owner) { 09574 if (option_verbose > 2) 09575 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n"); 09576 09577 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause; 09578 f.subclass = AST_CONTROL_BUSY; 09579 } 09580 } 09581 } 09582 09583 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09584 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n", 09585 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 09586 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 09587 #ifdef PRI_PROGRESS_MASK 09588 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 09589 #else 09590 if (e->proceeding.progress == 8) { 09591 #endif 09592 /* Now we can do call progress detection */ 09593 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 09594 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 09595 pri->pvts[chanpos]->dsp_features = 0; 09596 } 09597 /* Bring voice path up */ 09598 f.subclass = AST_CONTROL_PROGRESS; 09599 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 09600 } 09601 pri->pvts[chanpos]->progress = 1; 09602 pri->pvts[chanpos]->dialing = 0; 09603 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09604 } 09605 } 09606 break; 09607 case PRI_EVENT_PROCEEDING: 09608 chanpos = pri_find_principle(pri, e->proceeding.channel); 09609 if (chanpos > -1) { 09610 if (!pri->pvts[chanpos]->proceeding) { 09611 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, }; 09612 09613 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09614 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n", 09615 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 09616 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 09617 #ifdef PRI_PROGRESS_MASK 09618 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 09619 #else 09620 if (e->proceeding.progress == 8) { 09621 #endif 09622 /* Now we can do call progress detection */ 09623 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 09624 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 09625 pri->pvts[chanpos]->dsp_features = 0; 09626 } 09627 /* Bring voice path up */ 09628 f.subclass = AST_CONTROL_PROGRESS; 09629 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 09630 } 09631 pri->pvts[chanpos]->proceeding = 1; 09632 pri->pvts[chanpos]->dialing = 0; 09633 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09634 } 09635 } 09636 break; 09637 case PRI_EVENT_FACNAME: 09638 chanpos = pri_find_principle(pri, e->facname.channel); 09639 if (chanpos < 0) { 09640 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 09641 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 09642 } else { 09643 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call); 09644 if (chanpos < 0) { 09645 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 09646 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 09647 } else { 09648 /* Re-use *69 field for PRI */ 09649 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09650 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num)); 09651 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name)); 09652 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1; 09653 dahdi_enable_ec(pri->pvts[chanpos]); 09654 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09655 } 09656 } 09657 break; 09658 case PRI_EVENT_ANSWER: 09659 chanpos = pri_find_principle(pri, e->answer.channel); 09660 if (chanpos < 0) { 09661 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 09662 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 09663 } else { 09664 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call); 09665 if (chanpos < 0) { 09666 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 09667 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 09668 } else { 09669 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09670 /* Now we can do call progress detection */ 09671 09672 /* We changed this so it turns on the DSP no matter what... progress or no progress. 09673 * By this time, we need DTMF detection and other features that were previously disabled 09674 * -- Matt F */ 09675 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 09676 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 09677 pri->pvts[chanpos]->dsp_features = 0; 09678 } 09679 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) { 09680 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n"); 09681 x = DAHDI_START; 09682 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 09683 if (res < 0) { 09684 if (errno != EINPROGRESS) { 09685 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 09686 } 09687 } 09688 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 09689 pri->pvts[chanpos]->dialing = 1; 09690 /* Send any "w" waited stuff */ 09691 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop); 09692 if (res < 0) { 09693 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno)); 09694 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 09695 } else 09696 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr); 09697 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 09698 } else if (pri->pvts[chanpos]->confirmanswer) { 09699 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel); 09700 } else { 09701 pri->pvts[chanpos]->dialing = 0; 09702 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1; 09703 /* Enable echo cancellation if it's not on already */ 09704 dahdi_enable_ec(pri->pvts[chanpos]); 09705 } 09706 09707 #ifdef SUPPORT_USERUSER 09708 if (!ast_strlen_zero(e->answer.useruserinfo)) { 09709 struct ast_channel *owner = pri->pvts[chanpos]->owner; 09710 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09711 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo); 09712 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09713 } 09714 #endif 09715 09716 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09717 } 09718 } 09719 break; 09720 case PRI_EVENT_HANGUP: 09721 chanpos = pri_find_principle(pri, e->hangup.channel); 09722 if (chanpos < 0) { 09723 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 09724 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 09725 } else { 09726 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 09727 if (chanpos > -1) { 09728 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09729 if (!pri->pvts[chanpos]->alreadyhungup) { 09730 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */ 09731 pri->pvts[chanpos]->alreadyhungup = 1; 09732 if (pri->pvts[chanpos]->realcall) 09733 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 09734 else if (pri->pvts[chanpos]->owner) { 09735 /* Queue a BUSY instead of a hangup if our cause is appropriate */ 09736 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 09737 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP) 09738 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09739 else { 09740 switch (e->hangup.cause) { 09741 case PRI_CAUSE_USER_BUSY: 09742 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 09743 break; 09744 case PRI_CAUSE_CALL_REJECTED: 09745 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 09746 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 09747 case PRI_CAUSE_SWITCH_CONGESTION: 09748 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 09749 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 09750 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 09751 break; 09752 default: 09753 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09754 } 09755 } 09756 } 09757 if (option_verbose > 2) 09758 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n", 09759 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause); 09760 } else { 09761 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 09762 pri->pvts[chanpos]->call = NULL; 09763 } 09764 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 09765 if (option_verbose > 2) 09766 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 09767 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 09768 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 09769 pri->pvts[chanpos]->resetting = 1; 09770 } 09771 if (e->hangup.aoc_units > -1) 09772 if (option_verbose > 2) 09773 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 09774 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 09775 09776 #ifdef SUPPORT_USERUSER 09777 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) { 09778 struct ast_channel *owner = pri->pvts[chanpos]->owner; 09779 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09780 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 09781 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09782 } 09783 #endif 09784 09785 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09786 } else { 09787 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 09788 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 09789 } 09790 } 09791 break; 09792 #ifndef PRI_EVENT_HANGUP_REQ 09793 #error please update libpri 09794 #endif 09795 case PRI_EVENT_HANGUP_REQ: 09796 chanpos = pri_find_principle(pri, e->hangup.channel); 09797 if (chanpos < 0) { 09798 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 09799 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 09800 } else { 09801 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 09802 if (chanpos > -1) { 09803 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09804 if (pri->pvts[chanpos]->realcall) 09805 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 09806 else if (pri->pvts[chanpos]->owner) { 09807 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 09808 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP) 09809 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09810 else { 09811 switch (e->hangup.cause) { 09812 case PRI_CAUSE_USER_BUSY: 09813 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 09814 break; 09815 case PRI_CAUSE_CALL_REJECTED: 09816 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 09817 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 09818 case PRI_CAUSE_SWITCH_CONGESTION: 09819 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 09820 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 09821 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 09822 break; 09823 default: 09824 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09825 } 09826 } 09827 if (option_verbose > 2) 09828 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); 09829 if (e->hangup.aoc_units > -1) 09830 if (option_verbose > 2) 09831 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 09832 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 09833 } else { 09834 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 09835 pri->pvts[chanpos]->call = NULL; 09836 } 09837 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 09838 if (option_verbose > 2) 09839 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n", 09840 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 09841 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 09842 pri->pvts[chanpos]->resetting = 1; 09843 } 09844 09845 #ifdef SUPPORT_USERUSER 09846 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 09847 struct ast_channel *owner = pri->pvts[chanpos]->owner; 09848 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09849 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 09850 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09851 } 09852 #endif 09853 09854 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09855 } else { 09856 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); 09857 } 09858 } 09859 break; 09860 case PRI_EVENT_HANGUP_ACK: 09861 chanpos = pri_find_principle(pri, e->hangup.channel); 09862 if (chanpos < 0) { 09863 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 09864 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 09865 } else { 09866 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 09867 if (chanpos > -1) { 09868 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09869 pri->pvts[chanpos]->call = NULL; 09870 pri->pvts[chanpos]->resetting = 0; 09871 if (pri->pvts[chanpos]->owner) { 09872 if (option_verbose > 2) 09873 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); 09874 } 09875 09876 #ifdef SUPPORT_USERUSER 09877 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 09878 struct ast_channel *owner = pri->pvts[chanpos]->owner; 09879 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09880 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 09881 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09882 } 09883 #endif 09884 09885 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09886 } 09887 } 09888 break; 09889 case PRI_EVENT_CONFIG_ERR: 09890 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err); 09891 break; 09892 case PRI_EVENT_RESTART_ACK: 09893 chanpos = pri_find_principle(pri, e->restartack.channel); 09894 if (chanpos < 0) { 09895 /* Sometime switches (e.g. I421 / British Telecom) don't give us the 09896 channel number, so we have to figure it out... This must be why 09897 everybody resets exactly a channel at a time. */ 09898 for (x = 0; x < pri->numchans; x++) { 09899 if (pri->pvts[x] && pri->pvts[x]->resetting) { 09900 chanpos = x; 09901 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09902 ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 09903 pri->pvts[chanpos]->prioffset, pri->span); 09904 if (pri->pvts[chanpos]->realcall) 09905 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 09906 else if (pri->pvts[chanpos]->owner) { 09907 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 09908 pri->pvts[chanpos]->prioffset, pri->span); 09909 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09910 } 09911 pri->pvts[chanpos]->resetting = 0; 09912 if (option_verbose > 2) 09913 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 09914 pri->pvts[chanpos]->prioffset, pri->span); 09915 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09916 if (pri->resetting) 09917 pri_check_restart(pri); 09918 break; 09919 } 09920 } 09921 if (chanpos < 0) { 09922 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 09923 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 09924 } 09925 } else { 09926 if (pri->pvts[chanpos]) { 09927 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09928 if (pri->pvts[chanpos]->realcall) 09929 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 09930 else if (pri->pvts[chanpos]->owner) { 09931 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n", 09932 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 09933 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09934 } 09935 pri->pvts[chanpos]->resetting = 0; 09936 if (option_verbose > 2) 09937 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 09938 pri->pvts[chanpos]->prioffset, pri->span); 09939 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09940 if (pri->resetting) 09941 pri_check_restart(pri); 09942 } 09943 } 09944 break; 09945 case PRI_EVENT_SETUP_ACK: 09946 chanpos = pri_find_principle(pri, e->setup_ack.channel); 09947 if (chanpos < 0) { 09948 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 09949 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span); 09950 } else { 09951 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call); 09952 if (chanpos > -1) { 09953 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09954 pri->pvts[chanpos]->setup_ack = 1; 09955 /* Send any queued digits */ 09956 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) { 09957 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]); 09958 pri_information(pri->pri, pri->pvts[chanpos]->call, 09959 pri->pvts[chanpos]->dialdest[x]); 09960 } 09961 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09962 } else 09963 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel); 09964 } 09965 break; 09966 case PRI_EVENT_NOTIFY: 09967 chanpos = pri_find_principle(pri, e->notify.channel); 09968 if (chanpos < 0) { 09969 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n", 09970 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span); 09971 } else { 09972 struct ast_frame f = { AST_FRAME_CONTROL, }; 09973 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09974 switch (e->notify.info) { 09975 case PRI_NOTIFY_REMOTE_HOLD: 09976 f.subclass = AST_CONTROL_HOLD; 09977 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 09978 break; 09979 case PRI_NOTIFY_REMOTE_RETRIEVAL: 09980 f.subclass = AST_CONTROL_UNHOLD; 09981 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 09982 break; 09983 } 09984 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09985 } 09986 break; 09987 default: 09988 ast_log(LOG_DEBUG, "Event: %d\n", e->e); 09989 } 09990 } 09991 ast_mutex_unlock(&pri->lock); 09992 } 09993 /* Never reached */ 09994 return NULL; 09995 }
Definition at line 8524 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pri::crvs, dahdi_pvt::next, and dahdi_pvt::pri.
08525 { 08526 struct dahdi_pvt *p; 08527 p = pri->crvs; 08528 while (p) { 08529 if (p->channel == crv) 08530 return p; 08531 p = p->next; 08532 } 08533 return NULL; 08534 }
static int pri_find_dchan | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 2788 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, dahdi_pri::dchans, NUM_DCHANS, and dahdi_pri::pri.
02789 { 02790 int oldslot = -1; 02791 struct pri *old; 02792 int newslot = -1; 02793 int x; 02794 old = pri->pri; 02795 for (x = 0; x < NUM_DCHANS; x++) { 02796 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0)) 02797 newslot = x; 02798 if (pri->dchans[x] == old) { 02799 oldslot = x; 02800 } 02801 } 02802 if (newslot < 0) { 02803 newslot = 0; 02804 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n", 02805 pri->dchannels[newslot]); 02806 } 02807 if (old && (oldslot != newslot)) 02808 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n", 02809 pri->dchannels[oldslot], pri->dchannels[newslot]); 02810 pri->pri = pri->dchans[newslot]; 02811 return 0; 02812 }
static int pri_find_empty_chan | ( | struct dahdi_pri * | pri, | |
int | backwards | |||
) | [static] |
Definition at line 8256 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().
08257 { 08258 int x; 08259 if (backwards) 08260 x = pri->numchans; 08261 else 08262 x = 0; 08263 for (;;) { 08264 if (backwards && (x < 0)) 08265 break; 08266 if (!backwards && (x >= pri->numchans)) 08267 break; 08268 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) { 08269 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n", 08270 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset); 08271 return x; 08272 } 08273 if (backwards) 08274 x--; 08275 else 08276 x++; 08277 } 08278 return -1; 08279 }
static int pri_find_principle | ( | struct dahdi_pri * | pri, | |
int | channel | |||
) | [static] |
Definition at line 8537 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.
08538 { 08539 int x; 08540 int span = PRI_SPAN(channel); 08541 int spanfd; 08542 struct dahdi_params param; 08543 int principle = -1; 08544 int explicit = PRI_EXPLICIT(channel); 08545 channel = PRI_CHANNEL(channel); 08546 08547 if (!explicit) { 08548 spanfd = pri_active_dchan_fd(pri); 08549 memset(¶m, 0, sizeof(param)); 08550 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m)) 08551 return -1; 08552 span = pris[param.spanno - 1].prilogicalspan; 08553 } 08554 08555 for (x = 0; x < pri->numchans; x++) { 08556 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) { 08557 principle = x; 08558 break; 08559 } 08560 } 08561 08562 return principle; 08563 }
static int pri_fixup_principle | ( | struct dahdi_pri * | pri, | |
int | principle, | |||
q931_call * | c | |||
) | [static] |
Definition at line 8565 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.
08566 { 08567 int x; 08568 struct dahdi_pvt *crv; 08569 if (!c) { 08570 if (principle < 0) 08571 return -1; 08572 return principle; 08573 } 08574 if ((principle > -1) && 08575 (principle < pri->numchans) && 08576 (pri->pvts[principle]) && 08577 (pri->pvts[principle]->call == c)) 08578 return principle; 08579 /* First, check for other bearers */ 08580 for (x = 0; x < pri->numchans; x++) { 08581 if (!pri->pvts[x]) 08582 continue; 08583 if (pri->pvts[x]->call == c) { 08584 /* Found our call */ 08585 if (principle != x) { 08586 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x]; 08587 08588 if (option_verbose > 2) 08589 ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n", 08590 old->channel, new->channel); 08591 if (new->owner) { 08592 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n", 08593 old->channel, new->channel, new->channel); 08594 return -1; 08595 } 08596 /* Fix it all up now */ 08597 new->owner = old->owner; 08598 old->owner = NULL; 08599 if (new->owner) { 08600 ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1); 08601 new->owner->tech_pvt = new; 08602 new->owner->fds[0] = new->subs[SUB_REAL].dfd; 08603 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner; 08604 old->subs[SUB_REAL].owner = NULL; 08605 } else 08606 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); 08607 new->call = old->call; 08608 old->call = NULL; 08609 08610 /* Copy any DSP that may be present */ 08611 new->dsp = old->dsp; 08612 new->dsp_features = old->dsp_features; 08613 old->dsp = NULL; 08614 old->dsp_features = 0; 08615 } 08616 return principle; 08617 } 08618 } 08619 /* Now check for a CRV with no bearer */ 08620 crv = pri->crvs; 08621 while (crv) { 08622 if (crv->call == c) { 08623 /* This is our match... Perform some basic checks */ 08624 if (crv->bearer) 08625 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n"); 08626 else if (pri->pvts[principle]->owner) 08627 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n"); 08628 else { 08629 /* Looks good. Drop the pseudo channel now, clear up the assignment, and 08630 wakeup the potential sleeper */ 08631 dahdi_close_sub(crv, SUB_REAL); 08632 pri->pvts[principle]->call = crv->call; 08633 pri_assign_bearer(crv, pri, pri->pvts[principle]); 08634 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n", 08635 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset, 08636 pri->trunkgroup, crv->channel); 08637 wakeup_sub(crv, SUB_REAL, pri); 08638 } 08639 return principle; 08640 } 08641 crv = crv->next; 08642 } 08643 ast_log(LOG_WARNING, "Call specified, but not found?\n"); 08644 return -1; 08645 }
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 8805 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.
08806 { 08807 int x; 08808 int redo; 08809 ast_mutex_unlock(&pri->lock); 08810 ast_mutex_lock(&p->lock); 08811 do { 08812 redo = 0; 08813 for (x = 0; x < 3; x++) { 08814 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) { 08815 redo++; 08816 DEADLOCK_AVOIDANCE(&p->lock); 08817 } 08818 if (p->subs[x].owner) { 08819 ast_queue_hangup(p->subs[x].owner); 08820 ast_mutex_unlock(&p->subs[x].owner->lock); 08821 } 08822 } 08823 } while (redo); 08824 ast_mutex_unlock(&p->lock); 08825 ast_mutex_lock(&pri->lock); 08826 return 0; 08827 }
static int pri_is_up | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 2736 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, NUM_DCHANS, and dahdi_pvt::pri.
Referenced by pri_dchannel().
02737 { 02738 int x; 02739 for (x = 0; x < NUM_DCHANS; x++) { 02740 if (pri->dchanavail[x] == DCHAN_AVAILABLE) 02741 return 1; 02742 } 02743 return 0; 02744 }
static char* pri_order | ( | int | level | ) | [static] |
Definition at line 2759 of file chan_dahdi.c.
Referenced by handle_pri_show_span().
02760 { 02761 switch (level) { 02762 case 0: 02763 return "Primary"; 02764 case 1: 02765 return "Secondary"; 02766 case 2: 02767 return "Tertiary"; 02768 case 3: 02769 return "Quaternary"; 02770 default: 02771 return "<Unknown>"; 02772 } 02773 }
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 7496 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().
07497 { 07498 int x; 07499 int trunkgroup; 07500 /* Get appropriate trunk group if there is one */ 07501 trunkgroup = pris[*span].mastertrunkgroup; 07502 if (trunkgroup) { 07503 /* Select a specific trunk group */ 07504 for (x = 0; x < NUM_SPANS; x++) { 07505 if (pris[x].trunkgroup == trunkgroup) { 07506 *span = x; 07507 return 0; 07508 } 07509 } 07510 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup); 07511 *span = -1; 07512 } else { 07513 if (pris[*span].trunkgroup) { 07514 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup); 07515 *span = -1; 07516 } else if (pris[*span].mastertrunkgroup) { 07517 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup); 07518 *span = -1; 07519 } else { 07520 if (si->totalchans == 31) { 07521 /* E1 */ 07522 pris[*span].dchannels[0] = 16 + offset; 07523 } else if (si->totalchans == 24) { 07524 /* T1 or J1 */ 07525 pris[*span].dchannels[0] = 24 + offset; 07526 } else if (si->totalchans == 3) { 07527 /* BRI */ 07528 pris[*span].dchannels[0] = 3 + offset; 07529 } else { 07530 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); 07531 *span = -1; 07532 return 0; 07533 } 07534 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED; 07535 pris[*span].offset = offset; 07536 pris[*span].span = *span + 1; 07537 } 07538 } 07539 return 0; 07540 }
static int process_dahdi | ( | struct dahdi_chan_conf * | confp, | |
const char * | cat, | |||
struct ast_variable * | v, | |||
int | reload, | |||
int | skipchannels | |||
) | [static] |
Definition at line 11354 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().
11355 { 11356 struct dahdi_pvt *tmp; 11357 int y; 11358 int found_pseudo = 0; 11359 char dahdichan[MAX_CHANLIST_LEN] = {}; 11360 11361 for (; v; v = v->next) { 11362 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 11363 continue; 11364 11365 /* Create the interface list */ 11366 if (!strcasecmp(v->name, "channel") 11367 #ifdef HAVE_PRI 11368 || !strcasecmp(v->name, "crv") 11369 #endif 11370 ) { 11371 int iscrv; 11372 if (skipchannels) 11373 continue; 11374 iscrv = !strcasecmp(v->name, "crv"); 11375 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo)) 11376 return -1; 11377 } else if (!strcasecmp(v->name, "buffers")) { 11378 int res; 11379 char policy[21] = ""; 11380 11381 res = sscanf(v->value, "%d,%20s", &confp->chan.buf_no, policy); 11382 if (res != 2) { 11383 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n"); 11384 confp->chan.buf_no = numbufs; 11385 continue; 11386 } 11387 if (confp->chan.buf_no < 0) 11388 confp->chan.buf_no = numbufs; 11389 if (!strcasecmp(policy, "full")) { 11390 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL; 11391 } else if (!strcasecmp(policy, "immediate")) { 11392 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE; 11393 } else { 11394 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy); 11395 } 11396 } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) { 11397 ast_copy_string(dahdichan, v->value, sizeof(dahdichan)); 11398 if (v->name[0] == 'z' || v->name[0] == 'Z') { 11399 ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat); 11400 } 11401 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) { 11402 if (ast_true(v->value)) 11403 confp->chan.usedistinctiveringdetection = 1; 11404 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) { 11405 if (ast_true(v->value)) 11406 distinctiveringaftercid = 1; 11407 } else if (!strcasecmp(v->name, "dring1context")) { 11408 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData)); 11409 } else if (!strcasecmp(v->name, "dring2context")) { 11410 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData)); 11411 } else if (!strcasecmp(v->name, "dring3context")) { 11412 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData)); 11413 } else if (!strcasecmp(v->name, "dring1")) { 11414 sscanf(v->value, "%d,%d,%d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]); 11415 } else if (!strcasecmp(v->name, "dring2")) { 11416 sscanf(v->value, "%d,%d,%d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]); 11417 } else if (!strcasecmp(v->name, "dring3")) { 11418 sscanf(v->value, "%d,%d,%d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]); 11419 } else if (!strcasecmp(v->name, "usecallerid")) { 11420 confp->chan.use_callerid = ast_true(v->value); 11421 } else if (!strcasecmp(v->name, "cidsignalling")) { 11422 if (!strcasecmp(v->value, "bell")) 11423 confp->chan.cid_signalling = CID_SIG_BELL; 11424 else if (!strcasecmp(v->value, "v23")) 11425 confp->chan.cid_signalling = CID_SIG_V23; 11426 else if (!strcasecmp(v->value, "dtmf")) 11427 confp->chan.cid_signalling = CID_SIG_DTMF; 11428 else if (!strcasecmp(v->value, "smdi")) 11429 confp->chan.cid_signalling = CID_SIG_SMDI; 11430 else if (!strcasecmp(v->value, "v23_jp")) 11431 confp->chan.cid_signalling = CID_SIG_V23_JP; 11432 else if (ast_true(v->value)) 11433 confp->chan.cid_signalling = CID_SIG_BELL; 11434 } else if (!strcasecmp(v->name, "cidstart")) { 11435 if (!strcasecmp(v->value, "ring")) 11436 confp->chan.cid_start = CID_START_RING; 11437 else if (!strcasecmp(v->value, "polarity")) 11438 confp->chan.cid_start = CID_START_POLARITY; 11439 else if (ast_true(v->value)) 11440 confp->chan.cid_start = CID_START_RING; 11441 } else if (!strcasecmp(v->name, "threewaycalling")) { 11442 confp->chan.threewaycalling = ast_true(v->value); 11443 } else if (!strcasecmp(v->name, "cancallforward")) { 11444 confp->chan.cancallforward = ast_true(v->value); 11445 } else if (!strcasecmp(v->name, "relaxdtmf")) { 11446 if (ast_true(v->value)) 11447 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 11448 else 11449 confp->chan.dtmfrelax = 0; 11450 } else if (!strcasecmp(v->name, "mailbox")) { 11451 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox)); 11452 } else if (!strcasecmp(v->name, "hasvoicemail")) { 11453 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) { 11454 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox)); 11455 } 11456 } else if (!strcasecmp(v->name, "adsi")) { 11457 confp->chan.adsi = ast_true(v->value); 11458 } else if (!strcasecmp(v->name, "usesmdi")) { 11459 confp->chan.use_smdi = ast_true(v->value); 11460 } else if (!strcasecmp(v->name, "smdiport")) { 11461 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port)); 11462 } else if (!strcasecmp(v->name, "transfer")) { 11463 confp->chan.transfer = ast_true(v->value); 11464 } else if (!strcasecmp(v->name, "canpark")) { 11465 confp->chan.canpark = ast_true(v->value); 11466 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) { 11467 confp->chan.echocanbridged = ast_true(v->value); 11468 } else if (!strcasecmp(v->name, "busydetect")) { 11469 confp->chan.busydetect = ast_true(v->value); 11470 } else if (!strcasecmp(v->name, "busycount")) { 11471 confp->chan.busycount = atoi(v->value); 11472 } else if (!strcasecmp(v->name, "silencethreshold")) { 11473 confp->chan.silencethreshold = atoi(v->value); 11474 } else if (!strcasecmp(v->name, "busycompare")) { 11475 confp->chan.busycompare = ast_true(v->value); 11476 } else if (!strcasecmp(v->name, "busypattern")) { 11477 int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength); 11478 if (count == 1) 11479 confp->chan.busyquietlength = 0; 11480 else if (count < 1) 11481 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n"); 11482 } else if (!strcasecmp(v->name, "busyfuzziness")) { 11483 confp->chan.busyfuzziness = atoi(v->value); 11484 } else if (!strcasecmp(v->name, "callprogress")) { 11485 if (ast_true(v->value)) 11486 confp->chan.callprogress |= 1; 11487 else 11488 confp->chan.callprogress &= ~1; 11489 } else if (!strcasecmp(v->name, "faxdetect")) { 11490 if (!strcasecmp(v->value, "incoming")) { 11491 confp->chan.callprogress |= 4; 11492 confp->chan.callprogress &= ~2; 11493 } else if (!strcasecmp(v->value, "outgoing")) { 11494 confp->chan.callprogress &= ~4; 11495 confp->chan.callprogress |= 2; 11496 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) 11497 confp->chan.callprogress |= 6; 11498 else 11499 confp->chan.callprogress &= ~6; 11500 } else if (!strcasecmp(v->name, "echocancel")) { 11501 if (!ast_strlen_zero(v->value)) { 11502 y = atoi(v->value); 11503 } else 11504 y = 0; 11505 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024)) 11506 confp->chan.echocancel = y; 11507 else { 11508 confp->chan.echocancel = ast_true(v->value); 11509 if (confp->chan.echocancel) 11510 confp->chan.echocancel=128; 11511 } 11512 } else if (!strcasecmp(v->name, "echotraining")) { 11513 if (sscanf(v->value, "%d", &y) == 1) { 11514 if ((y < 10) || (y > 4000)) { 11515 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno); 11516 } else { 11517 confp->chan.echotraining = y; 11518 } 11519 } else if (ast_true(v->value)) { 11520 confp->chan.echotraining = 400; 11521 } else 11522 confp->chan.echotraining = 0; 11523 } else if (!strcasecmp(v->name, "hidecallerid")) { 11524 confp->chan.hidecallerid = ast_true(v->value); 11525 } else if (!strcasecmp(v->name, "hidecalleridname")) { 11526 confp->chan.hidecalleridname = ast_true(v->value); 11527 } else if (!strcasecmp(v->name, "pulsedial")) { 11528 confp->chan.pulse = ast_true(v->value); 11529 } else if (!strcasecmp(v->name, "callreturn")) { 11530 confp->chan.callreturn = ast_true(v->value); 11531 } else if (!strcasecmp(v->name, "callwaiting")) { 11532 confp->chan.callwaiting = ast_true(v->value); 11533 } else if (!strcasecmp(v->name, "callwaitingcallerid")) { 11534 confp->chan.callwaitingcallerid = ast_true(v->value); 11535 } else if (!strcasecmp(v->name, "context")) { 11536 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context)); 11537 } else if (!strcasecmp(v->name, "language")) { 11538 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language)); 11539 } else if (!strcasecmp(v->name, "progzone")) { 11540 ast_copy_string(progzone, v->value, sizeof(progzone)); 11541 } else if (!strcasecmp(v->name, "mohinterpret") 11542 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) { 11543 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret)); 11544 } else if (!strcasecmp(v->name, "mohsuggest")) { 11545 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest)); 11546 } else if (!strcasecmp(v->name, "stripmsd")) { 11547 confp->chan.stripmsd = atoi(v->value); 11548 } else if (!strcasecmp(v->name, "jitterbuffers")) { 11549 numbufs = atoi(v->value); 11550 } else if (!strcasecmp(v->name, "group")) { 11551 confp->chan.group = ast_get_group(v->value); 11552 } else if (!strcasecmp(v->name, "callgroup")) { 11553 confp->chan.callgroup = ast_get_group(v->value); 11554 } else if (!strcasecmp(v->name, "pickupgroup")) { 11555 confp->chan.pickupgroup = ast_get_group(v->value); 11556 } else if (!strcasecmp(v->name, "immediate")) { 11557 confp->chan.immediate = ast_true(v->value); 11558 } else if (!strcasecmp(v->name, "transfertobusy")) { 11559 confp->chan.transfertobusy = ast_true(v->value); 11560 } else if (!strcasecmp(v->name, "rxgain")) { 11561 if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) { 11562 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value); 11563 } 11564 } else if (!strcasecmp(v->name, "txgain")) { 11565 if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) { 11566 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value); 11567 } 11568 } else if (!strcasecmp(v->name, "tonezone")) { 11569 if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) { 11570 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value); 11571 } 11572 } else if (!strcasecmp(v->name, "callerid")) { 11573 if (!strcasecmp(v->value, "asreceived")) { 11574 confp->chan.cid_num[0] = '\0'; 11575 confp->chan.cid_name[0] = '\0'; 11576 } else { 11577 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num)); 11578 } 11579 } else if (!strcasecmp(v->name, "fullname")) { 11580 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name)); 11581 } else if (!strcasecmp(v->name, "cid_number")) { 11582 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num)); 11583 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) { 11584 confp->chan.dahditrcallerid = ast_true(v->value); 11585 if (strstr(v->name, "zap")) { 11586 ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat); 11587 } 11588 } else if (!strcasecmp(v->name, "restrictcid")) { 11589 confp->chan.restrictcid = ast_true(v->value); 11590 } else if (!strcasecmp(v->name, "usecallingpres")) { 11591 confp->chan.use_callingpres = ast_true(v->value); 11592 } else if (!strcasecmp(v->name, "accountcode")) { 11593 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode)); 11594 } else if (!strcasecmp(v->name, "amaflags")) { 11595 y = ast_cdr_amaflags2int(v->value); 11596 if (y < 0) 11597 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno); 11598 else 11599 confp->chan.amaflags = y; 11600 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) { 11601 confp->chan.polarityonanswerdelay = atoi(v->value); 11602 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) { 11603 confp->chan.answeronpolarityswitch = ast_true(v->value); 11604 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) { 11605 confp->chan.hanguponpolarityswitch = ast_true(v->value); 11606 } else if (!strcasecmp(v->name, "sendcalleridafter")) { 11607 confp->chan.sendcalleridafter = atoi(v->value); 11608 } else if (reload != 1) { 11609 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) { 11610 confp->chan.outsigmod = -1; 11611 if (!strcasecmp(v->value, "em")) { 11612 confp->chan.sig = SIG_EM; 11613 } else if (!strcasecmp(v->value, "em_e1")) { 11614 confp->chan.sig = SIG_EM_E1; 11615 } else if (!strcasecmp(v->value, "em_w")) { 11616 confp->chan.sig = SIG_EMWINK; 11617 confp->chan.radio = 0; 11618 } else if (!strcasecmp(v->value, "fxs_ls")) { 11619 confp->chan.sig = SIG_FXSLS; 11620 confp->chan.radio = 0; 11621 } else if (!strcasecmp(v->value, "fxs_gs")) { 11622 confp->chan.sig = SIG_FXSGS; 11623 confp->chan.radio = 0; 11624 } else if (!strcasecmp(v->value, "fxs_ks")) { 11625 confp->chan.sig = SIG_FXSKS; 11626 confp->chan.radio = 0; 11627 } else if (!strcasecmp(v->value, "fxo_ls")) { 11628 confp->chan.sig = SIG_FXOLS; 11629 confp->chan.radio = 0; 11630 } else if (!strcasecmp(v->value, "fxo_gs")) { 11631 confp->chan.sig = SIG_FXOGS; 11632 confp->chan.radio = 0; 11633 } else if (!strcasecmp(v->value, "fxo_ks")) { 11634 confp->chan.sig = SIG_FXOKS; 11635 confp->chan.radio = 0; 11636 } else if (!strcasecmp(v->value, "fxs_rx")) { 11637 confp->chan.sig = SIG_FXSKS; 11638 confp->chan.radio = 1; 11639 } else if (!strcasecmp(v->value, "fxo_rx")) { 11640 confp->chan.sig = SIG_FXOLS; 11641 confp->chan.radio = 1; 11642 } else if (!strcasecmp(v->value, "fxs_tx")) { 11643 confp->chan.sig = SIG_FXSLS; 11644 confp->chan.radio = 1; 11645 } else if (!strcasecmp(v->value, "fxo_tx")) { 11646 confp->chan.sig = SIG_FXOGS; 11647 confp->chan.radio = 1; 11648 } else if (!strcasecmp(v->value, "em_rx")) { 11649 confp->chan.sig = SIG_EM; 11650 confp->chan.radio = 1; 11651 } else if (!strcasecmp(v->value, "em_tx")) { 11652 confp->chan.sig = SIG_EM; 11653 confp->chan.radio = 1; 11654 } else if (!strcasecmp(v->value, "em_rxtx")) { 11655 confp->chan.sig = SIG_EM; 11656 confp->chan.radio = 2; 11657 } else if (!strcasecmp(v->value, "em_txrx")) { 11658 confp->chan.sig = SIG_EM; 11659 confp->chan.radio = 2; 11660 } else if (!strcasecmp(v->value, "sf")) { 11661 confp->chan.sig = SIG_SF; 11662 confp->chan.radio = 0; 11663 } else if (!strcasecmp(v->value, "sf_w")) { 11664 confp->chan.sig = SIG_SFWINK; 11665 confp->chan.radio = 0; 11666 } else if (!strcasecmp(v->value, "sf_featd")) { 11667 confp->chan.sig = SIG_FEATD; 11668 confp->chan.radio = 0; 11669 } else if (!strcasecmp(v->value, "sf_featdmf")) { 11670 confp->chan.sig = SIG_FEATDMF; 11671 confp->chan.radio = 0; 11672 } else if (!strcasecmp(v->value, "sf_featb")) { 11673 confp->chan.sig = SIG_SF_FEATB; 11674 confp->chan.radio = 0; 11675 } else if (!strcasecmp(v->value, "sf")) { 11676 confp->chan.sig = SIG_SF; 11677 confp->chan.radio = 0; 11678 } else if (!strcasecmp(v->value, "sf_rx")) { 11679 confp->chan.sig = SIG_SF; 11680 confp->chan.radio = 1; 11681 } else if (!strcasecmp(v->value, "sf_tx")) { 11682 confp->chan.sig = SIG_SF; 11683 confp->chan.radio = 1; 11684 } else if (!strcasecmp(v->value, "sf_rxtx")) { 11685 confp->chan.sig = SIG_SF; 11686 confp->chan.radio = 2; 11687 } else if (!strcasecmp(v->value, "sf_txrx")) { 11688 confp->chan.sig = SIG_SF; 11689 confp->chan.radio = 2; 11690 } else if (!strcasecmp(v->value, "featd")) { 11691 confp->chan.sig = SIG_FEATD; 11692 confp->chan.radio = 0; 11693 } else if (!strcasecmp(v->value, "featdmf")) { 11694 confp->chan.sig = SIG_FEATDMF; 11695 confp->chan.radio = 0; 11696 } else if (!strcasecmp(v->value, "featdmf_ta")) { 11697 confp->chan.sig = SIG_FEATDMF_TA; 11698 confp->chan.radio = 0; 11699 } else if (!strcasecmp(v->value, "e911")) { 11700 confp->chan.sig = SIG_E911; 11701 confp->chan.radio = 0; 11702 } else if (!strcasecmp(v->value, "fgccama")) { 11703 confp->chan.sig = SIG_FGC_CAMA; 11704 confp->chan.radio = 0; 11705 } else if (!strcasecmp(v->value, "fgccamamf")) { 11706 confp->chan.sig = SIG_FGC_CAMAMF; 11707 confp->chan.radio = 0; 11708 } else if (!strcasecmp(v->value, "featb")) { 11709 confp->chan.sig = SIG_FEATB; 11710 confp->chan.radio = 0; 11711 #ifdef HAVE_PRI 11712 } else if (!strcasecmp(v->value, "pri_net")) { 11713 confp->chan.radio = 0; 11714 confp->chan.sig = SIG_PRI; 11715 confp->pri.nodetype = PRI_NETWORK; 11716 } else if (!strcasecmp(v->value, "pri_cpe")) { 11717 confp->chan.sig = SIG_PRI; 11718 confp->chan.radio = 0; 11719 confp->pri.nodetype = PRI_CPE; 11720 } else if (!strcasecmp(v->value, "gr303fxoks_net")) { 11721 confp->chan.sig = SIG_GR303FXOKS; 11722 confp->chan.radio = 0; 11723 confp->pri.nodetype = PRI_NETWORK; 11724 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) { 11725 confp->chan.sig = SIG_GR303FXSKS; 11726 confp->chan.radio = 0; 11727 confp->pri.nodetype = PRI_CPE; 11728 #endif 11729 } else { 11730 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value); 11731 } 11732 } else if (!strcasecmp(v->name, "outsignalling")) { 11733 if (!strcasecmp(v->value, "em")) { 11734 confp->chan.outsigmod = SIG_EM; 11735 } else if (!strcasecmp(v->value, "em_e1")) { 11736 confp->chan.outsigmod = SIG_EM_E1; 11737 } else if (!strcasecmp(v->value, "em_w")) { 11738 confp->chan.outsigmod = SIG_EMWINK; 11739 } else if (!strcasecmp(v->value, "sf")) { 11740 confp->chan.outsigmod = SIG_SF; 11741 } else if (!strcasecmp(v->value, "sf_w")) { 11742 confp->chan.outsigmod = SIG_SFWINK; 11743 } else if (!strcasecmp(v->value, "sf_featd")) { 11744 confp->chan.outsigmod = SIG_FEATD; 11745 } else if (!strcasecmp(v->value, "sf_featdmf")) { 11746 confp->chan.outsigmod = SIG_FEATDMF; 11747 } else if (!strcasecmp(v->value, "sf_featb")) { 11748 confp->chan.outsigmod = SIG_SF_FEATB; 11749 } else if (!strcasecmp(v->value, "sf")) { 11750 confp->chan.outsigmod = SIG_SF; 11751 } else if (!strcasecmp(v->value, "featd")) { 11752 confp->chan.outsigmod = SIG_FEATD; 11753 } else if (!strcasecmp(v->value, "featdmf")) { 11754 confp->chan.outsigmod = SIG_FEATDMF; 11755 } else if (!strcasecmp(v->value, "featdmf_ta")) { 11756 confp->chan.outsigmod = SIG_FEATDMF_TA; 11757 } else if (!strcasecmp(v->value, "e911")) { 11758 confp->chan.outsigmod = SIG_E911; 11759 } else if (!strcasecmp(v->value, "fgccama")) { 11760 confp->chan.outsigmod = SIG_FGC_CAMA; 11761 } else if (!strcasecmp(v->value, "fgccamamf")) { 11762 confp->chan.outsigmod = SIG_FGC_CAMAMF; 11763 } else if (!strcasecmp(v->value, "featb")) { 11764 confp->chan.outsigmod = SIG_FEATB; 11765 } else { 11766 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value); 11767 } 11768 #ifdef HAVE_PRI 11769 } else if (!strcasecmp(v->name, "pridialplan")) { 11770 if (!strcasecmp(v->value, "national")) { 11771 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1; 11772 } else if (!strcasecmp(v->value, "unknown")) { 11773 confp->pri.dialplan = PRI_UNKNOWN + 1; 11774 } else if (!strcasecmp(v->value, "private")) { 11775 confp->pri.dialplan = PRI_PRIVATE + 1; 11776 } else if (!strcasecmp(v->value, "international")) { 11777 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1; 11778 } else if (!strcasecmp(v->value, "local")) { 11779 confp->pri.dialplan = PRI_LOCAL_ISDN + 1; 11780 } else if (!strcasecmp(v->value, "dynamic")) { 11781 confp->pri.dialplan = -1; 11782 } else { 11783 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 11784 } 11785 } else if (!strcasecmp(v->name, "prilocaldialplan")) { 11786 if (!strcasecmp(v->value, "national")) { 11787 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1; 11788 } else if (!strcasecmp(v->value, "unknown")) { 11789 confp->pri.localdialplan = PRI_UNKNOWN + 1; 11790 } else if (!strcasecmp(v->value, "private")) { 11791 confp->pri.localdialplan = PRI_PRIVATE + 1; 11792 } else if (!strcasecmp(v->value, "international")) { 11793 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1; 11794 } else if (!strcasecmp(v->value, "local")) { 11795 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1; 11796 } else if (!strcasecmp(v->value, "dynamic")) { 11797 confp->pri.localdialplan = -1; 11798 } else { 11799 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 11800 } 11801 } else if (!strcasecmp(v->name, "switchtype")) { 11802 if (!strcasecmp(v->value, "national")) 11803 confp->pri.switchtype = PRI_SWITCH_NI2; 11804 else if (!strcasecmp(v->value, "ni1")) 11805 confp->pri.switchtype = PRI_SWITCH_NI1; 11806 else if (!strcasecmp(v->value, "dms100")) 11807 confp->pri.switchtype = PRI_SWITCH_DMS100; 11808 else if (!strcasecmp(v->value, "4ess")) 11809 confp->pri.switchtype = PRI_SWITCH_ATT4ESS; 11810 else if (!strcasecmp(v->value, "5ess")) 11811 confp->pri.switchtype = PRI_SWITCH_LUCENT5E; 11812 else if (!strcasecmp(v->value, "euroisdn")) 11813 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1; 11814 else if (!strcasecmp(v->value, "qsig")) 11815 confp->pri.switchtype = PRI_SWITCH_QSIG; 11816 else { 11817 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value); 11818 return -1; 11819 } 11820 } else if (!strcasecmp(v->name, "nsf")) { 11821 if (!strcasecmp(v->value, "sdn")) 11822 confp->pri.nsf = PRI_NSF_SDN; 11823 else if (!strcasecmp(v->value, "megacom")) 11824 confp->pri.nsf = PRI_NSF_MEGACOM; 11825 else if (!strcasecmp(v->value, "tollfreemegacom")) 11826 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM; 11827 else if (!strcasecmp(v->value, "accunet")) 11828 confp->pri.nsf = PRI_NSF_ACCUNET; 11829 else if (!strcasecmp(v->value, "none")) 11830 confp->pri.nsf = PRI_NSF_NONE; 11831 else { 11832 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value); 11833 confp->pri.nsf = PRI_NSF_NONE; 11834 } 11835 } else if (!strcasecmp(v->name, "priindication")) { 11836 if (!strcasecmp(v->value, "outofband")) 11837 confp->chan.priindication_oob = 1; 11838 else if (!strcasecmp(v->value, "inband")) 11839 confp->chan.priindication_oob = 0; 11840 else 11841 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n", 11842 v->value, v->lineno); 11843 } else if (!strcasecmp(v->name, "priexclusive")) { 11844 confp->chan.priexclusive = ast_true(v->value); 11845 } else if (!strcasecmp(v->name, "internationalprefix")) { 11846 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix)); 11847 } else if (!strcasecmp(v->name, "nationalprefix")) { 11848 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix)); 11849 } else if (!strcasecmp(v->name, "localprefix")) { 11850 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix)); 11851 } else if (!strcasecmp(v->name, "privateprefix")) { 11852 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix)); 11853 } else if (!strcasecmp(v->name, "unknownprefix")) { 11854 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix)); 11855 } else if (!strcasecmp(v->name, "resetinterval")) { 11856 if (!strcasecmp(v->value, "never")) 11857 confp->pri.resetinterval = -1; 11858 else if (atoi(v->value) >= 60) 11859 confp->pri.resetinterval = atoi(v->value); 11860 else 11861 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n", 11862 v->value, v->lineno); 11863 } else if (!strcasecmp(v->name, "minunused")) { 11864 confp->pri.minunused = atoi(v->value); 11865 } else if (!strcasecmp(v->name, "minidle")) { 11866 confp->pri.minidle = atoi(v->value); 11867 } else if (!strcasecmp(v->name, "idleext")) { 11868 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext)); 11869 } else if (!strcasecmp(v->name, "idledial")) { 11870 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial)); 11871 } else if (!strcasecmp(v->name, "overlapdial")) { 11872 confp->pri.overlapdial = ast_true(v->value); 11873 #ifdef HAVE_PRI_INBANDDISCONNECT 11874 } else if (!strcasecmp(v->name, "inbanddisconnect")) { 11875 confp->pri.inbanddisconnect = ast_true(v->value); 11876 #endif 11877 } else if (!strcasecmp(v->name, "pritimer")) { 11878 #ifdef PRI_GETSET_TIMERS 11879 char tmp[20]; 11880 char *timerc; 11881 char *c; 11882 int timer; 11883 int timeridx; 11884 11885 ast_copy_string(tmp, v->value, sizeof(tmp)); 11886 c = tmp; 11887 timerc = strsep(&c, ","); 11888 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) { 11889 timeridx = pri_timer2idx(timerc); 11890 timer = atoi(c); 11891 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) { 11892 ast_log(LOG_WARNING, 11893 "'%s' is not a valid ISDN timer at line %d.\n", timerc, 11894 v->lineno); 11895 } else if (!timer) { 11896 ast_log(LOG_WARNING, 11897 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n", 11898 c, timerc, v->lineno); 11899 } else { 11900 pritimers[timeridx] = timer; 11901 } 11902 } else { 11903 ast_log(LOG_WARNING, 11904 "'%s' is not a valid ISDN timer configuration string at line %d.\n", 11905 v->value, v->lineno); 11906 } 11907 #endif /* PRI_GETSET_TIMERS */ 11908 } else if (!strcasecmp(v->name, "facilityenable")) { 11909 confp->pri.facilityenable = ast_true(v->value); 11910 #endif /* HAVE_PRI */ 11911 } else if (!strcasecmp(v->name, "cadence")) { 11912 /* setup to scan our argument */ 11913 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 11914 int i; 11915 struct dahdi_ring_cadence new_cadence; 11916 int cid_location = -1; 11917 int firstcadencepos = 0; 11918 char original_args[80]; 11919 int cadence_is_ok = 1; 11920 11921 ast_copy_string(original_args, v->value, sizeof(original_args)); 11922 /* 16 cadences allowed (8 pairs) */ 11923 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]); 11924 11925 /* Cadence must be even (on/off) */ 11926 if (element_count % 2 == 1) { 11927 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args); 11928 cadence_is_ok = 0; 11929 } 11930 11931 /* Ring cadences cannot be negative */ 11932 for (i = 0; i < element_count; i++) { 11933 if (c[i] == 0) { 11934 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args); 11935 cadence_is_ok = 0; 11936 break; 11937 } else if (c[i] < 0) { 11938 if (i % 2 == 1) { 11939 /* Silence duration, negative possibly okay */ 11940 if (cid_location == -1) { 11941 cid_location = i; 11942 c[i] *= -1; 11943 } else { 11944 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args); 11945 cadence_is_ok = 0; 11946 break; 11947 } 11948 } else { 11949 if (firstcadencepos == 0) { 11950 firstcadencepos = i; /* only recorded to avoid duplicate specification */ 11951 /* duration will be passed negative to the DAHDI driver */ 11952 } else { 11953 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args); 11954 cadence_is_ok = 0; 11955 break; 11956 } 11957 } 11958 } 11959 } 11960 11961 /* Substitute our scanned cadence */ 11962 for (i = 0; i < 16; i++) { 11963 new_cadence.ringcadence[i] = c[i]; 11964 } 11965 11966 if (cadence_is_ok) { 11967 /* ---we scanned it without getting annoyed; now some sanity checks--- */ 11968 if (element_count < 2) { 11969 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args); 11970 } else { 11971 if (cid_location == -1) { 11972 /* user didn't say; default to first pause */ 11973 cid_location = 1; 11974 } else { 11975 /* convert element_index to cidrings value */ 11976 cid_location = (cid_location + 1) / 2; 11977 } 11978 /* ---we like their cadence; try to install it--- */ 11979 if (!user_has_defined_cadences++) 11980 /* this is the first user-defined cadence; clear the default user cadences */ 11981 num_cadence = 0; 11982 if ((num_cadence+1) >= NUM_CADENCE_MAX) 11983 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args); 11984 else { 11985 cadences[num_cadence] = new_cadence; 11986 cidrings[num_cadence++] = cid_location; 11987 if (option_verbose > 2) 11988 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args); 11989 } 11990 } 11991 } 11992 } else if (!strcasecmp(v->name, "ringtimeout")) { 11993 ringt_base = (atoi(v->value) * 8) / READ_SIZE; 11994 } else if (!strcasecmp(v->name, "prewink")) { 11995 confp->timing.prewinktime = atoi(v->value); 11996 } else if (!strcasecmp(v->name, "preflash")) { 11997 confp->timing.preflashtime = atoi(v->value); 11998 } else if (!strcasecmp(v->name, "wink")) { 11999 confp->timing.winktime = atoi(v->value); 12000 } else if (!strcasecmp(v->name, "flash")) { 12001 confp->timing.flashtime = atoi(v->value); 12002 } else if (!strcasecmp(v->name, "start")) { 12003 confp->timing.starttime = atoi(v->value); 12004 } else if (!strcasecmp(v->name, "rxwink")) { 12005 confp->timing.rxwinktime = atoi(v->value); 12006 } else if (!strcasecmp(v->name, "rxflash")) { 12007 confp->timing.rxflashtime = atoi(v->value); 12008 } else if (!strcasecmp(v->name, "debounce")) { 12009 confp->timing.debouncetime = atoi(v->value); 12010 } else if (!strcasecmp(v->name, "toneduration")) { 12011 int toneduration; 12012 int ctlfd; 12013 int res; 12014 struct dahdi_dialparams dps; 12015 12016 ctlfd = open(DAHDI_FILE_CTL, O_RDWR); 12017 12018 if (ctlfd == -1) { 12019 ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n"); 12020 return -1; 12021 } 12022 12023 toneduration = atoi(v->value); 12024 if (toneduration > -1) { 12025 memset(&dps, 0, sizeof(dps)); 12026 12027 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration; 12028 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps); 12029 if (res < 0) { 12030 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno)); 12031 return -1; 12032 } 12033 } 12034 close(ctlfd); 12035 } else if (!strcasecmp(v->name, "defaultcic")) { 12036 ast_copy_string(defaultcic, v->value, sizeof(defaultcic)); 12037 } else if (!strcasecmp(v->name, "defaultozz")) { 12038 ast_copy_string(defaultozz, v->value, sizeof(defaultozz)); 12039 } 12040 } else if (!skipchannels) 12041 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload)\n", v->name); 12042 } 12043 if (dahdichan[0]) { 12044 /* The user has set 'dahdichan' */ 12045 /*< \todo pass proper line number instead of 0 */ 12046 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) { 12047 return -1; 12048 } 12049 } 12050 /*< \todo why check for the pseudo in the per-channel section. 12051 * Any actual use for manual setup of the pseudo channel? */ 12052 if (!found_pseudo && reload != 1) { 12053 /* use the default configuration for a channel, so 12054 that any settings from real configured channels 12055 don't "leak" into the pseudo channel config 12056 */ 12057 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 12058 12059 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload); 12060 12061 if (tmp) { 12062 if (option_verbose > 2) 12063 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n"); 12064 } else { 12065 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n"); 12066 } 12067 } 12068 return 0; 12069 }
static char* redirectingreason2str | ( | int | redirectingreason | ) | [static] |
Definition at line 8829 of file chan_dahdi.c.
Referenced by __oh323_new().
08830 { 08831 switch (redirectingreason) { 08832 case 0: 08833 return "UNKNOWN"; 08834 case 1: 08835 return "BUSY"; 08836 case 2: 08837 return "NO_REPLY"; 08838 case 0xF: 08839 return "UNCONDITIONAL"; 08840 default: 08841 return "NOREDIRECT"; 08842 } 08843 }
static int reload | ( | void | ) | [static] |
Definition at line 12376 of file chan_dahdi.c.
References ast_log(), and setup_dahdi().
12377 { 12378 int res = 0; 12379 12380 res = setup_dahdi(1); 12381 if (res) { 12382 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n"); 12383 return -1; 12384 } 12385 return 0; 12386 }
static int reset_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1699 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().
01700 { 01701 p->confno = -1; 01702 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf)); 01703 if (p->subs[SUB_REAL].dfd > -1) { 01704 struct dahdi_confinfo zi; 01705 01706 memset(&zi, 0, sizeof(zi)); 01707 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi)) 01708 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno)); 01709 } 01710 return 0; 01711 }
static int restart_monitor | ( | void | ) | [static] |
Definition at line 7464 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().
07465 { 07466 pthread_attr_t attr; 07467 pthread_attr_init(&attr); 07468 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 07469 /* If we're supposed to be stopped -- stay stopped */ 07470 if (monitor_thread == AST_PTHREADT_STOP) 07471 return 0; 07472 ast_mutex_lock(&monlock); 07473 if (monitor_thread == pthread_self()) { 07474 ast_mutex_unlock(&monlock); 07475 ast_log(LOG_WARNING, "Cannot kill myself\n"); 07476 return -1; 07477 } 07478 if (monitor_thread != AST_PTHREADT_NULL) { 07479 /* Wake up the thread */ 07480 pthread_kill(monitor_thread, SIGURG); 07481 } else { 07482 /* Start a new monitor */ 07483 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) { 07484 ast_mutex_unlock(&monlock); 07485 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 07486 pthread_attr_destroy(&attr); 07487 return -1; 07488 } 07489 } 07490 ast_mutex_unlock(&monlock); 07491 pthread_attr_destroy(&attr); 07492 return 0; 07493 }
static int restore_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2032 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().
02033 { 02034 int res; 02035 if (p->saveconf.confmode) { 02036 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf); 02037 p->saveconf.confmode = 0; 02038 if (res) { 02039 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno)); 02040 return -1; 02041 } 02042 } 02043 if (option_debug) 02044 ast_log(LOG_DEBUG, "Restored conferencing\n"); 02045 return 0; 02046 }
static int restore_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1959 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().
01960 { 01961 int res; 01962 01963 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 01964 if (res) { 01965 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno)); 01966 return -1; 01967 } 01968 01969 return 0; 01970 }
static int save_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2005 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().
02006 { 02007 struct dahdi_confinfo c; 02008 int res; 02009 if (p->saveconf.confmode) { 02010 ast_log(LOG_WARNING, "Can't save conference -- already in use\n"); 02011 return -1; 02012 } 02013 p->saveconf.chan = 0; 02014 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf); 02015 if (res) { 02016 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno)); 02017 p->saveconf.confmode = 0; 02018 return -1; 02019 } 02020 memset(&c, 0, sizeof(c)); 02021 c.confmode = DAHDI_CONF_NORMAL; 02022 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c); 02023 if (res) { 02024 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno)); 02025 return -1; 02026 } 02027 if (option_debug) 02028 ast_log(LOG_DEBUG, "Disabled conferencing\n"); 02029 return 0; 02030 }
static int send_callerid | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2072 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().
02073 { 02074 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */ 02075 int res; 02076 /* Take out of linear mode if necessary */ 02077 if (p->subs[SUB_REAL].linear) { 02078 p->subs[SUB_REAL].linear = 0; 02079 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 02080 } 02081 while (p->cidpos < p->cidlen) { 02082 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos); 02083 if (res < 0) { 02084 if (errno == EAGAIN) 02085 return 0; 02086 else { 02087 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 02088 return -1; 02089 } 02090 } 02091 if (!res) 02092 return 0; 02093 p->cidpos += res; 02094 } 02095 free(p->cidspill); 02096 p->cidspill = NULL; 02097 if (p->callwaitcas) { 02098 /* Wait for CID/CW to expire */ 02099 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES; 02100 } else 02101 restore_conference(p); 02102 return 0; 02103 }
static int send_cwcidspill | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2050 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().
02051 { 02052 p->callwaitcas = 0; 02053 p->cidcwexpire = 0; 02054 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) 02055 return -1; 02056 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p)); 02057 /* Make sure we account for the end */ 02058 p->cidlen += READ_SIZE * 4; 02059 p->cidpos = 0; 02060 send_callerid(p); 02061 if (option_verbose > 2) 02062 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num); 02063 return 0; 02064 }
static int send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 2685 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().
02686 { 02687 /* Data will be our digit string */ 02688 struct dahdi_pvt *p; 02689 char *digits = (char *) data; 02690 02691 if (ast_strlen_zero(digits)) { 02692 ast_log(LOG_DEBUG, "No digit string sent to application!\n"); 02693 return -1; 02694 } 02695 02696 p = (struct dahdi_pvt *)chan->tech_pvt; 02697 02698 if (!p) { 02699 ast_log(LOG_DEBUG, "Unable to find technology private\n"); 02700 return -1; 02701 } 02702 02703 ast_mutex_lock(&p->lock); 02704 02705 if (!p->pri || !p->call) { 02706 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n"); 02707 ast_mutex_unlock(&p->lock); 02708 return -1; 02709 } 02710 02711 if (!pri_grab(p, p->pri)) { 02712 pri_keypad_facility(p->pri->pri, p->call, digits); 02713 pri_rel(p->pri); 02714 } else { 02715 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n"); 02716 ast_mutex_unlock(&p->lock); 02717 return -1; 02718 } 02719 02720 ast_mutex_unlock(&p->lock); 02721 02722 return 0; 02723 }
static int set_actual_gain | ( | int | fd, | |
int | chan, | |||
float | rxgain, | |||
float | txgain, | |||
int | law | |||
) | [static] |
Definition at line 1940 of file chan_dahdi.c.
References set_actual_rxgain(), and set_actual_txgain().
Referenced by bump_gains(), dahdi_call(), and restore_gains().
01941 { 01942 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law); 01943 }
static int set_actual_rxgain | ( | int | fd, | |
int | chan, | |||
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 1922 of file chan_dahdi.c.
References ast_log(), errno, fill_rxgain(), and LOG_DEBUG.
Referenced by dahdi_setoption(), and set_actual_gain().
01923 { 01924 struct dahdi_gains g; 01925 int res; 01926 01927 memset(&g, 0, sizeof(g)); 01928 g.chan = chan; 01929 res = ioctl(fd, DAHDI_GETGAINS, &g); 01930 if (res) { 01931 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno)); 01932 return res; 01933 } 01934 01935 fill_rxgain(&g, gain, law); 01936 01937 return ioctl(fd, DAHDI_SETGAINS, &g); 01938 }
static int set_actual_txgain | ( | int | fd, | |
int | chan, | |||
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 1903 of file chan_dahdi.c.
References ast_log(), errno, fill_txgain(), LOG_DEBUG, and option_debug.
Referenced by dahdi_setoption(), and set_actual_gain().
01904 { 01905 struct dahdi_gains g; 01906 int res; 01907 01908 memset(&g, 0, sizeof(g)); 01909 g.chan = chan; 01910 res = ioctl(fd, DAHDI_GETGAINS, &g); 01911 if (res) { 01912 if (option_debug) 01913 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno)); 01914 return res; 01915 } 01916 01917 fill_txgain(&g, gain, law); 01918 01919 return ioctl(fd, DAHDI_SETGAINS, &g); 01920 }
static int setup_dahdi | ( | int | reload | ) | [static] |
Definition at line 12071 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().
12072 { 12073 struct ast_config *cfg; 12074 struct ast_variable *v; 12075 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 12076 int res; 12077 12078 #ifdef HAVE_PRI 12079 char *c; 12080 int spanno; 12081 int i, x; 12082 int logicalspan; 12083 int trunkgroup; 12084 int dchannels[NUM_DCHANS]; 12085 #endif 12086 12087 #ifdef HAVE_ZAPTEL 12088 int load_from_zapata_conf = 1; 12089 #else 12090 int load_from_zapata_conf = (*dahdi_chan_mode == CHAN_ZAP_MODE); 12091 #endif 12092 12093 if (load_from_zapata_conf) { 12094 if (!(cfg = ast_config_load("zapata.conf"))) { 12095 ast_log(LOG_ERROR, "Unable to load zapata.conf\n"); 12096 return 0; 12097 } 12098 } else { 12099 if (!(cfg = ast_config_load("chan_dahdi.conf"))) { 12100 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n"); 12101 return 0; 12102 } 12103 } 12104 12105 /* It's a little silly to lock it, but we mind as well just to be sure */ 12106 ast_mutex_lock(&iflock); 12107 #ifdef HAVE_PRI 12108 if (reload != 1) { 12109 /* Process trunkgroups first */ 12110 v = ast_variable_browse(cfg, "trunkgroups"); 12111 while (v) { 12112 if (!strcasecmp(v->name, "trunkgroup")) { 12113 trunkgroup = atoi(v->value); 12114 if (trunkgroup > 0) { 12115 if ((c = strchr(v->value, ','))) { 12116 i = 0; 12117 memset(dchannels, 0, sizeof(dchannels)); 12118 while (c && (i < NUM_DCHANS)) { 12119 dchannels[i] = atoi(c + 1); 12120 if (dchannels[i] < 0) { 12121 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); 12122 } else 12123 i++; 12124 c = strchr(c + 1, ','); 12125 } 12126 if (i) { 12127 if (pri_create_trunkgroup(trunkgroup, dchannels)) { 12128 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); 12129 } else if (option_verbose > 1) 12130 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"); 12131 } else 12132 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 12133 } else 12134 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 12135 } else 12136 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno); 12137 } else if (!strcasecmp(v->name, "spanmap")) { 12138 spanno = atoi(v->value); 12139 if (spanno > 0) { 12140 if ((c = strchr(v->value, ','))) { 12141 trunkgroup = atoi(c + 1); 12142 if (trunkgroup > 0) { 12143 if ((c = strchr(c + 1, ','))) 12144 logicalspan = atoi(c + 1); 12145 else 12146 logicalspan = 0; 12147 if (logicalspan >= 0) { 12148 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { 12149 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 12150 } else if (option_verbose > 1) 12151 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 12152 } else 12153 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); 12154 } else 12155 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno); 12156 } else 12157 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno); 12158 } else 12159 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno); 12160 } else { 12161 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); 12162 } 12163 v = v->next; 12164 } 12165 } 12166 #endif 12167 12168 /* Copy the default jb config over global_jbconf */ 12169 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 12170 12171 v = ast_variable_browse(cfg, "channels"); 12172 res = process_dahdi(&conf, "", v, reload, 0); 12173 ast_mutex_unlock(&iflock); 12174 ast_config_destroy(cfg); 12175 if (res) 12176 return res; 12177 cfg = ast_config_load("users.conf"); 12178 if (cfg) { 12179 char *cat; 12180 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1); 12181 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) { 12182 if (!strcasecmp(cat, "general")) 12183 continue; 12184 if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) { 12185 struct dahdi_chan_conf sect_conf; 12186 memcpy(§_conf, &conf, sizeof(sect_conf)); 12187 12188 process_dahdi(§_conf, cat, ast_variable_browse(cfg, cat), reload, 0); 12189 } 12190 } 12191 ast_config_destroy(cfg); 12192 } 12193 #ifdef HAVE_PRI 12194 if (reload != 1) { 12195 for (x = 0; x < NUM_SPANS; x++) { 12196 if (pris[x].pvts[0]) { 12197 if (start_pri(pris + x)) { 12198 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1); 12199 return -1; 12200 } else if (option_verbose > 1) 12201 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1); 12202 } 12203 } 12204 } 12205 #endif 12206 /* And start the monitor for the first time */ 12207 restart_monitor(); 12208 return 0; 12209 }
static void * ss_thread | ( | void * | data | ) | [static] |
Definition at line 5884 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().
05885 { 05886 struct ast_channel *chan = data; 05887 struct dahdi_pvt *p = chan->tech_pvt; 05888 char exten[AST_MAX_EXTENSION] = ""; 05889 char exten2[AST_MAX_EXTENSION] = ""; 05890 unsigned char buf[256]; 05891 char dtmfcid[300]; 05892 char dtmfbuf[300]; 05893 struct callerid_state *cs = NULL; 05894 char *name = NULL, *number = NULL; 05895 int distMatches; 05896 int curRingData[3]; 05897 int receivedRingT; 05898 int counter1; 05899 int counter; 05900 int samples = 0; 05901 struct ast_smdi_md_message *smdi_msg = NULL; 05902 int flags; 05903 int i; 05904 int timeout; 05905 int getforward = 0; 05906 char *s1, *s2; 05907 int len = 0; 05908 int res; 05909 int index; 05910 05911 ast_mutex_lock(&ss_thread_lock); 05912 ss_thread_count++; 05913 ast_mutex_unlock(&ss_thread_lock); 05914 /* in the bizarre case where the channel has become a zombie before we 05915 even get started here, abort safely 05916 */ 05917 if (!p) { 05918 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name); 05919 ast_hangup(chan); 05920 goto quit; 05921 } 05922 if (option_verbose > 2) 05923 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name); 05924 index = dahdi_get_index(chan, p, 1); 05925 if (index < 0) { 05926 ast_log(LOG_WARNING, "Huh?\n"); 05927 ast_hangup(chan); 05928 goto quit; 05929 } 05930 if (p->dsp) 05931 ast_dsp_digitreset(p->dsp); 05932 switch (p->sig) { 05933 #ifdef HAVE_PRI 05934 case SIG_PRI: 05935 /* Now loop looking for an extension */ 05936 ast_copy_string(exten, p->exten, sizeof(exten)); 05937 len = strlen(exten); 05938 res = 0; 05939 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 05940 if (len && !ast_ignore_pattern(chan->context, exten)) 05941 tone_zone_play_tone(p->subs[index].dfd, -1); 05942 else 05943 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 05944 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) 05945 timeout = matchdigittimeout; 05946 else 05947 timeout = gendigittimeout; 05948 res = ast_waitfordigit(chan, timeout); 05949 if (res < 0) { 05950 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 05951 ast_hangup(chan); 05952 goto quit; 05953 } else if (res) { 05954 exten[len++] = res; 05955 exten[len] = '\0'; 05956 } else 05957 break; 05958 } 05959 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */ 05960 if (ast_strlen_zero(exten)) { 05961 if (option_verbose > 2) 05962 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n"); 05963 exten[0] = 's'; 05964 exten[1] = '\0'; 05965 } 05966 tone_zone_play_tone(p->subs[index].dfd, -1); 05967 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) { 05968 /* Start the real PBX */ 05969 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 05970 if (p->dsp) ast_dsp_digitreset(p->dsp); 05971 dahdi_enable_ec(p); 05972 ast_setstate(chan, AST_STATE_RING); 05973 res = ast_pbx_run(chan); 05974 if (res) { 05975 ast_log(LOG_WARNING, "PBX exited non-zero!\n"); 05976 } 05977 } else { 05978 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context); 05979 chan->hangupcause = AST_CAUSE_UNALLOCATED; 05980 ast_hangup(chan); 05981 p->exten[0] = '\0'; 05982 /* Since we send release complete here, we won't get one */ 05983 p->call = NULL; 05984 } 05985 goto quit; 05986 break; 05987 #endif 05988 case SIG_FEATD: 05989 case SIG_FEATDMF: 05990 case SIG_FEATDMF_TA: 05991 case SIG_E911: 05992 case SIG_FGC_CAMAMF: 05993 case SIG_FEATB: 05994 case SIG_EMWINK: 05995 case SIG_SF_FEATD: 05996 case SIG_SF_FEATDMF: 05997 case SIG_SF_FEATB: 05998 case SIG_SFWINK: 05999 if (dahdi_wink(p, index)) 06000 goto quit; 06001 /* Fall through */ 06002 case SIG_EM: 06003 case SIG_EM_E1: 06004 case SIG_SF: 06005 case SIG_FGC_CAMA: 06006 res = tone_zone_play_tone(p->subs[index].dfd, -1); 06007 if (p->dsp) 06008 ast_dsp_digitreset(p->dsp); 06009 /* set digit mode appropriately */ 06010 if (p->dsp) { 06011 if (NEED_MFDETECT(p)) 06012 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 06013 else 06014 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 06015 } 06016 memset(dtmfbuf, 0, sizeof(dtmfbuf)); 06017 /* Wait for the first digit only if immediate=no */ 06018 if (!p->immediate) 06019 /* Wait for the first digit (up to 5 seconds). */ 06020 res = ast_waitfordigit(chan, 5000); 06021 else 06022 res = 0; 06023 if (res > 0) { 06024 /* save first char */ 06025 dtmfbuf[0] = res; 06026 switch (p->sig) { 06027 case SIG_FEATD: 06028 case SIG_SF_FEATD: 06029 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06030 if (res > 0) 06031 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06032 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06033 break; 06034 case SIG_FEATDMF_TA: 06035 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06036 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06037 if (dahdi_wink(p, index)) goto quit; 06038 dtmfbuf[0] = 0; 06039 /* Wait for the first digit (up to 5 seconds). */ 06040 res = ast_waitfordigit(chan, 5000); 06041 if (res <= 0) break; 06042 dtmfbuf[0] = res; 06043 /* fall through intentionally */ 06044 case SIG_FEATDMF: 06045 case SIG_E911: 06046 case SIG_FGC_CAMAMF: 06047 case SIG_SF_FEATDMF: 06048 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06049 /* if international caca, do it again to get real ANO */ 06050 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14)) 06051 { 06052 if (dahdi_wink(p, index)) goto quit; 06053 dtmfbuf[0] = 0; 06054 /* Wait for the first digit (up to 5 seconds). */ 06055 res = ast_waitfordigit(chan, 5000); 06056 if (res <= 0) break; 06057 dtmfbuf[0] = res; 06058 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06059 } 06060 if (res > 0) { 06061 /* if E911, take off hook */ 06062 if (p->sig == SIG_E911) 06063 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06064 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000); 06065 } 06066 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06067 break; 06068 case SIG_FEATB: 06069 case SIG_SF_FEATB: 06070 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06071 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06072 break; 06073 case SIG_EMWINK: 06074 /* if we received a '*', we are actually receiving Feature Group D 06075 dial syntax, so use that mode; otherwise, fall through to normal 06076 mode 06077 */ 06078 if (res == '*') { 06079 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06080 if (res > 0) 06081 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06082 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06083 break; 06084 } 06085 default: 06086 /* If we got the first digit, get the rest */ 06087 len = 1; 06088 dtmfbuf[len] = '\0'; 06089 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06090 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06091 timeout = matchdigittimeout; 06092 } else { 06093 timeout = gendigittimeout; 06094 } 06095 res = ast_waitfordigit(chan, timeout); 06096 if (res < 0) { 06097 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 06098 ast_hangup(chan); 06099 goto quit; 06100 } else if (res) { 06101 dtmfbuf[len++] = res; 06102 dtmfbuf[len] = '\0'; 06103 } else { 06104 break; 06105 } 06106 } 06107 break; 06108 } 06109 } 06110 if (res == -1) { 06111 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno)); 06112 ast_hangup(chan); 06113 goto quit; 06114 } else if (res < 0) { 06115 ast_log(LOG_DEBUG, "Got hung up before digits finished\n"); 06116 ast_hangup(chan); 06117 goto quit; 06118 } 06119 06120 if (p->sig == SIG_FGC_CAMA) { 06121 char anibuf[100]; 06122 06123 if (ast_safe_sleep(chan,1000) == -1) { 06124 ast_hangup(chan); 06125 goto quit; 06126 } 06127 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06128 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 06129 res = my_getsigstr(chan, anibuf, "#", 10000); 06130 if ((res > 0) && (strlen(anibuf) > 2)) { 06131 if (anibuf[strlen(anibuf) - 1] == '#') 06132 anibuf[strlen(anibuf) - 1] = 0; 06133 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2); 06134 } 06135 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 06136 } 06137 06138 ast_copy_string(exten, dtmfbuf, sizeof(exten)); 06139 if (ast_strlen_zero(exten)) 06140 ast_copy_string(exten, "s", sizeof(exten)); 06141 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) { 06142 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */ 06143 if (exten[0] == '*') { 06144 char *stringp=NULL; 06145 ast_copy_string(exten2, exten, sizeof(exten2)); 06146 /* Parse out extension and callerid */ 06147 stringp=exten2 +1; 06148 s1 = strsep(&stringp, "*"); 06149 s2 = strsep(&stringp, "*"); 06150 if (s2) { 06151 if (!ast_strlen_zero(p->cid_num)) 06152 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 06153 else 06154 ast_set_callerid(chan, s1, NULL, s1); 06155 ast_copy_string(exten, s2, sizeof(exten)); 06156 } else 06157 ast_copy_string(exten, s1, sizeof(exten)); 06158 } else if (p->sig == SIG_FEATD) 06159 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 06160 } 06161 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 06162 if (exten[0] == '*') { 06163 char *stringp=NULL; 06164 ast_copy_string(exten2, exten, sizeof(exten2)); 06165 /* Parse out extension and callerid */ 06166 stringp=exten2 +1; 06167 s1 = strsep(&stringp, "#"); 06168 s2 = strsep(&stringp, "#"); 06169 if (s2) { 06170 if (!ast_strlen_zero(p->cid_num)) 06171 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 06172 else 06173 if (*(s1 + 2)) 06174 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2); 06175 ast_copy_string(exten, s2 + 1, sizeof(exten)); 06176 } else 06177 ast_copy_string(exten, s1 + 2, sizeof(exten)); 06178 } else 06179 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 06180 } 06181 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) { 06182 if (exten[0] == '*') { 06183 char *stringp=NULL; 06184 ast_copy_string(exten2, exten, sizeof(exten2)); 06185 /* Parse out extension and callerid */ 06186 stringp=exten2 +1; 06187 s1 = strsep(&stringp, "#"); 06188 s2 = strsep(&stringp, "#"); 06189 if (s2 && (*(s2 + 1) == '0')) { 06190 if (*(s2 + 2)) 06191 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2); 06192 } 06193 if (s1) ast_copy_string(exten, s1, sizeof(exten)); 06194 else ast_copy_string(exten, "911", sizeof(exten)); 06195 } else 06196 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel); 06197 } 06198 if (p->sig == SIG_FEATB) { 06199 if (exten[0] == '*') { 06200 char *stringp=NULL; 06201 ast_copy_string(exten2, exten, sizeof(exten2)); 06202 /* Parse out extension and callerid */ 06203 stringp=exten2 +1; 06204 s1 = strsep(&stringp, "#"); 06205 ast_copy_string(exten, exten2 + 1, sizeof(exten)); 06206 } else 06207 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel); 06208 } 06209 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 06210 dahdi_wink(p, index); 06211 /* some switches require a minimum guard time between 06212 the last FGD wink and something that answers 06213 immediately. This ensures it */ 06214 if (ast_safe_sleep(chan,100)) goto quit; 06215 } 06216 dahdi_enable_ec(p); 06217 if (NEED_MFDETECT(p)) { 06218 if (p->dsp) { 06219 if (!p->hardwaredtmf) 06220 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 06221 else { 06222 ast_dsp_free(p->dsp); 06223 p->dsp = NULL; 06224 } 06225 } 06226 } 06227 06228 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) { 06229 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06230 if (p->dsp) ast_dsp_digitreset(p->dsp); 06231 res = ast_pbx_run(chan); 06232 if (res) { 06233 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 06234 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06235 } 06236 goto quit; 06237 } else { 06238 if (option_verbose > 2) 06239 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context); 06240 sleep(2); 06241 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO); 06242 if (res < 0) 06243 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel); 06244 else 06245 sleep(1); 06246 res = ast_streamfile(chan, "ss-noservice", chan->language); 06247 if (res >= 0) 06248 ast_waitstream(chan, ""); 06249 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06250 ast_hangup(chan); 06251 goto quit; 06252 } 06253 break; 06254 case SIG_FXOLS: 06255 case SIG_FXOGS: 06256 case SIG_FXOKS: 06257 /* Read the first digit */ 06258 timeout = firstdigittimeout; 06259 /* If starting a threeway call, never timeout on the first digit so someone 06260 can use flash-hook as a "hold" feature */ 06261 if (p->subs[SUB_THREEWAY].owner) 06262 timeout = 999999; 06263 while (len < AST_MAX_EXTENSION-1) { 06264 /* Read digit unless it's supposed to be immediate, in which case the 06265 only answer is 's' */ 06266 if (p->immediate) 06267 res = 's'; 06268 else 06269 res = ast_waitfordigit(chan, timeout); 06270 timeout = 0; 06271 if (res < 0) { 06272 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 06273 res = tone_zone_play_tone(p->subs[index].dfd, -1); 06274 ast_hangup(chan); 06275 goto quit; 06276 } else if (res) { 06277 exten[len++]=res; 06278 exten[len] = '\0'; 06279 } 06280 if (!ast_ignore_pattern(chan->context, exten)) 06281 tone_zone_play_tone(p->subs[index].dfd, -1); 06282 else 06283 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 06284 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) { 06285 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 06286 if (getforward) { 06287 /* Record this as the forwarding extension */ 06288 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 06289 if (option_verbose > 2) 06290 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel); 06291 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06292 if (res) 06293 break; 06294 usleep(500000); 06295 res = tone_zone_play_tone(p->subs[index].dfd, -1); 06296 sleep(1); 06297 memset(exten, 0, sizeof(exten)); 06298 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 06299 len = 0; 06300 getforward = 0; 06301 } else { 06302 res = tone_zone_play_tone(p->subs[index].dfd, -1); 06303 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06304 if (!ast_strlen_zero(p->cid_num)) { 06305 if (!p->hidecallerid) 06306 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 06307 else 06308 ast_set_callerid(chan, NULL, NULL, p->cid_num); 06309 } 06310 if (!ast_strlen_zero(p->cid_name)) { 06311 if (!p->hidecallerid) 06312 ast_set_callerid(chan, NULL, p->cid_name, NULL); 06313 } 06314 ast_setstate(chan, AST_STATE_RING); 06315 dahdi_enable_ec(p); 06316 res = ast_pbx_run(chan); 06317 if (res) { 06318 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 06319 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06320 } 06321 goto quit; 06322 } 06323 } else { 06324 /* It's a match, but they just typed a digit, and there is an ambiguous match, 06325 so just set the timeout to matchdigittimeout and wait some more */ 06326 timeout = matchdigittimeout; 06327 } 06328 } else if (res == 0) { 06329 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n"); 06330 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06331 dahdi_wait_event(p->subs[index].dfd); 06332 ast_hangup(chan); 06333 goto quit; 06334 } else if (p->callwaiting && !strcmp(exten, "*70")) { 06335 if (option_verbose > 2) 06336 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name); 06337 /* Disable call waiting if enabled */ 06338 p->callwaiting = 0; 06339 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06340 if (res) { 06341 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 06342 chan->name, strerror(errno)); 06343 } 06344 len = 0; 06345 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len); 06346 memset(exten, 0, sizeof(exten)); 06347 timeout = firstdigittimeout; 06348 06349 } else if (!strcmp(exten,ast_pickup_ext())) { 06350 /* Scan all channels and see if there are any 06351 * ringing channels that have call groups 06352 * that equal this channels pickup group 06353 */ 06354 if (index == SUB_REAL) { 06355 /* Switch us from Third call to Call Wait */ 06356 if (p->subs[SUB_THREEWAY].owner) { 06357 /* If you make a threeway call and the *8# a call, it should actually 06358 look like a callwait */ 06359 alloc_sub(p, SUB_CALLWAIT); 06360 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 06361 unalloc_sub(p, SUB_THREEWAY); 06362 } 06363 dahdi_enable_ec(p); 06364 if (ast_pickup_call(chan)) { 06365 ast_log(LOG_DEBUG, "No call pickup possible...\n"); 06366 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06367 dahdi_wait_event(p->subs[index].dfd); 06368 } 06369 ast_hangup(chan); 06370 goto quit; 06371 } else { 06372 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n"); 06373 ast_hangup(chan); 06374 goto quit; 06375 } 06376 06377 } else if (!p->hidecallerid && !strcmp(exten, "*67")) { 06378 if (option_verbose > 2) 06379 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name); 06380 /* Disable Caller*ID if enabled */ 06381 p->hidecallerid = 1; 06382 if (chan->cid.cid_num) 06383 free(chan->cid.cid_num); 06384 chan->cid.cid_num = NULL; 06385 if (chan->cid.cid_name) 06386 free(chan->cid.cid_name); 06387 chan->cid.cid_name = NULL; 06388 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06389 if (res) { 06390 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 06391 chan->name, strerror(errno)); 06392 } 06393 len = 0; 06394 memset(exten, 0, sizeof(exten)); 06395 timeout = firstdigittimeout; 06396 } else if (p->callreturn && !strcmp(exten, "*69")) { 06397 res = 0; 06398 if (!ast_strlen_zero(p->lastcid_num)) { 06399 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language); 06400 } 06401 if (!res) 06402 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06403 break; 06404 } else if (!strcmp(exten, "*78")) { 06405 /* Do not disturb */ 06406 if (option_verbose > 2) 06407 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel); 06408 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 06409 "Channel: %s/%d\r\n" 06410 "Status: enabled\r\n", dahdi_chan_name, p->channel); 06411 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06412 p->dnd = 1; 06413 getforward = 0; 06414 memset(exten, 0, sizeof(exten)); 06415 len = 0; 06416 } else if (!strcmp(exten, "*79")) { 06417 /* Do not disturb */ 06418 if (option_verbose > 2) 06419 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel); 06420 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 06421 "Channel: %s/%d\r\n" 06422 "Status: disabled\r\n", dahdi_chan_name, p->channel); 06423 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06424 p->dnd = 0; 06425 getforward = 0; 06426 memset(exten, 0, sizeof(exten)); 06427 len = 0; 06428 } else if (p->cancallforward && !strcmp(exten, "*72")) { 06429 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06430 getforward = 1; 06431 memset(exten, 0, sizeof(exten)); 06432 len = 0; 06433 } else if (p->cancallforward && !strcmp(exten, "*73")) { 06434 if (option_verbose > 2) 06435 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel); 06436 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06437 memset(p->call_forward, 0, sizeof(p->call_forward)); 06438 getforward = 0; 06439 memset(exten, 0, sizeof(exten)); 06440 len = 0; 06441 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 06442 p->subs[SUB_THREEWAY].owner && 06443 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 06444 /* This is a three way call, the main call being a real channel, 06445 and we're parking the first call. */ 06446 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL); 06447 if (option_verbose > 2) 06448 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name); 06449 break; 06450 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) { 06451 if (option_verbose > 2) 06452 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num); 06453 res = ast_db_put("blacklist", p->lastcid_num, "1"); 06454 if (!res) { 06455 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06456 memset(exten, 0, sizeof(exten)); 06457 len = 0; 06458 } 06459 } else if (p->hidecallerid && !strcmp(exten, "*82")) { 06460 if (option_verbose > 2) 06461 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name); 06462 /* Enable Caller*ID if enabled */ 06463 p->hidecallerid = 0; 06464 if (chan->cid.cid_num) 06465 free(chan->cid.cid_num); 06466 chan->cid.cid_num = NULL; 06467 if (chan->cid.cid_name) 06468 free(chan->cid.cid_name); 06469 chan->cid.cid_name = NULL; 06470 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 06471 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06472 if (res) { 06473 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 06474 chan->name, strerror(errno)); 06475 } 06476 len = 0; 06477 memset(exten, 0, sizeof(exten)); 06478 timeout = firstdigittimeout; 06479 } else if (!strcmp(exten, "*0")) { 06480 struct ast_channel *nbridge = 06481 p->subs[SUB_THREEWAY].owner; 06482 struct dahdi_pvt *pbridge = NULL; 06483 /* set up the private struct of the bridged one, if any */ 06484 if (nbridge && ast_bridged_channel(nbridge)) 06485 pbridge = ast_bridged_channel(nbridge)->tech_pvt; 06486 if (nbridge && pbridge && 06487 (nbridge->tech == chan_tech) && 06488 (ast_bridged_channel(nbridge)->tech == chan_tech) && 06489 ISTRUNK(pbridge)) { 06490 int func = DAHDI_FLASH; 06491 /* Clear out the dial buffer */ 06492 p->dop.dialstr[0] = '\0'; 06493 /* flash hookswitch */ 06494 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 06495 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 06496 nbridge->name, strerror(errno)); 06497 } 06498 swap_subs(p, SUB_REAL, SUB_THREEWAY); 06499 unalloc_sub(p, SUB_THREEWAY); 06500 p->owner = p->subs[SUB_REAL].owner; 06501 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 06502 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 06503 ast_hangup(chan); 06504 goto quit; 06505 } else { 06506 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06507 dahdi_wait_event(p->subs[index].dfd); 06508 tone_zone_play_tone(p->subs[index].dfd, -1); 06509 swap_subs(p, SUB_REAL, SUB_THREEWAY); 06510 unalloc_sub(p, SUB_THREEWAY); 06511 p->owner = p->subs[SUB_REAL].owner; 06512 ast_hangup(chan); 06513 goto quit; 06514 } 06515 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) && 06516 ((exten[0] != '*') || (strlen(exten) > 2))) { 06517 if (option_debug) 06518 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); 06519 break; 06520 } 06521 if (!timeout) 06522 timeout = gendigittimeout; 06523 if (len && !ast_ignore_pattern(chan->context, exten)) 06524 tone_zone_play_tone(p->subs[index].dfd, -1); 06525 } 06526 break; 06527 case SIG_FXSLS: 06528 case SIG_FXSGS: 06529 case SIG_FXSKS: 06530 #ifdef HAVE_PRI 06531 if (p->pri) { 06532 /* This is a GR-303 trunk actually. Wait for the first ring... */ 06533 struct ast_frame *f; 06534 int res; 06535 time_t start; 06536 06537 time(&start); 06538 ast_setstate(chan, AST_STATE_RING); 06539 while (time(NULL) < start + 3) { 06540 res = ast_waitfor(chan, 1000); 06541 if (res) { 06542 f = ast_read(chan); 06543 if (!f) { 06544 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n"); 06545 ast_hangup(chan); 06546 goto quit; 06547 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) { 06548 res = 1; 06549 } else 06550 res = 0; 06551 ast_frfree(f); 06552 if (res) { 06553 ast_log(LOG_DEBUG, "Got ring!\n"); 06554 res = 0; 06555 break; 06556 } 06557 } 06558 } 06559 } 06560 #endif 06561 /* check for SMDI messages */ 06562 if (p->use_smdi && p->smdi_iface) { 06563 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); 06564 06565 if (smdi_msg != NULL) { 06566 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten)); 06567 06568 if (smdi_msg->type == 'B') 06569 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b"); 06570 else if (smdi_msg->type == 'N') 06571 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u"); 06572 06573 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name); 06574 } else { 06575 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n"); 06576 } 06577 } 06578 06579 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) { 06580 number = smdi_msg->calling_st; 06581 06582 /* If we want caller id, we're in a prering state due to a polarity reversal 06583 * and we're set to use a polarity reversal to trigger the start of caller id, 06584 * grab the caller id and wait for ringing to start... */ 06585 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) { 06586 /* If set to use DTMF CID signalling, listen for DTMF */ 06587 if (p->cid_signalling == CID_SIG_DTMF) { 06588 int i = 0; 06589 cs = NULL; 06590 ast_log(LOG_DEBUG, "Receiving DTMF cid on " 06591 "channel %s\n", chan->name); 06592 dahdi_setlinear(p->subs[index].dfd, 0); 06593 res = 2000; 06594 for (;;) { 06595 struct ast_frame *f; 06596 res = ast_waitfor(chan, res); 06597 if (res <= 0) { 06598 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 06599 "Exiting simple switch\n"); 06600 ast_hangup(chan); 06601 goto quit; 06602 } 06603 f = ast_read(chan); 06604 if (!f) 06605 break; 06606 if (f->frametype == AST_FRAME_DTMF) { 06607 dtmfbuf[i++] = f->subclass; 06608 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass); 06609 res = 2000; 06610 } 06611 ast_frfree(f); 06612 if (chan->_state == AST_STATE_RING || 06613 chan->_state == AST_STATE_RINGING) 06614 break; /* Got ring */ 06615 } 06616 dtmfbuf[i] = '\0'; 06617 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06618 /* Got cid and ring. */ 06619 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf); 06620 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 06621 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 06622 dtmfcid, flags); 06623 /* If first byte is NULL, we have no cid */ 06624 if (!ast_strlen_zero(dtmfcid)) 06625 number = dtmfcid; 06626 else 06627 number = NULL; 06628 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 06629 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { 06630 cs = callerid_new(p->cid_signalling); 06631 if (cs) { 06632 samples = 0; 06633 #if 1 06634 bump_gains(p); 06635 #endif 06636 /* Take out of linear mode for Caller*ID processing */ 06637 dahdi_setlinear(p->subs[index].dfd, 0); 06638 06639 /* First we wait and listen for the Caller*ID */ 06640 for (;;) { 06641 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 06642 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 06643 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 06644 callerid_free(cs); 06645 ast_hangup(chan); 06646 goto quit; 06647 } 06648 if (i & DAHDI_IOMUX_SIGEVENT) { 06649 res = dahdi_get_event(p->subs[index].dfd); 06650 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 06651 06652 if (p->cid_signalling == CID_SIG_V23_JP) { 06653 #ifdef DAHDI_EVENT_RINGBEGIN 06654 if (res == DAHDI_EVENT_RINGBEGIN) { 06655 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06656 usleep(1); 06657 } 06658 #endif 06659 } else { 06660 res = 0; 06661 break; 06662 } 06663 } else if (i & DAHDI_IOMUX_READ) { 06664 res = read(p->subs[index].dfd, buf, sizeof(buf)); 06665 if (res < 0) { 06666 if (errno != ELAST) { 06667 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 06668 callerid_free(cs); 06669 ast_hangup(chan); 06670 goto quit; 06671 } 06672 break; 06673 } 06674 samples += res; 06675 06676 if (p->cid_signalling == CID_SIG_V23_JP) { 06677 res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); 06678 } else { 06679 res = callerid_feed(cs, buf, res, AST_LAW(p)); 06680 } 06681 06682 if (res < 0) { 06683 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name); 06684 break; 06685 } else if (res) 06686 break; 06687 else if (samples > (8000 * 10)) 06688 break; 06689 } 06690 } 06691 if (res == 1) { 06692 callerid_get(cs, &name, &number, &flags); 06693 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 06694 } 06695 06696 if (p->cid_signalling == CID_SIG_V23_JP) { 06697 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 06698 usleep(1); 06699 res = 4000; 06700 } else { 06701 06702 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 06703 res = 2000; 06704 } 06705 06706 for (;;) { 06707 struct ast_frame *f; 06708 res = ast_waitfor(chan, res); 06709 if (res <= 0) { 06710 ast_log(LOG_WARNING, "CID timed out waiting for ring. " 06711 "Exiting simple switch\n"); 06712 ast_hangup(chan); 06713 goto quit; 06714 } 06715 if (!(f = ast_read(chan))) { 06716 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); 06717 ast_hangup(chan); 06718 goto quit; 06719 } 06720 ast_frfree(f); 06721 if (chan->_state == AST_STATE_RING || 06722 chan->_state == AST_STATE_RINGING) 06723 break; /* Got ring */ 06724 } 06725 06726 /* We must have a ring by now, so, if configured, lets try to listen for 06727 * distinctive ringing */ 06728 if (p->usedistinctiveringdetection) { 06729 len = 0; 06730 distMatches = 0; 06731 /* Clear the current ring data array so we dont have old data in it. */ 06732 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++) 06733 curRingData[receivedRingT] = 0; 06734 receivedRingT = 0; 06735 counter = 0; 06736 counter1 = 0; 06737 /* Check to see if context is what it should be, if not set to be. */ 06738 if (strcmp(p->context,p->defcontext) != 0) { 06739 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 06740 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 06741 } 06742 06743 for (;;) { 06744 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 06745 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 06746 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 06747 callerid_free(cs); 06748 ast_hangup(chan); 06749 goto quit; 06750 } 06751 if (i & DAHDI_IOMUX_SIGEVENT) { 06752 res = dahdi_get_event(p->subs[index].dfd); 06753 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 06754 res = 0; 06755 /* Let us detect distinctive ring */ 06756 06757 curRingData[receivedRingT] = p->ringt; 06758 06759 if (p->ringt < p->ringt_base/2) 06760 break; 06761 /* Increment the ringT counter so we can match it against 06762 values in chan_dahdi.conf for distinctive ring */ 06763 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 06764 break; 06765 } else if (i & DAHDI_IOMUX_READ) { 06766 res = read(p->subs[index].dfd, buf, sizeof(buf)); 06767 if (res < 0) { 06768 if (errno != ELAST) { 06769 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 06770 callerid_free(cs); 06771 ast_hangup(chan); 06772 goto quit; 06773 } 06774 break; 06775 } 06776 if (p->ringt) 06777 p->ringt--; 06778 if (p->ringt == 1) { 06779 res = -1; 06780 break; 06781 } 06782 } 06783 } 06784 if (option_verbose > 2) 06785 /* this only shows up if you have n of the dring patterns filled in */ 06786 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 06787 06788 for (counter = 0; counter < 3; counter++) { 06789 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 06790 channel */ 06791 distMatches = 0; 06792 for (counter1 = 0; counter1 < 3; counter1++) { 06793 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >= 06794 (p->drings.ringnum[counter].ring[counter1]-10)) { 06795 distMatches++; 06796 } 06797 } 06798 if (distMatches == 3) { 06799 /* The ring matches, set the context to whatever is for distinctive ring.. */ 06800 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 06801 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 06802 if (option_verbose > 2) 06803 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context); 06804 break; 06805 } 06806 } 06807 } 06808 /* Restore linear mode (if appropriate) for Caller*ID processing */ 06809 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06810 #if 1 06811 restore_gains(p); 06812 #endif 06813 } else 06814 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 06815 } else { 06816 ast_log(LOG_WARNING, "Channel %s in prering " 06817 "state, but I have nothing to do. " 06818 "Terminating simple switch, should be " 06819 "restarted by the actual ring.\n", 06820 chan->name); 06821 ast_hangup(chan); 06822 goto quit; 06823 } 06824 } else if (p->use_callerid && p->cid_start == CID_START_RING) { 06825 /* FSK Bell202 callerID */ 06826 cs = callerid_new(p->cid_signalling); 06827 if (cs) { 06828 #if 1 06829 bump_gains(p); 06830 #endif 06831 samples = 0; 06832 len = 0; 06833 distMatches = 0; 06834 /* Clear the current ring data array so we dont have old data in it. */ 06835 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++) 06836 curRingData[receivedRingT] = 0; 06837 receivedRingT = 0; 06838 counter = 0; 06839 counter1 = 0; 06840 /* Check to see if context is what it should be, if not set to be. */ 06841 if (strcmp(p->context,p->defcontext) != 0) { 06842 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 06843 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 06844 } 06845 06846 /* Take out of linear mode for Caller*ID processing */ 06847 dahdi_setlinear(p->subs[index].dfd, 0); 06848 for (;;) { 06849 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 06850 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 06851 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 06852 callerid_free(cs); 06853 ast_hangup(chan); 06854 goto quit; 06855 } 06856 if (i & DAHDI_IOMUX_SIGEVENT) { 06857 res = dahdi_get_event(p->subs[index].dfd); 06858 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 06859 /* If we get a PR event, they hung up while processing calerid */ 06860 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { 06861 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); 06862 p->polarity = POLARITY_IDLE; 06863 callerid_free(cs); 06864 ast_hangup(chan); 06865 goto quit; 06866 } 06867 res = 0; 06868 /* Let us detect callerid when the telco uses distinctive ring */ 06869 06870 curRingData[receivedRingT] = p->ringt; 06871 06872 if (p->ringt < p->ringt_base/2) 06873 break; 06874 /* Increment the ringT counter so we can match it against 06875 values in chan_dahdi.conf for distinctive ring */ 06876 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 06877 break; 06878 } else if (i & DAHDI_IOMUX_READ) { 06879 res = read(p->subs[index].dfd, buf, sizeof(buf)); 06880 if (res < 0) { 06881 if (errno != ELAST) { 06882 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 06883 callerid_free(cs); 06884 ast_hangup(chan); 06885 goto quit; 06886 } 06887 break; 06888 } 06889 if (p->ringt) 06890 p->ringt--; 06891 if (p->ringt == 1) { 06892 res = -1; 06893 break; 06894 } 06895 samples += res; 06896 res = callerid_feed(cs, buf, res, AST_LAW(p)); 06897 if (res < 0) { 06898 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno)); 06899 break; 06900 } else if (res) 06901 break; 06902 else if (samples > (8000 * 10)) 06903 break; 06904 } 06905 } 06906 if (res == 1) { 06907 callerid_get(cs, &name, &number, &flags); 06908 if (option_debug) 06909 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 06910 } 06911 if (distinctiveringaftercid == 1) { 06912 /* Clear the current ring data array so we dont have old data in it. */ 06913 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) { 06914 curRingData[receivedRingT] = 0; 06915 } 06916 receivedRingT = 0; 06917 if (option_verbose > 2) 06918 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n"); 06919 for (;;) { 06920 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 06921 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 06922 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 06923 callerid_free(cs); 06924 ast_hangup(chan); 06925 goto quit; 06926 } 06927 if (i & DAHDI_IOMUX_SIGEVENT) { 06928 res = dahdi_get_event(p->subs[index].dfd); 06929 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 06930 res = 0; 06931 /* Let us detect callerid when the telco uses distinctive ring */ 06932 06933 curRingData[receivedRingT] = p->ringt; 06934 06935 if (p->ringt < p->ringt_base/2) 06936 break; 06937 /* Increment the ringT counter so we can match it against 06938 values in chan_dahdi.conf for distinctive ring */ 06939 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 06940 break; 06941 } else if (i & DAHDI_IOMUX_READ) { 06942 res = read(p->subs[index].dfd, buf, sizeof(buf)); 06943 if (res < 0) { 06944 if (errno != ELAST) { 06945 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 06946 callerid_free(cs); 06947 ast_hangup(chan); 06948 goto quit; 06949 } 06950 break; 06951 } 06952 if (p->ringt) 06953 p->ringt--; 06954 if (p->ringt == 1) { 06955 res = -1; 06956 break; 06957 } 06958 } 06959 } 06960 } 06961 if (p->usedistinctiveringdetection) { 06962 if (option_verbose > 2) 06963 /* this only shows up if you have n of the dring patterns filled in */ 06964 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 06965 06966 for (counter = 0; counter < 3; counter++) { 06967 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 06968 channel */ 06969 if (option_verbose > 2) 06970 /* this only shows up if you have n of the dring patterns filled in */ 06971 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n", 06972 p->drings.ringnum[counter].ring[0], 06973 p->drings.ringnum[counter].ring[1], 06974 p->drings.ringnum[counter].ring[2]); 06975 distMatches = 0; 06976 for (counter1 = 0; counter1 < 3; counter1++) { 06977 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >= 06978 (p->drings.ringnum[counter].ring[counter1]-10)) { 06979 distMatches++; 06980 } 06981 } 06982 if (distMatches == 3) { 06983 /* The ring matches, set the context to whatever is for distinctive ring.. */ 06984 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 06985 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 06986 if (option_verbose > 2) 06987 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context); 06988 break; 06989 } 06990 } 06991 } 06992 /* Restore linear mode (if appropriate) for Caller*ID processing */ 06993 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06994 #if 1 06995 restore_gains(p); 06996 #endif 06997 if (res < 0) { 06998 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); 06999 } 07000 } else 07001 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 07002 } 07003 else 07004 cs = NULL; 07005 07006 if (number) 07007 ast_shrink_phone_number(number); 07008 ast_set_callerid(chan, number, name, number); 07009 07010 if (smdi_msg) 07011 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy); 07012 07013 if (cs) 07014 callerid_free(cs); 07015 07016 ast_setstate(chan, AST_STATE_RING); 07017 chan->rings = 1; 07018 p->ringt = p->ringt_base; 07019 res = ast_pbx_run(chan); 07020 if (res) { 07021 ast_hangup(chan); 07022 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07023 } 07024 goto quit; 07025 default: 07026 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel); 07027 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07028 if (res < 0) 07029 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 07030 } 07031 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07032 if (res < 0) 07033 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 07034 ast_hangup(chan); 07035 quit: 07036 ast_mutex_lock(&ss_thread_lock); 07037 ss_thread_count--; 07038 ast_cond_signal(&ss_thread_complete); 07039 ast_mutex_unlock(&ss_thread_lock); 07040 return NULL; 07041 }
static int start_pri | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 9997 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().
09998 { 09999 int res, x; 10000 struct dahdi_params p; 10001 struct dahdi_bufferinfo bi; 10002 struct dahdi_spaninfo si; 10003 int i; 10004 10005 for (i = 0; i < NUM_DCHANS; i++) { 10006 if (!pri->dchannels[i]) 10007 break; 10008 pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600); 10009 x = pri->dchannels[i]; 10010 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) { 10011 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno)); 10012 return -1; 10013 } 10014 memset(&p, 0, sizeof(p)); 10015 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p); 10016 if (res) { 10017 dahdi_close_pri_fd(pri, i); 10018 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno)); 10019 return -1; 10020 } 10021 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) { 10022 dahdi_close_pri_fd(pri, i); 10023 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/dahdi/system.conf\n", x); 10024 return -1; 10025 } 10026 memset(&si, 0, sizeof(si)); 10027 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si); 10028 if (res) { 10029 dahdi_close_pri_fd(pri, i); 10030 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno)); 10031 } 10032 if (!si.alarms) 10033 pri->dchanavail[i] |= DCHAN_NOTINALARM; 10034 else 10035 pri->dchanavail[i] &= ~DCHAN_NOTINALARM; 10036 memset(&bi, 0, sizeof(bi)); 10037 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 10038 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 10039 bi.numbufs = 32; 10040 bi.bufsize = 1024; 10041 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) { 10042 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno)); 10043 dahdi_close_pri_fd(pri, i); 10044 return -1; 10045 } 10046 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype); 10047 /* Force overlap dial if we're doing GR-303! */ 10048 if (pri->switchtype == PRI_SWITCH_GR303_TMC) 10049 pri->overlapdial = 1; 10050 pri_set_overlapdial(pri->dchans[i],pri->overlapdial); 10051 #ifdef HAVE_PRI_INBANDDISCONNECT 10052 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect); 10053 #endif 10054 /* Enslave to master if appropriate */ 10055 if (i) 10056 pri_enslave(pri->dchans[0], pri->dchans[i]); 10057 if (!pri->dchans[i]) { 10058 dahdi_close_pri_fd(pri, i); 10059 ast_log(LOG_ERROR, "Unable to create PRI structure\n"); 10060 return -1; 10061 } 10062 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG); 10063 pri_set_nsf(pri->dchans[i], pri->nsf); 10064 #ifdef PRI_GETSET_TIMERS 10065 for (x = 0; x < PRI_MAX_TIMERS; x++) { 10066 if (pritimers[x] != 0) 10067 pri_set_timer(pri->dchans[i], x, pritimers[x]); 10068 } 10069 #endif 10070 } 10071 /* Assume primary is the one we use */ 10072 pri->pri = pri->dchans[0]; 10073 pri->resetpos = -1; 10074 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) { 10075 for (i = 0; i < NUM_DCHANS; i++) { 10076 if (!pri->dchannels[i]) 10077 break; 10078 dahdi_close_pri_fd(pri, i); 10079 } 10080 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno)); 10081 return -1; 10082 } 10083 return 0; 10084 }
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 11251 of file chan_dahdi.c.
References __unload_module(), ast_mutex_destroy(), lock, NUM_SPANS, and pris.
11252 { 11253 #ifdef HAVE_PRI 11254 int y; 11255 for (y = 0; y < NUM_SPANS; y++) 11256 ast_mutex_destroy(&pris[y].lock); 11257 #endif 11258 return __unload_module(); 11259 }
static int update_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1713 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().
01714 { 01715 int needconf = 0; 01716 int x; 01717 int useslavenative; 01718 struct dahdi_pvt *slave = NULL; 01719 01720 useslavenative = isslavenative(p, &slave); 01721 /* Start with the obvious, general stuff */ 01722 for (x = 0; x < 3; x++) { 01723 /* Look for three way calls */ 01724 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) { 01725 conf_add(p, &p->subs[x], x, 0); 01726 needconf++; 01727 } else { 01728 conf_del(p, &p->subs[x], x); 01729 } 01730 } 01731 /* If we have a slave, add him to our conference now. or DAX 01732 if this is slave native */ 01733 for (x = 0; x < MAX_SLAVES; x++) { 01734 if (p->slaves[x]) { 01735 if (useslavenative) 01736 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 01737 else { 01738 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 01739 needconf++; 01740 } 01741 } 01742 } 01743 /* If we're supposed to be in there, do so now */ 01744 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 01745 if (useslavenative) 01746 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 01747 else { 01748 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 01749 needconf++; 01750 } 01751 } 01752 /* If we have a master, add ourselves to his conference */ 01753 if (p->master) { 01754 if (isslavenative(p->master, NULL)) { 01755 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 01756 } else { 01757 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 01758 } 01759 } 01760 if (!needconf) { 01761 /* Nobody is left (or should be left) in our conference. 01762 Kill it. */ 01763 p->confno = -1; 01764 } 01765 if (option_debug) 01766 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf); 01767 return 0; 01768 }
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 11097 of file chan_dahdi.c.
References __action_dialoffhook(), and s.
11098 { 11099 return __action_dialoffhook(s, m, 1); 11100 }
static int zap_action_dndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10997 of file chan_dahdi.c.
References __action_dnd(), and s.
10998 { 10999 return __action_dnd(s, m, 1, 0); 11000 }
static int zap_action_dndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10987 of file chan_dahdi.c.
References __action_dnd(), and s.
10988 { 10989 return __action_dnd(s, m, 1, 1); 10990 }
static int zap_action_restart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 11176 of file chan_dahdi.c.
References __action_restart(), and s.
11177 { 11178 return __action_restart(s, m, 1); 11179 }
static int zap_action_showchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 11152 of file chan_dahdi.c.
References __action_showchannels(), and s.
11153 { 11154 return __action_showchannels(s, m, 1); 11155 }
static int zap_action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 11026 of file chan_dahdi.c.
References __action_transfer(), and s.
11027 { 11028 return __action_transfer(s, m, 1); 11029 }
static int zap_action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 11054 of file chan_dahdi.c.
References __action_transferhangup(), and s.
11055 { 11056 return __action_transferhangup(s, m, 1); 11057 }
static int zap_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 2730 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and send_keypad_facility_exec().
Referenced by load_module().
02731 { 02732 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); 02733 return send_keypad_facility_exec(chan, data); 02734 }
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 12402 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 12402 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 10893 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 10898 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 10878 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 10888 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 10883 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 10903 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 10871 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static] |
Definition at line 2672 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 2678 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static] |
Definition at line 2675 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 10764 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 10863 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 10867 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_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 10349 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 10353 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 10357 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 10361 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 10365 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 10859 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 10855 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 2673 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 2681 of file chan_dahdi.c.
char* zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static] |
Definition at line 2676 of file chan_dahdi.c.
struct ast_channel_tech zap_tech [static] |