#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 |
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 409 of file chan_dahdi.c.
#define CONF_USER_THIRDCALL (1 << 1) |
Definition at line 410 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 749 of file chan_dahdi.c.
#define HANGUP 1 |
Definition at line 10575 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 796 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 10605 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 10606 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 10993 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 774 of file chan_dahdi.c.
#define NUM_DCHANS 4 |
No more than 4 d-channels
Definition at line 188 of file chan_dahdi.c.
Referenced by dahdi_pri_error(), dahdi_pri_message(), mkintf(), pri_active_dchan_fd(), pri_create_trunkgroup(), pri_dchannel(), pri_find_dchan(), and pri_is_up().
#define NUM_SPANS 32 |
Definition at line 187 of file chan_dahdi.c.
Referenced by __unload_module(), build_channels(), complete_span_helper(), dahdi_pri_error(), dahdi_pri_message(), dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), handle_pri_debug(), handle_pri_no_debug(), handle_pri_really_debug(), handle_pri_show_debug(), handle_pri_show_span(), handle_pri_show_spans(), load_module(), mkintf(), pri_create_trunkgroup(), pri_resolve_span(), setup_dahdi(), and unload_module().
#define POLARITY_IDLE 0 |
Definition at line 367 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_hangup(), and unalloc_sub().
#define POLARITY_REV 1 |
Definition at line 368 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 294 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 1270 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 363 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 362 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 364 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 12024 of file chan_dahdi.c.
#define TRAILER_MS 5 |
Referenced by dahdi_sendtext().
#define TRANSFER 0 |
Definition at line 10574 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 10704 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().
10705 { 10706 struct dahdi_pvt *p = NULL; 10707 const char *channel = local_astman_header(m, "Channel", zap_mode); 10708 const char *number = astman_get_header(m, "Number"); 10709 int i; 10710 10711 if (ast_strlen_zero(channel)) { 10712 astman_send_error(s, m, "No channel specified"); 10713 return 0; 10714 } 10715 if (ast_strlen_zero(number)) { 10716 astman_send_error(s, m, "No number specified"); 10717 return 0; 10718 } 10719 if (!(p = find_channel(atoi(channel)))) { 10720 astman_send_error(s, m, "No such channel"); 10721 return 0; 10722 } 10723 if (!p->owner) { 10724 astman_send_error(s, m, "Channel does not have an owner"); 10725 return 0; 10726 } 10727 for (i = 0; i < strlen(number); i++) { 10728 struct ast_frame f = { AST_FRAME_DTMF, number[i] }; 10729 10730 dahdi_queue_frame(p, &f, NULL); 10731 } 10732 local_astman_ack(s, m, "DialOffHook", zap_mode); 10733 10734 return 0; 10735 }
static int __action_dnd | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode, | |||
int | dnd | |||
) | [static] |
Definition at line 10608 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().
10609 { 10610 struct dahdi_pvt *p = NULL; 10611 const char *channel = local_astman_header(m, "Channel", zap_mode); 10612 10613 if (ast_strlen_zero(channel)) { 10614 astman_send_error(s, m, "No channel specified"); 10615 return 0; 10616 } 10617 if (!(p = find_channel(atoi(channel)))) { 10618 astman_send_error(s, m, "No such channel"); 10619 return 0; 10620 } 10621 p->dnd = dnd; 10622 local_astman_ack(s, m, "DND", zap_mode); 10623 10624 return 0; 10625 }
static int __action_restart | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 10802 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().
10803 { 10804 if (dahdi_restart() != 0) { 10805 if (zap_mode) { 10806 astman_send_error(s, m, "Failed to restart Zap"); 10807 } else { 10808 astman_send_error(s, m, "Failed to restart DAHDI"); 10809 } 10810 return 1; 10811 } 10812 local_astman_ack(s, m, "Restart: Success", zap_mode); 10813 return 0; 10814 }
static int __action_showchannels | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 10747 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().
10748 { 10749 struct dahdi_pvt *tmp = NULL; 10750 const char *id = astman_get_header(m, "ActionID"); 10751 char idText[256] = ""; 10752 10753 local_astman_ack(s, m, " channel status will follow", zap_mode); 10754 if (!ast_strlen_zero(id)) 10755 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id); 10756 10757 ast_mutex_lock(&iflock); 10758 10759 tmp = iflist; 10760 while (tmp) { 10761 if (tmp->channel > 0) { 10762 int alarm = get_alarms(tmp); 10763 astman_append(s, 10764 "Event: %sShowChannels\r\n" 10765 "Channel: %d\r\n" 10766 "Signalling: %s\r\n" 10767 "Context: %s\r\n" 10768 "DND: %s\r\n" 10769 "Alarm: %s\r\n" 10770 "%s" 10771 "\r\n", 10772 dahdi_chan_name, 10773 tmp->channel, sig2str(tmp->sig), tmp->context, 10774 tmp->dnd ? "Enabled" : "Disabled", 10775 alarm2str(alarm), idText); 10776 } 10777 10778 tmp = tmp->next; 10779 } 10780 10781 ast_mutex_unlock(&iflock); 10782 10783 astman_append(s, 10784 "Event: %sShowChannelsComplete\r\n" 10785 "%s" 10786 "\r\n", 10787 dahdi_chan_name, 10788 idText); 10789 return 0; 10790 }
static int __action_transfer | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 10647 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().
10648 { 10649 struct dahdi_pvt *p = NULL; 10650 const char *channel = local_astman_header(m, "Channel", zap_mode); 10651 10652 if (ast_strlen_zero(channel)) { 10653 astman_send_error(s, m, "No channel specified"); 10654 return 0; 10655 } 10656 if (!(p = find_channel(atoi(channel)))) { 10657 astman_send_error(s, m, "No such channel"); 10658 return 0; 10659 } 10660 dahdi_fake_event(p,TRANSFER); 10661 local_astman_ack(s, m, "Transfer", zap_mode); 10662 10663 return 0; 10664 }
static int __action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 10676 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().
10677 { 10678 struct dahdi_pvt *p = NULL; 10679 const char *channel = local_astman_header(m, "Channel", zap_mode); 10680 10681 if (ast_strlen_zero(channel)) { 10682 astman_send_error(s, m, "No channel specified"); 10683 return 0; 10684 } 10685 if (!(p = find_channel(atoi(channel)))) { 10686 astman_send_error(s, m, "No such channel"); 10687 return 0; 10688 } 10689 dahdi_fake_event(p, HANGUP); 10690 local_astman_ack(s, m, "Hangup", zap_mode); 10691 return 0; 10692 }
static struct ast_frame* __dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 4642 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().
04643 { 04644 struct dahdi_pvt *p = ast->tech_pvt; 04645 int res; 04646 int usedindex=-1; 04647 int index; 04648 struct ast_frame *f; 04649 04650 04651 index = dahdi_get_index(ast, p, 1); 04652 04653 p->subs[index].f.frametype = AST_FRAME_NULL; 04654 p->subs[index].f.datalen = 0; 04655 p->subs[index].f.samples = 0; 04656 p->subs[index].f.mallocd = 0; 04657 p->subs[index].f.offset = 0; 04658 p->subs[index].f.subclass = 0; 04659 p->subs[index].f.delivery = ast_tv(0,0); 04660 p->subs[index].f.src = "dahdi_exception"; 04661 p->subs[index].f.data = NULL; 04662 04663 04664 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) { 04665 /* If nobody owns us, absorb the event appropriately, otherwise 04666 we loop indefinitely. This occurs when, during call waiting, the 04667 other end hangs up our channel so that it no longer exists, but we 04668 have neither FLASH'd nor ONHOOK'd to signify our desire to 04669 change to the other channel. */ 04670 if (p->fake_event) { 04671 res = p->fake_event; 04672 p->fake_event = 0; 04673 } else 04674 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 04675 /* Switch to real if there is one and this isn't something really silly... */ 04676 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) && 04677 (res != DAHDI_EVENT_HOOKCOMPLETE)) { 04678 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res); 04679 p->owner = p->subs[SUB_REAL].owner; 04680 if (p->owner && ast_bridged_channel(p->owner)) 04681 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 04682 p->subs[SUB_REAL].needunhold = 1; 04683 } 04684 switch (res) { 04685 case DAHDI_EVENT_ONHOOK: 04686 dahdi_disable_ec(p); 04687 if (p->owner) { 04688 if (option_verbose > 2) 04689 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name); 04690 dahdi_ring_phone(p); 04691 p->callwaitingrepeat = 0; 04692 p->cidcwexpire = 0; 04693 } else 04694 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 04695 update_conf(p); 04696 break; 04697 case DAHDI_EVENT_RINGOFFHOOK: 04698 dahdi_enable_ec(p); 04699 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 04700 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) { 04701 p->subs[SUB_REAL].needanswer = 1; 04702 p->dialing = 0; 04703 } 04704 break; 04705 case DAHDI_EVENT_HOOKCOMPLETE: 04706 case DAHDI_EVENT_RINGERON: 04707 case DAHDI_EVENT_RINGEROFF: 04708 /* Do nothing */ 04709 break; 04710 case DAHDI_EVENT_WINKFLASH: 04711 gettimeofday(&p->flashtime, NULL); 04712 if (p->owner) { 04713 if (option_verbose > 2) 04714 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name); 04715 if (p->owner->_state != AST_STATE_UP) { 04716 /* Answer if necessary */ 04717 usedindex = dahdi_get_index(p->owner, p, 0); 04718 if (usedindex > -1) { 04719 p->subs[usedindex].needanswer = 1; 04720 } 04721 ast_setstate(p->owner, AST_STATE_UP); 04722 } 04723 p->callwaitingrepeat = 0; 04724 p->cidcwexpire = 0; 04725 if (ast_bridged_channel(p->owner)) 04726 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 04727 p->subs[SUB_REAL].needunhold = 1; 04728 } else 04729 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 04730 update_conf(p); 04731 break; 04732 default: 04733 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res)); 04734 } 04735 f = &p->subs[index].f; 04736 return f; 04737 } 04738 if (!(p->radio || (p->oprmode < 0)) && option_debug) 04739 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel); 04740 /* If it's not us, return NULL immediately */ 04741 if (ast != p->owner) { 04742 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name); 04743 f = &p->subs[index].f; 04744 return f; 04745 } 04746 f = dahdi_handle_event(ast); 04747 return f; 04748 }
static void __reg_module | ( | void | ) | [static] |
Definition at line 12033 of file chan_dahdi.c.
static int __unload_module | ( | void | ) | [static] |
Definition at line 10833 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().
10834 { 10835 struct dahdi_pvt *p; 10836 10837 #ifdef HAVE_PRI 10838 int i, j; 10839 for (i = 0; i < NUM_SPANS; i++) { 10840 if (pris[i].master != AST_PTHREADT_NULL) 10841 pthread_cancel(pris[i].master); 10842 } 10843 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry)); 10844 10845 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 10846 ast_unregister_application(dahdi_send_keypad_facility_app); 10847 } 10848 ast_unregister_application(zap_send_keypad_facility_app); 10849 #endif 10850 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 10851 local_astman_unregister("DialOffHook"); 10852 local_astman_unregister("Hangup"); 10853 local_astman_unregister("Transfer"); 10854 local_astman_unregister("DNDoff"); 10855 local_astman_unregister("DNDon"); 10856 local_astman_unregister("ShowChannels"); 10857 local_astman_unregister("Restart"); 10858 ast_channel_unregister(chan_tech); 10859 ast_mutex_lock(&iflock); 10860 /* Hangup all interfaces if they have an owner */ 10861 p = iflist; 10862 while (p) { 10863 if (p->owner) 10864 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 10865 p = p->next; 10866 } 10867 ast_mutex_unlock(&iflock); 10868 ast_mutex_lock(&monlock); 10869 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 10870 pthread_cancel(monitor_thread); 10871 pthread_kill(monitor_thread, SIGURG); 10872 pthread_join(monitor_thread, NULL); 10873 } 10874 monitor_thread = AST_PTHREADT_STOP; 10875 ast_mutex_unlock(&monlock); 10876 10877 destroy_all_channels(); 10878 #ifdef HAVE_PRI 10879 for (i = 0; i < NUM_SPANS; i++) { 10880 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) 10881 pthread_join(pris[i].master, NULL); 10882 for (j = 0; j < NUM_DCHANS; j++) { 10883 dahdi_close_pri_fd(&(pris[i]), j); 10884 } 10885 } 10886 #endif 10887 ast_cond_destroy(&ss_thread_complete); 10888 return 0; 10889 }
static void __unreg_module | ( | void | ) | [static] |
Definition at line 12033 of file chan_dahdi.c.
static char* alarm2str | ( | int | alarm | ) | [static] |
Definition at line 1181 of file chan_dahdi.c.
Referenced by __action_showchannels(), and handle_alarms().
01182 { 01183 int x; 01184 for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) { 01185 if (alarms[x].alarm & alarm) 01186 return alarms[x].name; 01187 } 01188 return alarm ? "Unknown Alarm" : "No Alarm"; 01189 }
static int alloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 983 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().
00984 { 00985 struct dahdi_bufferinfo bi; 00986 int res; 00987 if (p->subs[x].dfd < 0) { 00988 p->subs[x].dfd = dahdi_open(DAHDI_FILE_PSEUDO); 00989 if (p->subs[x].dfd > -1) { 00990 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi); 00991 if (!res) { 00992 bi.txbufpolicy = p->buf_policy; 00993 bi.rxbufpolicy = p->buf_policy; 00994 bi.numbufs = p->buf_no; 00995 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi); 00996 if (res < 0) { 00997 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno)); 00998 } 00999 } else 01000 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno)); 01001 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) { 01002 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno)); 01003 dahdi_close_sub(p, x); 01004 return -1; 01005 } 01006 if (option_debug) 01007 ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan); 01008 return 0; 01009 } else 01010 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 01011 return -1; 01012 } 01013 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel); 01014 return -1; 01015 }
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 8503 of file chan_dahdi.c.
References dahdi_pri::internationalprefix, dahdi_pri::localprefix, dahdi_pri::nationalprefix, dahdi_pri::privateprefix, and dahdi_pri::unknownprefix.
08504 { 08505 switch (plan) { 08506 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */ 08507 snprintf(buf, size, "%s%s", pri->internationalprefix, number); 08508 break; 08509 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */ 08510 snprintf(buf, size, "%s%s", pri->nationalprefix, number); 08511 break; 08512 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */ 08513 snprintf(buf, size, "%s%s", pri->localprefix, number); 08514 break; 08515 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */ 08516 snprintf(buf, size, "%s%s", pri->privateprefix, number); 08517 break; 08518 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */ 08519 snprintf(buf, size, "%s%s", pri->unknownprefix, number); 08520 break; 08521 default: /* other Q.931 dialplan => don't twiddle with callingnum */ 08522 snprintf(buf, size, "%s", number); 08523 break; 08524 } 08525 }
static int attempt_transfer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3593 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().
03594 { 03595 /* In order to transfer, we need at least one of the channels to 03596 actually be in a call bridge. We can't conference two applications 03597 together (but then, why would we want to?) */ 03598 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 03599 /* The three-way person we're about to transfer to could still be in MOH, so 03600 stop if now if appropriate */ 03601 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) 03602 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD); 03603 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) { 03604 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING); 03605 } 03606 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) { 03607 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 03608 } 03609 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { 03610 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 03611 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name); 03612 return -1; 03613 } 03614 /* Orphan the channel after releasing the lock */ 03615 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 03616 unalloc_sub(p, SUB_THREEWAY); 03617 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 03618 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 03619 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) { 03620 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING); 03621 } 03622 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) { 03623 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 03624 } 03625 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { 03626 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 03627 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); 03628 return -1; 03629 } 03630 /* Three-way is now the REAL */ 03631 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03632 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock); 03633 unalloc_sub(p, SUB_THREEWAY); 03634 /* Tell the caller not to hangup */ 03635 return 1; 03636 } else { 03637 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n", 03638 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name); 03639 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 03640 return -1; 03641 } 03642 return 0; 03643 }
static int available | ( | struct dahdi_pvt * | p, | |
int | channelmatch, | |||
ast_group_t | groupmatch, | |||
int * | busy, | |||
int * | channelmatched, | |||
int * | groupmatched | |||
) | [inline, static] |
Definition at line 7791 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 dahdi_request().
07792 { 07793 int res; 07794 struct dahdi_params par; 07795 07796 /* First, check group matching */ 07797 if (groupmatch) { 07798 if ((p->group & groupmatch) != groupmatch) 07799 return 0; 07800 *groupmatched = 1; 07801 } 07802 /* Check to see if we have a channel match */ 07803 if (channelmatch != -1) { 07804 if (p->channel != channelmatch) 07805 return 0; 07806 *channelmatched = 1; 07807 } 07808 /* We're at least busy at this point */ 07809 if (busy) { 07810 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS)) 07811 *busy = 1; 07812 } 07813 /* If do not disturb, definitely not */ 07814 if (p->dnd) 07815 return 0; 07816 /* If guard time, definitely not */ 07817 if (p->guardtime && (time(NULL) < p->guardtime)) 07818 return 0; 07819 07820 /* If no owner definitely available */ 07821 if (!p->owner) { 07822 #ifdef HAVE_PRI 07823 /* Trust PRI */ 07824 if (p->pri) { 07825 if (p->resetting || p->call) 07826 return 0; 07827 else 07828 return 1; 07829 } 07830 #endif 07831 if (!(p->radio || (p->oprmode < 0))) 07832 { 07833 if (!p->sig || (p->sig == SIG_FXSLS)) 07834 return 1; 07835 /* Check hook state */ 07836 if (p->subs[SUB_REAL].dfd > -1) 07837 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 07838 else { 07839 /* Assume not off hook on CVRS */ 07840 res = 0; 07841 par.rxisoffhook = 0; 07842 } 07843 if (res) { 07844 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno)); 07845 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) { 07846 /* When "onhook" that means no battery on the line, and thus 07847 it is out of service..., if it's on a TDM card... If it's a channel 07848 bank, there is no telling... */ 07849 if (par.rxbits > -1) 07850 return 1; 07851 if (par.rxisoffhook) 07852 return 1; 07853 else 07854 #ifdef DAHDI_CHECK_HOOKSTATE 07855 return 0; 07856 #else 07857 return 1; 07858 #endif 07859 } else if (par.rxisoffhook) { 07860 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel); 07861 /* Not available when the other end is off hook */ 07862 return 0; 07863 } 07864 } 07865 return 1; 07866 } 07867 07868 /* If it's not an FXO, forget about call wait */ 07869 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 07870 return 0; 07871 07872 if (!p->callwaiting) { 07873 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */ 07874 return 0; 07875 } 07876 07877 if (p->subs[SUB_CALLWAIT].dfd > -1) { 07878 /* If there is already a call waiting call, then we can't take a second one */ 07879 return 0; 07880 } 07881 07882 if ((p->owner->_state != AST_STATE_UP) && 07883 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) { 07884 /* If the current call is not up, then don't allow the call */ 07885 return 0; 07886 } 07887 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) { 07888 /* Can't take a call wait when the three way calling hasn't been merged yet. */ 07889 return 0; 07890 } 07891 /* We're cool */ 07892 return 1; 07893 }
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 10901 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().
10902 { 10903 char *c, *chan; 10904 int x, start, finish; 10905 struct dahdi_pvt *tmp; 10906 #ifdef HAVE_PRI 10907 struct dahdi_pri *pri; 10908 int trunkgroup, y; 10909 #endif 10910 10911 if ((reload == 0) && (conf->chan.sig < 0)) { 10912 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); 10913 return -1; 10914 } 10915 10916 c = ast_strdupa(value); 10917 10918 #ifdef HAVE_PRI 10919 pri = NULL; 10920 if (iscrv) { 10921 if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) { 10922 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno); 10923 return -1; 10924 } 10925 if (trunkgroup < 1) { 10926 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno); 10927 return -1; 10928 } 10929 c += y; 10930 for (y = 0; y < NUM_SPANS; y++) { 10931 if (pris[y].trunkgroup == trunkgroup) { 10932 pri = pris + y; 10933 break; 10934 } 10935 } 10936 if (!pri) { 10937 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno); 10938 return -1; 10939 } 10940 } 10941 #endif 10942 10943 while ((chan = strsep(&c, ","))) { 10944 if (sscanf(chan, "%d-%d", &start, &finish) == 2) { 10945 /* Range */ 10946 } else if (sscanf(chan, "%d", &start)) { 10947 /* Just one */ 10948 finish = start; 10949 } else if (!strcasecmp(chan, "pseudo")) { 10950 finish = start = CHAN_PSEUDO; 10951 if (found_pseudo) 10952 *found_pseudo = 1; 10953 } else { 10954 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan); 10955 return -1; 10956 } 10957 if (finish < start) { 10958 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); 10959 x = finish; 10960 finish = start; 10961 start = x; 10962 } 10963 10964 for (x = start; x <= finish; x++) { 10965 #ifdef HAVE_PRI 10966 tmp = mkintf(x, conf, pri, reload); 10967 #else 10968 tmp = mkintf(x, conf, NULL, reload); 10969 #endif 10970 10971 if (tmp) { 10972 if (option_verbose > 2) { 10973 #ifdef HAVE_PRI 10974 if (pri) 10975 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig)); 10976 else 10977 #endif 10978 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig)); 10979 } 10980 } else { 10981 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n", 10982 (reload == 1) ? "reconfigure" : "register", value); 10983 return -1; 10984 } 10985 } 10986 } 10987 10988 return 0; 10989 }
static void build_status | ( | char * | s, | |
size_t | len, | |||
int | status, | |||
int | active | |||
) | [static] |
Definition at line 9880 of file chan_dahdi.c.
References DCHAN_NOTINALARM, and DCHAN_PROVISIONED.
Referenced by handle_pri_show_span(), and handle_pri_show_spans().
09881 { 09882 if (!s || len < 1) { 09883 return; 09884 } 09885 s[0] = '\0'; 09886 if (status & DCHAN_PROVISIONED) 09887 strncat(s, "Provisioned, ", len - strlen(s) - 1); 09888 if (!(status & DCHAN_NOTINALARM)) 09889 strncat(s, "In Alarm, ", len - strlen(s) - 1); 09890 if (status & DCHAN_UP) 09891 strncat(s, "Up", len - strlen(s) - 1); 09892 else 09893 strncat(s, "Down", len - strlen(s) - 1); 09894 if (active) 09895 strncat(s, ", Active", len - strlen(s) - 1); 09896 else 09897 strncat(s, ", Standby", len - strlen(s) - 1); 09898 s[len - 1] = '\0'; 09899 }
static int bump_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1632 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().
01633 { 01634 int res; 01635 01636 /* Bump receive gain by 5.0db */ 01637 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law); 01638 if (res) { 01639 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno)); 01640 return -1; 01641 } 01642 01643 return 0; 01644 }
Definition at line 7895 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().
07896 { 07897 struct dahdi_pvt *p; 07898 struct dahdi_bufferinfo bi; 07899 int res; 07900 07901 if ((p = ast_malloc(sizeof(*p)))) { 07902 memcpy(p, src, sizeof(struct dahdi_pvt)); 07903 ast_mutex_init(&p->lock); 07904 p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO); 07905 /* Allocate a DAHDI structure */ 07906 if (p->subs[SUB_REAL].dfd < 0) { 07907 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno)); 07908 destroy_dahdi_pvt(&p); 07909 return NULL; 07910 } 07911 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 07912 if (!res) { 07913 bi.txbufpolicy = p->buf_policy; 07914 bi.rxbufpolicy = p->buf_policy; 07915 bi.numbufs = p->buf_no; 07916 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 07917 if (res < 0) { 07918 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno)); 07919 } 07920 } else 07921 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno)); 07922 } 07923 p->destroy = 1; 07924 p->next = iflist; 07925 p->prev = NULL; 07926 iflist = p; 07927 if (iflist->next) 07928 iflist->next->prev = p; 07929 return p; 07930 }
static int check_for_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3645 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().
03646 { 03647 struct dahdi_confinfo ci; 03648 /* Fine if we already have a master, etc */ 03649 if (p->master || (p->confno > -1)) 03650 return 0; 03651 memset(&ci, 0, sizeof(ci)); 03652 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 03653 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno)); 03654 return 0; 03655 } 03656 /* If we have no master and don't have a confno, then 03657 if we're in a conference, it's probably a MeetMe room or 03658 some such, so don't let us 3-way out! */ 03659 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) { 03660 if (option_verbose > 2) 03661 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n"); 03662 return 1; 03663 } 03664 return 0; 03665 }
static char* complete_span_4 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 9747 of file chan_dahdi.c.
References complete_span_helper().
09748 { 09749 return complete_span_helper(line,word,pos,state,3); 09750 }
static char* complete_span_5 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 9752 of file chan_dahdi.c.
References complete_span_helper().
09753 { 09754 return complete_span_helper(line,word,pos,state,4); 09755 }
static char* complete_span_helper | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state, | |||
int | rpos | |||
) | [static] |
Definition at line 9728 of file chan_dahdi.c.
References asprintf, ast_log(), errno, NUM_SPANS, and pris.
Referenced by complete_span_4(), and complete_span_5().
09729 { 09730 int which, span; 09731 char *ret = NULL; 09732 09733 if (pos != rpos) 09734 return ret; 09735 09736 for (which = span = 0; span < NUM_SPANS; span++) { 09737 if (pris[span].pri && ++which > state) { 09738 if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */ 09739 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 09740 } 09741 break; 09742 } 09743 } 09744 return ret; 09745 }
static int conf_add | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index, | |||
int | slavechannel | |||
) | [static] |
Definition at line 1272 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().
01273 { 01274 /* If the conference already exists, and we're already in it 01275 don't bother doing anything */ 01276 struct dahdi_confinfo zi; 01277 01278 memset(&zi, 0, sizeof(zi)); 01279 zi.chan = 0; 01280 01281 if (slavechannel > 0) { 01282 /* If we have only one slave, do a digital mon */ 01283 zi.confmode = DAHDI_CONF_DIGITALMON; 01284 zi.confno = slavechannel; 01285 } else { 01286 if (!index) { 01287 /* Real-side and pseudo-side both participate in conference */ 01288 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER | 01289 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 01290 } else 01291 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 01292 zi.confno = p->confno; 01293 } 01294 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode)) 01295 return 0; 01296 if (c->dfd < 0) 01297 return 0; 01298 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 01299 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno)); 01300 return -1; 01301 } 01302 if (slavechannel < 1) { 01303 p->confno = zi.confno; 01304 } 01305 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 01306 ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 01307 return 0; 01308 }
static int conf_del | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index | |||
) | [static] |
Definition at line 1321 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().
01322 { 01323 struct dahdi_confinfo zi; 01324 if (/* Can't delete if there's no dfd */ 01325 (c->dfd < 0) || 01326 /* Don't delete from the conference if it's not our conference */ 01327 !isourconf(p, c) 01328 /* Don't delete if we don't think it's conferenced at all (implied) */ 01329 ) return 0; 01330 memset(&zi, 0, sizeof(zi)); 01331 zi.chan = 0; 01332 zi.confno = 0; 01333 zi.confmode = 0; 01334 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 01335 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno)); 01336 return -1; 01337 } 01338 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 01339 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 01340 return 0; 01341 }
static int dahdi_action_dialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10742 of file chan_dahdi.c.
References __action_dialoffhook(), and s.
10743 { 10744 return __action_dialoffhook(s, m, 0); 10745 }
static int dahdi_action_dndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10642 of file chan_dahdi.c.
References __action_dnd(), and s.
10643 { 10644 return __action_dnd(s, m, 0, 0); 10645 }
static int dahdi_action_dndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10632 of file chan_dahdi.c.
References __action_dnd(), and s.
10633 { 10634 return __action_dnd(s, m, 0, 1); 10635 }
static int dahdi_action_restart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10821 of file chan_dahdi.c.
References __action_restart(), and s.
10822 { 10823 return __action_restart(s, m, 0); 10824 }
static int dahdi_action_showchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10797 of file chan_dahdi.c.
References __action_showchannels(), and s.
10798 { 10799 return __action_showchannels(s, m, 0); 10800 }
static int dahdi_action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10671 of file chan_dahdi.c.
References __action_transfer(), and s.
10672 { 10673 return __action_transfer(s, m, 0); 10674 }
static int dahdi_action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10699 of file chan_dahdi.c.
References __action_transferhangup(), and s.
10700 { 10701 return __action_transferhangup(s, m, 0); 10702 }
static int dahdi_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 2839 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.
02840 { 02841 struct dahdi_pvt *p = ast->tech_pvt; 02842 int res = 0; 02843 int index; 02844 int oldstate = ast->_state; 02845 ast_setstate(ast, AST_STATE_UP); 02846 ast_mutex_lock(&p->lock); 02847 index = dahdi_get_index(ast, p, 0); 02848 if (index < 0) 02849 index = SUB_REAL; 02850 /* nothing to do if a radio channel */ 02851 if ((p->radio || (p->oprmode < 0))) { 02852 ast_mutex_unlock(&p->lock); 02853 return 0; 02854 } 02855 switch (p->sig) { 02856 case SIG_FXSLS: 02857 case SIG_FXSGS: 02858 case SIG_FXSKS: 02859 p->ringt = 0; 02860 /* Fall through */ 02861 case SIG_EM: 02862 case SIG_EM_E1: 02863 case SIG_EMWINK: 02864 case SIG_FEATD: 02865 case SIG_FEATDMF: 02866 case SIG_FEATDMF_TA: 02867 case SIG_E911: 02868 case SIG_FGC_CAMA: 02869 case SIG_FGC_CAMAMF: 02870 case SIG_FEATB: 02871 case SIG_SF: 02872 case SIG_SFWINK: 02873 case SIG_SF_FEATD: 02874 case SIG_SF_FEATDMF: 02875 case SIG_SF_FEATB: 02876 case SIG_FXOLS: 02877 case SIG_FXOGS: 02878 case SIG_FXOKS: 02879 /* Pick up the line */ 02880 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name); 02881 if (p->hanguponpolarityswitch) { 02882 gettimeofday(&p->polaritydelaytv, NULL); 02883 } 02884 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 02885 tone_zone_play_tone(p->subs[index].dfd, -1); 02886 p->dialing = 0; 02887 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) { 02888 if (oldstate == AST_STATE_RINGING) { 02889 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n"); 02890 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1); 02891 swap_subs(p, SUB_THREEWAY, SUB_REAL); 02892 p->owner = p->subs[SUB_REAL].owner; 02893 } 02894 } 02895 if (p->sig & __DAHDI_SIG_FXS) { 02896 dahdi_enable_ec(p); 02897 dahdi_train_ec(p); 02898 } 02899 break; 02900 #ifdef HAVE_PRI 02901 case SIG_PRI: 02902 /* Send a pri acknowledge */ 02903 if (!pri_grab(p, p->pri)) { 02904 p->proceeding = 1; 02905 res = pri_answer(p->pri->pri, p->call, 0, !p->digital); 02906 pri_rel(p->pri); 02907 } else { 02908 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 02909 res = -1; 02910 } 02911 break; 02912 #endif 02913 case 0: 02914 ast_mutex_unlock(&p->lock); 02915 return 0; 02916 default: 02917 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel); 02918 res = -1; 02919 } 02920 ast_mutex_unlock(&p->lock); 02921 return res; 02922 }
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 3246 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.
03247 { 03248 struct ast_channel *who; 03249 struct dahdi_pvt *p0, *p1, *op0, *op1; 03250 struct dahdi_pvt *master = NULL, *slave = NULL; 03251 struct ast_frame *f; 03252 int inconf = 0; 03253 int nothingok = 1; 03254 int ofd0, ofd1; 03255 int oi0, oi1, i0 = -1, i1 = -1, t0, t1; 03256 int os0 = -1, os1 = -1; 03257 int priority = 0; 03258 struct ast_channel *oc0, *oc1; 03259 enum ast_bridge_result res; 03260 03261 #ifdef PRI_2BCT 03262 int triedtopribridge = 0; 03263 q931_call *q931c0 = NULL, *q931c1 = NULL; 03264 #endif 03265 03266 /* For now, don't attempt to native bridge if either channel needs DTMF detection. 03267 There is code below to handle it properly until DTMF is actually seen, 03268 but due to currently unresolved issues it's ignored... 03269 */ 03270 03271 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 03272 return AST_BRIDGE_FAILED_NOWARN; 03273 03274 ast_mutex_lock(&c0->lock); 03275 while (ast_mutex_trylock(&c1->lock)) { 03276 DEADLOCK_AVOIDANCE(&c0->lock); 03277 } 03278 03279 p0 = c0->tech_pvt; 03280 p1 = c1->tech_pvt; 03281 /* cant do pseudo-channels here */ 03282 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) { 03283 ast_mutex_unlock(&c0->lock); 03284 ast_mutex_unlock(&c1->lock); 03285 return AST_BRIDGE_FAILED_NOWARN; 03286 } 03287 03288 oi0 = dahdi_get_index(c0, p0, 0); 03289 oi1 = dahdi_get_index(c1, p1, 0); 03290 if ((oi0 < 0) || (oi1 < 0)) { 03291 ast_mutex_unlock(&c0->lock); 03292 ast_mutex_unlock(&c1->lock); 03293 return AST_BRIDGE_FAILED; 03294 } 03295 03296 op0 = p0 = c0->tech_pvt; 03297 op1 = p1 = c1->tech_pvt; 03298 ofd0 = c0->fds[0]; 03299 ofd1 = c1->fds[0]; 03300 oc0 = p0->owner; 03301 oc1 = p1->owner; 03302 03303 if (ast_mutex_trylock(&p0->lock)) { 03304 /* Don't block, due to potential for deadlock */ 03305 ast_mutex_unlock(&c0->lock); 03306 ast_mutex_unlock(&c1->lock); 03307 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 03308 return AST_BRIDGE_RETRY; 03309 } 03310 if (ast_mutex_trylock(&p1->lock)) { 03311 /* Don't block, due to potential for deadlock */ 03312 ast_mutex_unlock(&p0->lock); 03313 ast_mutex_unlock(&c0->lock); 03314 ast_mutex_unlock(&c1->lock); 03315 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 03316 return AST_BRIDGE_RETRY; 03317 } 03318 03319 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 03320 if (p0->owner && p1->owner) { 03321 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */ 03322 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) { 03323 master = p0; 03324 slave = p1; 03325 inconf = 1; 03326 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) { 03327 master = p1; 03328 slave = p0; 03329 inconf = 1; 03330 } else { 03331 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n"); 03332 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n", 03333 p0->channel, 03334 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 03335 p0->subs[SUB_REAL].inthreeway, p0->channel, 03336 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 03337 p1->subs[SUB_REAL].inthreeway); 03338 } 03339 nothingok = 0; 03340 } 03341 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) { 03342 if (p1->subs[SUB_THREEWAY].inthreeway) { 03343 master = p1; 03344 slave = p0; 03345 nothingok = 0; 03346 } 03347 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) { 03348 if (p0->subs[SUB_THREEWAY].inthreeway) { 03349 master = p0; 03350 slave = p1; 03351 nothingok = 0; 03352 } 03353 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) { 03354 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise, 03355 don't put us in anything */ 03356 if (p1->subs[SUB_CALLWAIT].inthreeway) { 03357 master = p1; 03358 slave = p0; 03359 nothingok = 0; 03360 } 03361 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) { 03362 /* Same as previous */ 03363 if (p0->subs[SUB_CALLWAIT].inthreeway) { 03364 master = p0; 03365 slave = p1; 03366 nothingok = 0; 03367 } 03368 } 03369 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n", 03370 master ? master->channel : 0, slave ? slave->channel : 0, nothingok); 03371 if (master && slave) { 03372 /* Stop any tones, or play ringtone as appropriate. If they're bridged 03373 in an active threeway call with a channel that is ringing, we should 03374 indicate ringing. */ 03375 if ((oi1 == SUB_THREEWAY) && 03376 p1->subs[SUB_THREEWAY].inthreeway && 03377 p1->subs[SUB_REAL].owner && 03378 p1->subs[SUB_REAL].inthreeway && 03379 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 03380 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name); 03381 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE); 03382 os1 = p1->subs[SUB_REAL].owner->_state; 03383 } else { 03384 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1); 03385 tone_zone_play_tone(p0->subs[oi0].dfd, -1); 03386 } 03387 if ((oi0 == SUB_THREEWAY) && 03388 p0->subs[SUB_THREEWAY].inthreeway && 03389 p0->subs[SUB_REAL].owner && 03390 p0->subs[SUB_REAL].inthreeway && 03391 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 03392 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name); 03393 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE); 03394 os0 = p0->subs[SUB_REAL].owner->_state; 03395 } else { 03396 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0); 03397 tone_zone_play_tone(p1->subs[oi0].dfd, -1); 03398 } 03399 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 03400 if (!p0->echocanbridged || !p1->echocanbridged) { 03401 /* Disable echo cancellation if appropriate */ 03402 dahdi_disable_ec(p0); 03403 dahdi_disable_ec(p1); 03404 } 03405 } 03406 dahdi_link(slave, master); 03407 master->inconference = inconf; 03408 } else if (!nothingok) 03409 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]); 03410 03411 update_conf(p0); 03412 update_conf(p1); 03413 t0 = p0->subs[SUB_REAL].inthreeway; 03414 t1 = p1->subs[SUB_REAL].inthreeway; 03415 03416 ast_mutex_unlock(&p0->lock); 03417 ast_mutex_unlock(&p1->lock); 03418 03419 ast_mutex_unlock(&c0->lock); 03420 ast_mutex_unlock(&c1->lock); 03421 03422 /* Native bridge failed */ 03423 if ((!master || !slave) && !nothingok) { 03424 dahdi_enable_ec(p0); 03425 dahdi_enable_ec(p1); 03426 return AST_BRIDGE_FAILED; 03427 } 03428 03429 if (option_verbose > 2) 03430 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name); 03431 03432 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 03433 disable_dtmf_detect(op0); 03434 03435 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 03436 disable_dtmf_detect(op1); 03437 03438 for (;;) { 03439 struct ast_channel *c0_priority[2] = {c0, c1}; 03440 struct ast_channel *c1_priority[2] = {c1, c0}; 03441 03442 /* Here's our main loop... Start by locking things, looking for private parts, 03443 and then balking if anything is wrong */ 03444 ast_mutex_lock(&c0->lock); 03445 while (ast_mutex_trylock(&c1->lock)) { 03446 DEADLOCK_AVOIDANCE(&c0->lock); 03447 } 03448 03449 p0 = c0->tech_pvt; 03450 p1 = c1->tech_pvt; 03451 03452 if (op0 == p0) 03453 i0 = dahdi_get_index(c0, p0, 1); 03454 if (op1 == p1) 03455 i1 = dahdi_get_index(c1, p1, 1); 03456 ast_mutex_unlock(&c0->lock); 03457 ast_mutex_unlock(&c1->lock); 03458 03459 if (!timeoutms || 03460 (op0 != p0) || 03461 (op1 != p1) || 03462 (ofd0 != c0->fds[0]) || 03463 (ofd1 != c1->fds[0]) || 03464 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 03465 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 03466 (oc0 != p0->owner) || 03467 (oc1 != p1->owner) || 03468 (t0 != p0->subs[SUB_REAL].inthreeway) || 03469 (t1 != p1->subs[SUB_REAL].inthreeway) || 03470 (oi0 != i0) || 03471 (oi1 != i1)) { 03472 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n", 03473 op0->channel, oi0, op1->channel, oi1); 03474 res = AST_BRIDGE_RETRY; 03475 goto return_from_bridge; 03476 } 03477 03478 #ifdef PRI_2BCT 03479 q931c0 = p0->call; 03480 q931c1 = p1->call; 03481 if (p0->transfer && p1->transfer 03482 && q931c0 && q931c1 03483 && !triedtopribridge) { 03484 pri_channel_bridge(q931c0, q931c1); 03485 triedtopribridge = 1; 03486 } 03487 #endif 03488 03489 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms); 03490 if (!who) { 03491 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 03492 continue; 03493 } 03494 f = ast_read(who); 03495 if (!f || (f->frametype == AST_FRAME_CONTROL)) { 03496 *fo = f; 03497 *rc = who; 03498 res = AST_BRIDGE_COMPLETE; 03499 goto return_from_bridge; 03500 } 03501 if (f->frametype == AST_FRAME_DTMF) { 03502 if ((who == c0) && p0->pulsedial) { 03503 ast_write(c1, f); 03504 } else if ((who == c1) && p1->pulsedial) { 03505 ast_write(c0, f); 03506 } else { 03507 *fo = f; 03508 *rc = who; 03509 res = AST_BRIDGE_COMPLETE; 03510 goto return_from_bridge; 03511 } 03512 } 03513 ast_frfree(f); 03514 03515 /* Swap who gets priority */ 03516 priority = !priority; 03517 } 03518 03519 return_from_bridge: 03520 if (op0 == p0) 03521 dahdi_enable_ec(p0); 03522 03523 if (op1 == p1) 03524 dahdi_enable_ec(p1); 03525 03526 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 03527 enable_dtmf_detect(op0); 03528 03529 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 03530 enable_dtmf_detect(op1); 03531 03532 dahdi_unlink(slave, master, 1); 03533 03534 return res; 03535 }
static int dahdi_call | ( | struct ast_channel * | ast, | |
char * | rdest, | |||
int | timeout | |||
) | [static] |
Definition at line 1821 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.
01822 { 01823 struct dahdi_pvt *p = ast->tech_pvt; 01824 int x, res, index,mysig; 01825 char *c, *n, *l; 01826 #ifdef HAVE_PRI 01827 char *s = NULL; 01828 #endif 01829 char dest[256]; /* must be same length as p->dialdest */ 01830 ast_mutex_lock(&p->lock); 01831 ast_copy_string(dest, rdest, sizeof(dest)); 01832 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest)); 01833 if ((ast->_state == AST_STATE_BUSY)) { 01834 p->subs[SUB_REAL].needbusy = 1; 01835 ast_mutex_unlock(&p->lock); 01836 return 0; 01837 } 01838 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 01839 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name); 01840 ast_mutex_unlock(&p->lock); 01841 return -1; 01842 } 01843 p->dialednone = 0; 01844 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ 01845 { 01846 /* Special pseudo -- automatically up */ 01847 ast_setstate(ast, AST_STATE_UP); 01848 ast_mutex_unlock(&p->lock); 01849 return 0; 01850 } 01851 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE; 01852 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 01853 if (res) 01854 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno)); 01855 p->outgoing = 1; 01856 01857 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 01858 01859 mysig = p->sig; 01860 if (p->outsigmod > -1) 01861 mysig = p->outsigmod; 01862 01863 switch (mysig) { 01864 case SIG_FXOLS: 01865 case SIG_FXOGS: 01866 case SIG_FXOKS: 01867 if (p->owner == ast) { 01868 /* Normal ring, on hook */ 01869 01870 /* Don't send audio while on hook, until the call is answered */ 01871 p->dialing = 1; 01872 if (p->use_callerid) { 01873 /* Generate the Caller-ID spill if desired */ 01874 if (p->cidspill) { 01875 ast_log(LOG_WARNING, "cidspill already exists??\n"); 01876 free(p->cidspill); 01877 } 01878 p->callwaitcas = 0; 01879 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) { 01880 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p)); 01881 p->cidpos = 0; 01882 send_callerid(p); 01883 } 01884 } 01885 /* Choose proper cadence */ 01886 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { 01887 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) 01888 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); 01889 p->cidrings = cidrings[p->distinctivering - 1]; 01890 } else { 01891 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) 01892 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); 01893 p->cidrings = p->sendcalleridafter; 01894 } 01895 01896 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */ 01897 c = strchr(dest, '/'); 01898 if (c) 01899 c++; 01900 if (c && (strlen(c) < p->stripmsd)) { 01901 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 01902 c = NULL; 01903 } 01904 if (c) { 01905 p->dop.op = DAHDI_DIAL_OP_REPLACE; 01906 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c); 01907 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c); 01908 } else { 01909 p->dop.dialstr[0] = '\0'; 01910 } 01911 x = DAHDI_RING; 01912 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) { 01913 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno)); 01914 ast_mutex_unlock(&p->lock); 01915 return -1; 01916 } 01917 p->dialing = 1; 01918 } else { 01919 /* Call waiting call */ 01920 p->callwaitrings = 0; 01921 if (ast->cid.cid_num) 01922 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num)); 01923 else 01924 p->callwait_num[0] = '\0'; 01925 if (ast->cid.cid_name) 01926 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name)); 01927 else 01928 p->callwait_name[0] = '\0'; 01929 /* Call waiting tone instead */ 01930 if (dahdi_callwait(ast)) { 01931 ast_mutex_unlock(&p->lock); 01932 return -1; 01933 } 01934 /* Make ring-back */ 01935 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE)) 01936 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name); 01937 01938 } 01939 n = ast->cid.cid_name; 01940 l = ast->cid.cid_num; 01941 if (l) 01942 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num)); 01943 else 01944 p->lastcid_num[0] = '\0'; 01945 if (n) 01946 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name)); 01947 else 01948 p->lastcid_name[0] = '\0'; 01949 ast_setstate(ast, AST_STATE_RINGING); 01950 index = dahdi_get_index(ast, p, 0); 01951 if (index > -1) { 01952 p->subs[index].needringing = 1; 01953 } 01954 break; 01955 case SIG_FXSLS: 01956 case SIG_FXSGS: 01957 case SIG_FXSKS: 01958 case SIG_EMWINK: 01959 case SIG_EM: 01960 case SIG_EM_E1: 01961 case SIG_FEATD: 01962 case SIG_FEATDMF: 01963 case SIG_E911: 01964 case SIG_FGC_CAMA: 01965 case SIG_FGC_CAMAMF: 01966 case SIG_FEATB: 01967 case SIG_SFWINK: 01968 case SIG_SF: 01969 case SIG_SF_FEATD: 01970 case SIG_SF_FEATDMF: 01971 case SIG_FEATDMF_TA: 01972 case SIG_SF_FEATB: 01973 c = strchr(dest, '/'); 01974 if (c) 01975 c++; 01976 else 01977 c = ""; 01978 if (strlen(c) < p->stripmsd) { 01979 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 01980 ast_mutex_unlock(&p->lock); 01981 return -1; 01982 } 01983 #ifdef HAVE_PRI 01984 /* Start the trunk, if not GR-303 */ 01985 if (!p->pri) { 01986 #endif 01987 x = DAHDI_START; 01988 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 01989 if (res < 0) { 01990 if (errno != EINPROGRESS) { 01991 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 01992 ast_mutex_unlock(&p->lock); 01993 return -1; 01994 } 01995 } 01996 #ifdef HAVE_PRI 01997 } 01998 #endif 01999 ast_log(LOG_DEBUG, "Dialing '%s'\n", c); 02000 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02001 02002 c += p->stripmsd; 02003 02004 switch (mysig) { 02005 case SIG_FEATD: 02006 l = ast->cid.cid_num; 02007 if (l) 02008 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c); 02009 else 02010 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c); 02011 break; 02012 case SIG_FEATDMF: 02013 l = ast->cid.cid_num; 02014 if (l) 02015 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c); 02016 else 02017 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c); 02018 break; 02019 case SIG_FEATDMF_TA: 02020 { 02021 const char *cic, *ozz; 02022 02023 /* If you have to go through a Tandem Access point you need to use this */ 02024 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ"); 02025 if (!ozz) 02026 ozz = defaultozz; 02027 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC"); 02028 if (!cic) 02029 cic = defaultcic; 02030 if (!ozz || !cic) { 02031 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n"); 02032 ast_mutex_unlock(&p->lock); 02033 return -1; 02034 } 02035 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic); 02036 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c); 02037 p->whichwink = 0; 02038 } 02039 break; 02040 case SIG_E911: 02041 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr)); 02042 break; 02043 case SIG_FGC_CAMA: 02044 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c); 02045 break; 02046 case SIG_FGC_CAMAMF: 02047 case SIG_FEATB: 02048 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c); 02049 break; 02050 default: 02051 if (p->pulse) 02052 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c); 02053 else 02054 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c); 02055 break; 02056 } 02057 02058 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) { 02059 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 02060 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 02061 p->echorest[sizeof(p->echorest) - 1] = '\0'; 02062 p->echobreak = 1; 02063 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 02064 } else 02065 p->echobreak = 0; 02066 if (!res) { 02067 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 02068 int saveerr = errno; 02069 02070 x = DAHDI_ONHOOK; 02071 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02072 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 02073 ast_mutex_unlock(&p->lock); 02074 return -1; 02075 } 02076 } else 02077 ast_log(LOG_DEBUG, "Deferring dialing...\n"); 02078 p->dialing = 1; 02079 if (ast_strlen_zero(c)) 02080 p->dialednone = 1; 02081 ast_setstate(ast, AST_STATE_DIALING); 02082 break; 02083 case 0: 02084 /* Special pseudo -- automatically up*/ 02085 ast_setstate(ast, AST_STATE_UP); 02086 break; 02087 case SIG_PRI: 02088 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */ 02089 p->dialdest[0] = '\0'; 02090 break; 02091 default: 02092 ast_log(LOG_DEBUG, "not yet implemented\n"); 02093 ast_mutex_unlock(&p->lock); 02094 return -1; 02095 } 02096 #ifdef HAVE_PRI 02097 if (p->pri) { 02098 struct pri_sr *sr; 02099 #ifdef SUPPORT_USERUSER 02100 const char *useruser; 02101 #endif 02102 int pridialplan; 02103 int dp_strip; 02104 int prilocaldialplan; 02105 int ldp_strip; 02106 int exclusive; 02107 const char *rr_str; 02108 int redirect_reason; 02109 02110 c = strchr(dest, '/'); 02111 if (c) 02112 c++; 02113 else 02114 c = dest; 02115 02116 l = NULL; 02117 n = NULL; 02118 02119 if (!p->hidecallerid) { 02120 l = ast->cid.cid_num; 02121 if (!p->hidecalleridname) { 02122 n = ast->cid.cid_name; 02123 } 02124 } 02125 02126 02127 if (strlen(c) < p->stripmsd) { 02128 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02129 ast_mutex_unlock(&p->lock); 02130 return -1; 02131 } 02132 if (mysig != SIG_FXSKS) { 02133 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02134 s = strchr(c + p->stripmsd, 'w'); 02135 if (s) { 02136 if (strlen(s) > 1) 02137 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s); 02138 else 02139 p->dop.dialstr[0] = '\0'; 02140 *s = '\0'; 02141 } else { 02142 p->dop.dialstr[0] = '\0'; 02143 } 02144 } 02145 if (pri_grab(p, p->pri)) { 02146 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 02147 ast_mutex_unlock(&p->lock); 02148 return -1; 02149 } 02150 if (!(p->call = pri_new_call(p->pri->pri))) { 02151 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel); 02152 pri_rel(p->pri); 02153 ast_mutex_unlock(&p->lock); 02154 return -1; 02155 } 02156 if (!(sr = pri_sr_new())) { 02157 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel); 02158 pri_destroycall(p->pri->pri, p->call); 02159 p->call = NULL; 02160 pri_rel(p->pri); 02161 ast_mutex_unlock(&p->lock); 02162 return -1; 02163 } 02164 if (p->bearer || (mysig == SIG_FXSKS)) { 02165 if (p->bearer) { 02166 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); 02167 p->bearer->call = p->call; 02168 } else 02169 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n"); 02170 pri_set_crv(p->pri->pri, p->call, p->channel, 0); 02171 } 02172 p->digital = IS_DIGITAL(ast->transfercapability); 02173 /* Add support for exclusive override */ 02174 if (p->priexclusive) 02175 exclusive = 1; 02176 else { 02177 /* otherwise, traditional behavior */ 02178 if (p->pri->nodetype == PRI_NETWORK) 02179 exclusive = 0; 02180 else 02181 exclusive = 1; 02182 } 02183 02184 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1); 02185 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 02186 (p->digital ? -1 : 02187 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW))); 02188 if (p->pri->facilityenable) 02189 pri_facility_enable(p->pri->pri); 02190 02191 if (option_verbose > 2) 02192 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability)); 02193 dp_strip = 0; 02194 pridialplan = p->pri->dialplan - 1; 02195 if (pridialplan == -2) { /* compute dynamically */ 02196 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 02197 dp_strip = strlen(p->pri->internationalprefix); 02198 pridialplan = PRI_INTERNATIONAL_ISDN; 02199 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 02200 dp_strip = strlen(p->pri->nationalprefix); 02201 pridialplan = PRI_NATIONAL_ISDN; 02202 } else { 02203 pridialplan = PRI_LOCAL_ISDN; 02204 } 02205 } 02206 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0); 02207 02208 ldp_strip = 0; 02209 prilocaldialplan = p->pri->localdialplan - 1; 02210 if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */ 02211 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 02212 ldp_strip = strlen(p->pri->internationalprefix); 02213 prilocaldialplan = PRI_INTERNATIONAL_ISDN; 02214 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 02215 ldp_strip = strlen(p->pri->nationalprefix); 02216 prilocaldialplan = PRI_NATIONAL_ISDN; 02217 } else { 02218 prilocaldialplan = PRI_LOCAL_ISDN; 02219 } 02220 } 02221 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan, 02222 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE)); 02223 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) { 02224 if (!strcasecmp(rr_str, "UNKNOWN")) 02225 redirect_reason = 0; 02226 else if (!strcasecmp(rr_str, "BUSY")) 02227 redirect_reason = 1; 02228 else if (!strcasecmp(rr_str, "NO_REPLY")) 02229 redirect_reason = 2; 02230 else if (!strcasecmp(rr_str, "UNCONDITIONAL")) 02231 redirect_reason = 15; 02232 else 02233 redirect_reason = PRI_REDIR_UNCONDITIONAL; 02234 } else 02235 redirect_reason = PRI_REDIR_UNCONDITIONAL; 02236 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason); 02237 02238 #ifdef SUPPORT_USERUSER 02239 /* User-user info */ 02240 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO"); 02241 02242 if (useruser) 02243 pri_sr_set_useruser(sr, useruser); 02244 #endif 02245 02246 if (pri_setup(p->pri->pri, p->call, sr)) { 02247 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 02248 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan)); 02249 pri_rel(p->pri); 02250 ast_mutex_unlock(&p->lock); 02251 pri_sr_free(sr); 02252 return -1; 02253 } 02254 pri_sr_free(sr); 02255 ast_setstate(ast, AST_STATE_DIALING); 02256 pri_rel(p->pri); 02257 } 02258 #endif 02259 ast_mutex_unlock(&p->lock); 02260 return 0; 02261 }
static int dahdi_callwait | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 1793 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().
01794 { 01795 struct dahdi_pvt *p = ast->tech_pvt; 01796 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 01797 if (p->cidspill) { 01798 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 01799 free(p->cidspill); 01800 } 01801 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 01802 return -1; 01803 save_conference(p); 01804 /* Silence */ 01805 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 01806 if (!p->callwaitrings && p->callwaitingcallerid) { 01807 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 01808 p->callwaitcas = 1; 01809 p->cidlen = 2400 + 680 + READ_SIZE * 4; 01810 } else { 01811 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 01812 p->callwaitcas = 0; 01813 p->cidlen = 2400 + READ_SIZE * 4; 01814 } 01815 p->cidpos = 0; 01816 send_callerid(p); 01817 01818 return 0; 01819 }
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 609 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().
00609 { 00610 /* recall that if a field is not included here it is initialized 00611 * to 0 or equivalent 00612 */ 00613 struct dahdi_chan_conf conf = { 00614 #ifdef HAVE_PRI 00615 .pri = { 00616 .nsf = PRI_NSF_NONE, 00617 .switchtype = PRI_SWITCH_NI2, 00618 .dialplan = PRI_NATIONAL_ISDN + 1, 00619 .localdialplan = PRI_NATIONAL_ISDN + 1, 00620 .nodetype = PRI_CPE, 00621 00622 .minunused = 2, 00623 .idleext = "", 00624 .idledial = "", 00625 .internationalprefix = "", 00626 .nationalprefix = "", 00627 .localprefix = "", 00628 .privateprefix = "", 00629 .unknownprefix = "", 00630 00631 .resetinterval = 3600 00632 }, 00633 #endif 00634 .chan = { 00635 .context = "default", 00636 .cid_num = "", 00637 .cid_name = "", 00638 .mohinterpret = "default", 00639 .mohsuggest = "", 00640 .transfertobusy = 1, 00641 00642 .cid_signalling = CID_SIG_BELL, 00643 .cid_start = CID_START_RING, 00644 .dahditrcallerid = 0, 00645 .use_callerid = 1, 00646 .sig = -1, 00647 .outsigmod = -1, 00648 00649 .tonezone = -1, 00650 00651 .echocancel = 1, 00652 00653 .busycount = 3, 00654 .busycompare = 0, 00655 .busytonelength = 0, 00656 .busyquietlength = 0, 00657 .busyfuzziness = 0, 00658 .silencethreshold = 0, 00659 00660 .accountcode = "", 00661 00662 .mailbox = "", 00663 00664 00665 .polarityonanswerdelay = 600, 00666 00667 .sendcalleridafter = DEFAULT_CIDRINGS, 00668 00669 .buf_policy = DAHDI_POLICY_IMMEDIATE, 00670 .buf_no = numbufs 00671 }, 00672 .timing = { 00673 .prewinktime = -1, 00674 .preflashtime = -1, 00675 .winktime = -1, 00676 .flashtime = -1, 00677 .starttime = -1, 00678 .rxwinktime = -1, 00679 .rxflashtime = -1, 00680 .debouncetime = -1 00681 }, 00682 .smdi_port = "/dev/ttyS0", 00683 }; 00684 00685 return conf; 00686 }
static void dahdi_close | ( | int | fd | ) | [static] |
Definition at line 953 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 966 of file chan_dahdi.c.
References dahdi_close(), and dahdi_pri::fds.
Referenced by __unload_module(), dahdi_restart(), and start_pri().
00967 { 00968 dahdi_close(pri->fds[fd_num]); 00969 pri->fds[fd_num] = -1; 00970 }
static void dahdi_close_sub | ( | struct dahdi_pvt * | chan_pvt, | |
int | sub_num | |||
) | [static] |
Definition at line 959 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().
00960 { 00961 dahdi_close(chan_pvt->subs[sub_num].dfd); 00962 chan_pvt->subs[sub_num].dfd = -1; 00963 }
static int dahdi_confmute | ( | struct dahdi_pvt * | p, | |
int | muted | |||
) | [inline, static] |
Definition at line 1676 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().
01677 { 01678 int x, y, res; 01679 x = muted; 01680 if (p->sig == SIG_PRI) { 01681 y = 1; 01682 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y); 01683 if (res) 01684 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno)); 01685 } 01686 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x); 01687 if (res < 0) 01688 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno)); 01689 return res; 01690 }
static int dahdi_destroy_channel | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 10049 of file chan_dahdi.c.
References dahdi_destroy_channel_bynum(), and RESULT_SHOWUSAGE.
10050 { 10051 int channel; 10052 10053 if (argc != 4) 10054 return RESULT_SHOWUSAGE; 10055 10056 channel = atoi(argv[3]); 10057 10058 return dahdi_destroy_channel_bynum(channel); 10059 }
static int dahdi_destroy_channel_bynum | ( | int | channel | ) | [static] |
Definition at line 6724 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().
06725 { 06726 struct dahdi_pvt *tmp = NULL; 06727 struct dahdi_pvt *prev = NULL; 06728 06729 tmp = iflist; 06730 while (tmp) { 06731 if (tmp->channel == channel) { 06732 int x = DAHDI_FLASH; 06733 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 */ 06734 destroy_channel(prev, tmp, 1); 06735 ast_module_unref(ast_module_info->self); 06736 return RESULT_SUCCESS; 06737 } 06738 prev = tmp; 06739 tmp = tmp->next; 06740 } 06741 return RESULT_FAILURE; 06742 }
static int dahdi_digit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 1050 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.
01051 { 01052 struct dahdi_pvt *pvt; 01053 int index; 01054 int dtmf = -1; 01055 01056 pvt = chan->tech_pvt; 01057 01058 ast_mutex_lock(&pvt->lock); 01059 01060 index = dahdi_get_index(chan, pvt, 0); 01061 01062 if ((index != SUB_REAL) || !pvt->owner) 01063 goto out; 01064 01065 #ifdef HAVE_PRI 01066 if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) { 01067 if (pvt->setup_ack) { 01068 if (!pri_grab(pvt, pvt->pri)) { 01069 pri_information(pvt->pri->pri, pvt->call, digit); 01070 pri_rel(pvt->pri); 01071 } else 01072 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span); 01073 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) { 01074 int res; 01075 ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit); 01076 res = strlen(pvt->dialdest); 01077 pvt->dialdest[res++] = digit; 01078 pvt->dialdest[res] = '\0'; 01079 } 01080 goto out; 01081 } 01082 #endif 01083 if ((dtmf = digit_to_dtmfindex(digit)) == -1) 01084 goto out; 01085 01086 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) { 01087 int res; 01088 struct dahdi_dialoperation zo = { 01089 .op = DAHDI_DIAL_OP_APPEND, 01090 .dialstr[0] = 'T', 01091 .dialstr[1] = digit, 01092 .dialstr[2] = 0, 01093 }; 01094 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo))) 01095 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno)); 01096 else 01097 pvt->dialing = 1; 01098 } else { 01099 ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit); 01100 pvt->dialing = 1; 01101 pvt->begindigit = digit; 01102 } 01103 01104 out: 01105 ast_mutex_unlock(&pvt->lock); 01106 01107 return 0; 01108 }
static int dahdi_digit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 1110 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.
01111 { 01112 struct dahdi_pvt *pvt; 01113 int res = 0; 01114 int index; 01115 int x; 01116 01117 pvt = chan->tech_pvt; 01118 01119 ast_mutex_lock(&pvt->lock); 01120 01121 index = dahdi_get_index(chan, pvt, 0); 01122 01123 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse) 01124 goto out; 01125 01126 #ifdef HAVE_PRI 01127 /* This means that the digit was already sent via PRI signalling */ 01128 if (pvt->sig == SIG_PRI && !pvt->begindigit) 01129 goto out; 01130 #endif 01131 01132 if (pvt->begindigit) { 01133 x = -1; 01134 ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit); 01135 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x); 01136 pvt->dialing = 0; 01137 pvt->begindigit = 0; 01138 } 01139 01140 out: 01141 ast_mutex_unlock(&pvt->lock); 01142 01143 return res; 01144 }
static void dahdi_disable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1507 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().
01508 { 01509 int x; 01510 int res; 01511 if (p->echocancel) { 01512 x = 0; 01513 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x); 01514 if (res) 01515 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno)); 01516 else if (option_debug) 01517 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel); 01518 } 01519 p->echocanon = 0; 01520 }
static void dahdi_enable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1457 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().
01458 { 01459 int x; 01460 int res; 01461 if (!p) 01462 return; 01463 if (p->echocanon) { 01464 ast_log(LOG_DEBUG, "Echo cancellation already on\n"); 01465 return; 01466 } 01467 if (p->digital) { 01468 ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n"); 01469 return; 01470 } 01471 if (p->echocancel) { 01472 if (p->sig == SIG_PRI) { 01473 x = 1; 01474 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x); 01475 if (res) 01476 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno)); 01477 } 01478 x = p->echocancel; 01479 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x); 01480 if (res) 01481 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno)); 01482 else { 01483 p->echocanon = 1; 01484 if (option_debug) 01485 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel); 01486 } 01487 } else if (option_debug) 01488 ast_log(LOG_DEBUG, "No echo cancellation requested\n"); 01489 }
static struct ast_frame * dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 4750 of file chan_dahdi.c.
References __dahdi_exception(), ast_mutex_lock(), ast_mutex_unlock(), f, dahdi_pvt::lock, and ast_channel::tech_pvt.
04751 { 04752 struct dahdi_pvt *p = ast->tech_pvt; 04753 struct ast_frame *f; 04754 ast_mutex_lock(&p->lock); 04755 f = __dahdi_exception(ast); 04756 ast_mutex_unlock(&p->lock); 04757 return f; 04758 }
static int dahdi_fake_event | ( | struct dahdi_pvt * | p, | |
int | mode | |||
) | [static] |
Definition at line 10577 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().
10578 { 10579 if (p) { 10580 switch (mode) { 10581 case TRANSFER: 10582 p->fake_event = DAHDI_EVENT_WINKFLASH; 10583 break; 10584 case HANGUP: 10585 p->fake_event = DAHDI_EVENT_ONHOOK; 10586 break; 10587 default: 10588 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name); 10589 } 10590 } 10591 return 0; 10592 }
static int dahdi_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 3537 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.
03538 { 03539 struct dahdi_pvt *p = newchan->tech_pvt; 03540 int x; 03541 ast_mutex_lock(&p->lock); 03542 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name); 03543 if (p->owner == oldchan) { 03544 p->owner = newchan; 03545 } 03546 for (x = 0; x < 3; x++) 03547 if (p->subs[x].owner == oldchan) { 03548 if (!x) 03549 dahdi_unlink(NULL, p, 0); 03550 p->subs[x].owner = newchan; 03551 } 03552 if (newchan->_state == AST_STATE_RINGING) 03553 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0); 03554 update_conf(p); 03555 ast_mutex_unlock(&p->lock); 03556 return 0; 03557 }
static int dahdi_func_read | ( | struct ast_channel * | chan, | |
char * | function, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 3109 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.
03110 { 03111 struct dahdi_pvt *p = chan->tech_pvt; 03112 03113 if (!strcasecmp(data, "rxgain")) { 03114 ast_mutex_lock(&p->lock); 03115 snprintf(buf, len, "%f", p->rxgain); 03116 ast_mutex_unlock(&p->lock); 03117 } else if (!strcasecmp(data, "txgain")) { 03118 ast_mutex_lock(&p->lock); 03119 snprintf(buf, len, "%f", p->txgain); 03120 ast_mutex_unlock(&p->lock); 03121 } else { 03122 ast_copy_string(buf, "", len); 03123 } 03124 return 0; 03125 }
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 802 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().
00803 { 00804 int res; 00805 if (p->subs[SUB_REAL].owner == ast) 00806 res = 0; 00807 else if (p->subs[SUB_CALLWAIT].owner == ast) 00808 res = 1; 00809 else if (p->subs[SUB_THREEWAY].owner == ast) 00810 res = 2; 00811 else { 00812 res = -1; 00813 if (!nullok) 00814 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n"); 00815 } 00816 return res; 00817 }
static void dahdi_handle_dtmfup | ( | struct ast_channel * | ast, | |
int | index, | |||
struct ast_frame ** | dest | |||
) | [static] |
Definition at line 3700 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().
03701 { 03702 struct dahdi_pvt *p = ast->tech_pvt; 03703 struct ast_frame *f = *dest; 03704 03705 if (option_debug) 03706 ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name); 03707 03708 if (p->confirmanswer) { 03709 if (option_debug) 03710 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name); 03711 /* Upon receiving a DTMF digit, consider this an answer confirmation instead 03712 of a DTMF digit */ 03713 p->subs[index].f.frametype = AST_FRAME_CONTROL; 03714 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 03715 *dest = &p->subs[index].f; 03716 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */ 03717 p->confirmanswer = 0; 03718 } else if (p->callwaitcas) { 03719 if ((f->subclass == 'A') || (f->subclass == 'D')) { 03720 if (option_debug) 03721 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n"); 03722 if (p->cidspill) 03723 free(p->cidspill); 03724 send_cwcidspill(p); 03725 } 03726 if ((f->subclass != 'm') && (f->subclass != 'u')) 03727 p->callwaitcas = 0; 03728 p->subs[index].f.frametype = AST_FRAME_NULL; 03729 p->subs[index].f.subclass = 0; 03730 *dest = &p->subs[index].f; 03731 } else if (f->subclass == 'f') { 03732 /* Fax tone -- Handle and return NULL */ 03733 if ((p->callprogress & 0x6) && !p->faxhandled) { 03734 p->faxhandled++; 03735 if (strcmp(ast->exten, "fax")) { 03736 const char *target_context = S_OR(ast->macrocontext, ast->context); 03737 03738 /* We need to unlock 'ast' here because ast_exists_extension has the 03739 * potential to start autoservice on the channel. Such action is prone 03740 * to deadlock. 03741 */ 03742 ast_mutex_unlock(&p->lock); 03743 ast_channel_unlock(ast); 03744 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) { 03745 ast_channel_lock(ast); 03746 ast_mutex_lock(&p->lock); 03747 if (option_verbose > 2) 03748 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name); 03749 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 03750 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 03751 if (ast_async_goto(ast, target_context, "fax", 1)) 03752 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 03753 } else { 03754 ast_channel_lock(ast); 03755 ast_mutex_lock(&p->lock); 03756 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 03757 } 03758 } else if (option_debug) 03759 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n"); 03760 } else if (option_debug) 03761 ast_log(LOG_DEBUG, "Fax already handled\n"); 03762 dahdi_confmute(p, 0); 03763 p->subs[index].f.frametype = AST_FRAME_NULL; 03764 p->subs[index].f.subclass = 0; 03765 *dest = &p->subs[index].f; 03766 } else if (f->subclass == 'm') { 03767 /* Confmute request */ 03768 dahdi_confmute(p, 1); 03769 p->subs[index].f.frametype = AST_FRAME_NULL; 03770 p->subs[index].f.subclass = 0; 03771 *dest = &p->subs[index].f; 03772 } else if (f->subclass == 'u') { 03773 /* Unmute */ 03774 dahdi_confmute(p, 0); 03775 p->subs[index].f.frametype = AST_FRAME_NULL; 03776 p->subs[index].f.subclass = 0; 03777 *dest = &p->subs[index].f; 03778 } else 03779 dahdi_confmute(p, 0); 03780 }
static struct ast_frame* dahdi_handle_event | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3802 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().
03803 { 03804 int res, x; 03805 int index, mysig; 03806 char *c; 03807 struct dahdi_pvt *p = ast->tech_pvt; 03808 pthread_t threadid; 03809 pthread_attr_t attr; 03810 struct ast_channel *chan; 03811 struct ast_frame *f; 03812 03813 index = dahdi_get_index(ast, p, 0); 03814 mysig = p->sig; 03815 if (p->outsigmod > -1) 03816 mysig = p->outsigmod; 03817 p->subs[index].f.frametype = AST_FRAME_NULL; 03818 p->subs[index].f.subclass = 0; 03819 p->subs[index].f.datalen = 0; 03820 p->subs[index].f.samples = 0; 03821 p->subs[index].f.mallocd = 0; 03822 p->subs[index].f.offset = 0; 03823 p->subs[index].f.src = "dahdi_handle_event"; 03824 p->subs[index].f.data = NULL; 03825 f = &p->subs[index].f; 03826 03827 if (index < 0) 03828 return &p->subs[index].f; 03829 if (p->fake_event) { 03830 res = p->fake_event; 03831 p->fake_event = 0; 03832 } else 03833 res = dahdi_get_event(p->subs[index].dfd); 03834 03835 if (option_debug) 03836 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index); 03837 03838 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) { 03839 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0; 03840 03841 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff); 03842 #ifdef HAVE_PRI 03843 if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) { 03844 /* absorb event */ 03845 } else { 03846 #endif 03847 p->subs[index].f.frametype = AST_FRAME_DTMF_END; 03848 p->subs[index].f.subclass = res & 0xff; 03849 #ifdef HAVE_PRI 03850 } 03851 #endif 03852 dahdi_handle_dtmfup(ast, index, &f); 03853 return f; 03854 } 03855 03856 if (res & DAHDI_EVENT_DTMFDOWN) { 03857 if (option_debug) 03858 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff); 03859 /* Mute conference */ 03860 dahdi_confmute(p, 1); 03861 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN; 03862 p->subs[index].f.subclass = res & 0xff; 03863 return &p->subs[index].f; 03864 } 03865 03866 switch (res) { 03867 #ifdef DAHDI_EVENT_EC_DISABLED 03868 case DAHDI_EVENT_EC_DISABLED: 03869 if (option_verbose > 2) 03870 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel); 03871 p->echocanon = 0; 03872 break; 03873 #endif 03874 case DAHDI_EVENT_BITSCHANGED: 03875 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig)); 03876 case DAHDI_EVENT_PULSE_START: 03877 /* Stop tone if there's a pulse start and the PBX isn't started */ 03878 if (!ast->pbx) 03879 tone_zone_play_tone(p->subs[index].dfd, -1); 03880 break; 03881 case DAHDI_EVENT_DIALCOMPLETE: 03882 if (p->inalarm) break; 03883 if ((p->radio || (p->oprmode < 0))) break; 03884 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) { 03885 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno)); 03886 return NULL; 03887 } 03888 if (!x) { /* if not still dialing in driver */ 03889 dahdi_enable_ec(p); 03890 if (p->echobreak) { 03891 dahdi_train_ec(p); 03892 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); 03893 p->dop.op = DAHDI_DIAL_OP_REPLACE; 03894 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 03895 p->echobreak = 0; 03896 } else { 03897 p->dialing = 0; 03898 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) { 03899 /* if thru with dialing after offhook */ 03900 if (ast->_state == AST_STATE_DIALING_OFFHOOK) { 03901 ast_setstate(ast, AST_STATE_UP); 03902 p->subs[index].f.frametype = AST_FRAME_CONTROL; 03903 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 03904 break; 03905 } else { /* if to state wait for offhook to dial rest */ 03906 /* we now wait for off hook */ 03907 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK); 03908 } 03909 } 03910 if (ast->_state == AST_STATE_DIALING) { 03911 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 03912 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n"); 03913 } 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)))) { 03914 ast_setstate(ast, AST_STATE_RINGING); 03915 } else if (!p->answeronpolarityswitch) { 03916 ast_setstate(ast, AST_STATE_UP); 03917 p->subs[index].f.frametype = AST_FRAME_CONTROL; 03918 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 03919 /* If aops=0 and hops=1, this is necessary */ 03920 p->polarity = POLARITY_REV; 03921 } else { 03922 /* Start clean, so we can catch the change to REV polarity when party answers */ 03923 p->polarity = POLARITY_IDLE; 03924 } 03925 } 03926 } 03927 } 03928 break; 03929 case DAHDI_EVENT_ALARM: 03930 #ifdef HAVE_PRI 03931 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) { 03932 /* T309 is not enabled : hangup calls when alarm occurs */ 03933 if (p->call) { 03934 if (p->pri && p->pri->pri) { 03935 if (!pri_grab(p, p->pri)) { 03936 pri_hangup(p->pri->pri, p->call, -1); 03937 pri_destroycall(p->pri->pri, p->call); 03938 p->call = NULL; 03939 pri_rel(p->pri); 03940 } else 03941 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 03942 } else 03943 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n"); 03944 } 03945 if (p->owner) 03946 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 03947 } 03948 if (p->bearer) 03949 p->bearer->inalarm = 1; 03950 else 03951 #endif 03952 p->inalarm = 1; 03953 res = get_alarms(p); 03954 handle_alarms(p, res); 03955 #ifdef HAVE_LIBPRI 03956 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 03957 /* fall through intentionally */ 03958 } else { 03959 break; 03960 } 03961 #endif 03962 case DAHDI_EVENT_ONHOOK: 03963 if (p->radio) { 03964 p->subs[index].f.frametype = AST_FRAME_CONTROL; 03965 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY; 03966 break; 03967 } 03968 if (p->oprmode < 0) 03969 { 03970 if (p->oprmode != -1) break; 03971 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 03972 { 03973 /* Make sure it starts ringing */ 03974 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 03975 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING); 03976 save_conference(p->oprpeer); 03977 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 03978 } 03979 break; 03980 } 03981 switch (p->sig) { 03982 case SIG_FXOLS: 03983 case SIG_FXOGS: 03984 case SIG_FXOKS: 03985 p->onhooktime = time(NULL); 03986 p->msgstate = -1; 03987 /* Check for some special conditions regarding call waiting */ 03988 if (index == SUB_REAL) { 03989 /* The normal line was hung up */ 03990 if (p->subs[SUB_CALLWAIT].owner) { 03991 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */ 03992 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03993 if (option_verbose > 2) 03994 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel); 03995 unalloc_sub(p, SUB_CALLWAIT); 03996 #if 0 03997 p->subs[index].needanswer = 0; 03998 p->subs[index].needringing = 0; 03999 #endif 04000 p->callwaitingrepeat = 0; 04001 p->cidcwexpire = 0; 04002 p->owner = NULL; 04003 /* Don't start streaming audio yet if the incoming call isn't up yet */ 04004 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP) 04005 p->dialing = 1; 04006 dahdi_ring_phone(p); 04007 } else if (p->subs[SUB_THREEWAY].owner) { 04008 unsigned int mssinceflash; 04009 /* Here we have to retain the lock on both the main channel, the 3-way channel, and 04010 the private structure -- not especially easy or clean */ 04011 while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) { 04012 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */ 04013 ast_mutex_unlock(&p->lock); 04014 DEADLOCK_AVOIDANCE(&ast->lock); 04015 /* We can grab ast and p in that order, without worry. We should make sure 04016 nothing seriously bad has happened though like some sort of bizarre double 04017 masquerade! */ 04018 ast_mutex_lock(&p->lock); 04019 if (p->owner != ast) { 04020 ast_log(LOG_WARNING, "This isn't good...\n"); 04021 return NULL; 04022 } 04023 } 04024 if (!p->subs[SUB_THREEWAY].owner) { 04025 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n"); 04026 return NULL; 04027 } 04028 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime); 04029 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash); 04030 if (mssinceflash < MIN_MS_SINCE_FLASH) { 04031 /* It hasn't been long enough since the last flashook. This is probably a bounce on 04032 hanging up. Hangup both channels now */ 04033 if (p->subs[SUB_THREEWAY].owner) 04034 ast_queue_hangup(p->subs[SUB_THREEWAY].owner); 04035 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04036 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel); 04037 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04038 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) { 04039 if (p->transfer) { 04040 /* In any case this isn't a threeway call anymore */ 04041 p->subs[SUB_REAL].inthreeway = 0; 04042 p->subs[SUB_THREEWAY].inthreeway = 0; 04043 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */ 04044 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) { 04045 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04046 /* Swap subs and dis-own channel */ 04047 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04048 p->owner = NULL; 04049 /* Ring the phone */ 04050 dahdi_ring_phone(p); 04051 } else { 04052 if ((res = attempt_transfer(p)) < 0) { 04053 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04054 if (p->subs[SUB_THREEWAY].owner) 04055 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04056 } else if (res) { 04057 /* Don't actually hang up at this point */ 04058 if (p->subs[SUB_THREEWAY].owner) 04059 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04060 break; 04061 } 04062 } 04063 } else { 04064 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04065 if (p->subs[SUB_THREEWAY].owner) 04066 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04067 } 04068 } else { 04069 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04070 /* Swap subs and dis-own channel */ 04071 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04072 p->owner = NULL; 04073 /* Ring the phone */ 04074 dahdi_ring_phone(p); 04075 } 04076 } 04077 } else { 04078 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index); 04079 } 04080 /* Fall through */ 04081 default: 04082 dahdi_disable_ec(p); 04083 return NULL; 04084 } 04085 break; 04086 case DAHDI_EVENT_RINGOFFHOOK: 04087 if (p->inalarm) break; 04088 if (p->oprmode < 0) 04089 { 04090 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 04091 { 04092 /* Make sure it stops ringing */ 04093 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 04094 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1); 04095 restore_conference(p->oprpeer); 04096 } 04097 break; 04098 } 04099 if (p->radio) 04100 { 04101 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04102 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY; 04103 break; 04104 } 04105 /* for E911, its supposed to wait for offhook then dial 04106 the second half of the dial string */ 04107 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) { 04108 c = strchr(p->dialdest, '/'); 04109 if (c) 04110 c++; 04111 else 04112 c = p->dialdest; 04113 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c); 04114 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr)); 04115 if (strlen(p->dop.dialstr) > 4) { 04116 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 04117 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 04118 p->echorest[sizeof(p->echorest) - 1] = '\0'; 04119 p->echobreak = 1; 04120 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 04121 } else 04122 p->echobreak = 0; 04123 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 04124 int saveerr = errno; 04125 04126 x = DAHDI_ONHOOK; 04127 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04128 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 04129 return NULL; 04130 } 04131 p->dialing = 1; 04132 return &p->subs[index].f; 04133 } 04134 switch (p->sig) { 04135 case SIG_FXOLS: 04136 case SIG_FXOGS: 04137 case SIG_FXOKS: 04138 switch (ast->_state) { 04139 case AST_STATE_RINGING: 04140 dahdi_enable_ec(p); 04141 dahdi_train_ec(p); 04142 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04143 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 04144 /* Make sure it stops ringing */ 04145 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 04146 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel); 04147 if (p->cidspill) { 04148 /* Cancel any running CallerID spill */ 04149 free(p->cidspill); 04150 p->cidspill = NULL; 04151 } 04152 p->dialing = 0; 04153 p->callwaitcas = 0; 04154 if (p->confirmanswer) { 04155 /* Ignore answer if "confirm answer" is enabled */ 04156 p->subs[index].f.frametype = AST_FRAME_NULL; 04157 p->subs[index].f.subclass = 0; 04158 } else if (!ast_strlen_zero(p->dop.dialstr)) { 04159 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ 04160 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 04161 if (res < 0) { 04162 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 04163 p->dop.dialstr[0] = '\0'; 04164 return NULL; 04165 } else { 04166 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr); 04167 p->subs[index].f.frametype = AST_FRAME_NULL; 04168 p->subs[index].f.subclass = 0; 04169 p->dialing = 1; 04170 } 04171 p->dop.dialstr[0] = '\0'; 04172 ast_setstate(ast, AST_STATE_DIALING); 04173 } else 04174 ast_setstate(ast, AST_STATE_UP); 04175 return &p->subs[index].f; 04176 case AST_STATE_DOWN: 04177 ast_setstate(ast, AST_STATE_RING); 04178 ast->rings = 1; 04179 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04180 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK; 04181 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel); 04182 return &p->subs[index].f; 04183 case AST_STATE_UP: 04184 /* Make sure it stops ringing */ 04185 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 04186 /* Okay -- probably call waiting*/ 04187 if (ast_bridged_channel(p->owner)) 04188 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 04189 p->subs[index].needunhold = 1; 04190 break; 04191 case AST_STATE_RESERVED: 04192 /* Start up dialtone */ 04193 if (has_voicemail(p)) 04194 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 04195 else 04196 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 04197 break; 04198 default: 04199 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state); 04200 } 04201 break; 04202 case SIG_FXSLS: 04203 case SIG_FXSGS: 04204 case SIG_FXSKS: 04205 if (ast->_state == AST_STATE_RING) { 04206 p->ringt = p->ringt_base; 04207 } 04208 04209 /* Fall through */ 04210 case SIG_EM: 04211 case SIG_EM_E1: 04212 case SIG_EMWINK: 04213 case SIG_FEATD: 04214 case SIG_FEATDMF: 04215 case SIG_FEATDMF_TA: 04216 case SIG_E911: 04217 case SIG_FGC_CAMA: 04218 case SIG_FGC_CAMAMF: 04219 case SIG_FEATB: 04220 case SIG_SF: 04221 case SIG_SFWINK: 04222 case SIG_SF_FEATD: 04223 case SIG_SF_FEATDMF: 04224 case SIG_SF_FEATB: 04225 if (ast->_state == AST_STATE_PRERING) 04226 ast_setstate(ast, AST_STATE_RING); 04227 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) { 04228 if (option_debug) 04229 ast_log(LOG_DEBUG, "Ring detected\n"); 04230 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04231 p->subs[index].f.subclass = AST_CONTROL_RING; 04232 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) { 04233 if (option_debug) 04234 ast_log(LOG_DEBUG, "Line answered\n"); 04235 if (p->confirmanswer) { 04236 p->subs[index].f.frametype = AST_FRAME_NULL; 04237 p->subs[index].f.subclass = 0; 04238 } else { 04239 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04240 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 04241 ast_setstate(ast, AST_STATE_UP); 04242 } 04243 } else if (ast->_state != AST_STATE_RING) 04244 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel); 04245 break; 04246 default: 04247 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 04248 } 04249 break; 04250 #ifdef DAHDI_EVENT_RINGBEGIN 04251 case DAHDI_EVENT_RINGBEGIN: 04252 switch (p->sig) { 04253 case SIG_FXSLS: 04254 case SIG_FXSGS: 04255 case SIG_FXSKS: 04256 if (ast->_state == AST_STATE_RING) { 04257 p->ringt = p->ringt_base; 04258 } 04259 break; 04260 } 04261 break; 04262 #endif 04263 case DAHDI_EVENT_RINGEROFF: 04264 if (p->inalarm) break; 04265 if ((p->radio || (p->oprmode < 0))) break; 04266 ast->rings++; 04267 if ((ast->rings > p->cidrings) && (p->cidspill)) { 04268 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n"); 04269 free(p->cidspill); 04270 p->cidspill = NULL; 04271 p->callwaitcas = 0; 04272 } 04273 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04274 p->subs[index].f.subclass = AST_CONTROL_RINGING; 04275 break; 04276 case DAHDI_EVENT_RINGERON: 04277 break; 04278 case DAHDI_EVENT_NOALARM: 04279 p->inalarm = 0; 04280 #ifdef HAVE_PRI 04281 /* Extremely unlikely but just in case */ 04282 if (p->bearer) 04283 p->bearer->inalarm = 0; 04284 #endif 04285 if (!p->unknown_alarm) { 04286 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 04287 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 04288 "Channel: %d\r\n", p->channel); 04289 } else { 04290 p->unknown_alarm = 0; 04291 } 04292 break; 04293 case DAHDI_EVENT_WINKFLASH: 04294 if (p->inalarm) break; 04295 if (p->radio) break; 04296 if (p->oprmode < 0) break; 04297 if (p->oprmode > 1) 04298 { 04299 struct dahdi_params par; 04300 04301 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1) 04302 { 04303 if (!par.rxisoffhook) 04304 { 04305 /* Make sure it stops ringing */ 04306 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 04307 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING); 04308 save_conference(p); 04309 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04310 } 04311 } 04312 break; 04313 } 04314 /* Remember last time we got a flash-hook */ 04315 gettimeofday(&p->flashtime, NULL); 04316 switch (mysig) { 04317 case SIG_FXOLS: 04318 case SIG_FXOGS: 04319 case SIG_FXOKS: 04320 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n", 04321 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 04322 p->callwaitcas = 0; 04323 04324 if (index != SUB_REAL) { 04325 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel); 04326 goto winkflashdone; 04327 } 04328 04329 if (p->subs[SUB_CALLWAIT].owner) { 04330 /* Swap to call-wait */ 04331 swap_subs(p, SUB_REAL, SUB_CALLWAIT); 04332 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 04333 p->owner = p->subs[SUB_REAL].owner; 04334 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name); 04335 if (p->owner->_state == AST_STATE_RINGING) { 04336 ast_setstate(p->owner, AST_STATE_UP); 04337 p->subs[SUB_REAL].needanswer = 1; 04338 } 04339 p->callwaitingrepeat = 0; 04340 p->cidcwexpire = 0; 04341 /* Start music on hold if appropriate */ 04342 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 04343 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 04344 S_OR(p->mohsuggest, NULL), 04345 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 04346 } 04347 p->subs[SUB_CALLWAIT].needhold = 1; 04348 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 04349 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD, 04350 S_OR(p->mohsuggest, NULL), 04351 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 04352 } 04353 p->subs[SUB_REAL].needunhold = 1; 04354 } else if (!p->subs[SUB_THREEWAY].owner) { 04355 char cid_num[256]; 04356 char cid_name[256]; 04357 04358 if (!p->threewaycalling) { 04359 /* Just send a flash if no 3-way calling */ 04360 p->subs[SUB_REAL].needflash = 1; 04361 goto winkflashdone; 04362 } else if (!check_for_conference(p)) { 04363 if (p->dahditrcallerid && p->owner) { 04364 if (p->owner->cid.cid_num) 04365 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num)); 04366 if (p->owner->cid.cid_name) 04367 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name)); 04368 } 04369 /* XXX This section needs much more error checking!!! XXX */ 04370 /* Start a 3-way call if feasible */ 04371 if (!((ast->pbx) || 04372 (ast->_state == AST_STATE_UP) || 04373 (ast->_state == AST_STATE_RING))) { 04374 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n"); 04375 goto winkflashdone; 04376 } 04377 if (alloc_sub(p, SUB_THREEWAY)) { 04378 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n"); 04379 goto winkflashdone; 04380 } 04381 /* Make new channel */ 04382 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0); 04383 if (p->dahditrcallerid) { 04384 if (!p->origcid_num) 04385 p->origcid_num = ast_strdup(p->cid_num); 04386 if (!p->origcid_name) 04387 p->origcid_name = ast_strdup(p->cid_name); 04388 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num)); 04389 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name)); 04390 } 04391 /* Swap things around between the three-way and real call */ 04392 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04393 /* Disable echo canceller for better dialing */ 04394 dahdi_disable_ec(p); 04395 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL); 04396 if (res) 04397 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel); 04398 p->owner = chan; 04399 pthread_attr_init(&attr); 04400 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 04401 if (!chan) { 04402 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel); 04403 } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 04404 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel); 04405 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 04406 dahdi_enable_ec(p); 04407 ast_hangup(chan); 04408 } else { 04409 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 04410 int way3bridge = 0, cdr3way = 0; 04411 04412 if (!other) { 04413 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 04414 } else 04415 way3bridge = 1; 04416 04417 if (p->subs[SUB_THREEWAY].owner->cdr) 04418 cdr3way = 1; 04419 04420 if (option_verbose > 2) 04421 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel); 04422 /* Start music on hold if appropriate */ 04423 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 04424 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 04425 S_OR(p->mohsuggest, NULL), 04426 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 04427 } 04428 p->subs[SUB_THREEWAY].needhold = 1; 04429 } 04430 pthread_attr_destroy(&attr); 04431 } 04432 } else { 04433 /* Already have a 3 way call */ 04434 if (p->subs[SUB_THREEWAY].inthreeway) { 04435 /* Call is already up, drop the last person */ 04436 if (option_debug) 04437 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel); 04438 /* If the primary call isn't answered yet, use it */ 04439 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) { 04440 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/ 04441 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04442 p->owner = p->subs[SUB_REAL].owner; 04443 } 04444 /* Drop the last call and stop the conference */ 04445 if (option_verbose > 2) 04446 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name); 04447 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04448 p->subs[SUB_REAL].inthreeway = 0; 04449 p->subs[SUB_THREEWAY].inthreeway = 0; 04450 } else { 04451 /* Lets see what we're up to */ 04452 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 04453 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) { 04454 int otherindex = SUB_THREEWAY; 04455 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 04456 int way3bridge = 0, cdr3way = 0; 04457 04458 if (!other) { 04459 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 04460 } else 04461 way3bridge = 1; 04462 04463 if (p->subs[SUB_THREEWAY].owner->cdr) 04464 cdr3way = 1; 04465 04466 if (option_verbose > 2) 04467 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); 04468 /* Put them in the threeway, and flip */ 04469 p->subs[SUB_THREEWAY].inthreeway = 1; 04470 p->subs[SUB_REAL].inthreeway = 1; 04471 if (ast->_state == AST_STATE_UP) { 04472 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04473 otherindex = SUB_REAL; 04474 } 04475 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner)) 04476 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD); 04477 p->subs[otherindex].needunhold = 1; 04478 p->owner = p->subs[SUB_REAL].owner; 04479 if (ast->_state == AST_STATE_RINGING) { 04480 ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n"); 04481 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04482 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 04483 } 04484 } else { 04485 if (option_verbose > 2) 04486 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name); 04487 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04488 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04489 p->owner = p->subs[SUB_REAL].owner; 04490 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner)) 04491 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 04492 p->subs[SUB_REAL].needunhold = 1; 04493 dahdi_enable_ec(p); 04494 } 04495 04496 } 04497 } 04498 winkflashdone: 04499 update_conf(p); 04500 break; 04501 case SIG_EM: 04502 case SIG_EM_E1: 04503 case SIG_EMWINK: 04504 case SIG_FEATD: 04505 case SIG_SF: 04506 case SIG_SFWINK: 04507 case SIG_SF_FEATD: 04508 case SIG_FXSLS: 04509 case SIG_FXSGS: 04510 if (p->dialing) 04511 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel); 04512 else 04513 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel); 04514 break; 04515 case SIG_FEATDMF_TA: 04516 switch (p->whichwink) { 04517 case 0: 04518 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 04519 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 04520 break; 04521 case 1: 04522 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr)); 04523 break; 04524 case 2: 04525 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n"); 04526 return NULL; 04527 } 04528 p->whichwink++; 04529 /* Fall through */ 04530 case SIG_FEATDMF: 04531 case SIG_E911: 04532 case SIG_FGC_CAMAMF: 04533 case SIG_FGC_CAMA: 04534 case SIG_FEATB: 04535 case SIG_SF_FEATDMF: 04536 case SIG_SF_FEATB: 04537 /* FGD MF *Must* wait for wink */ 04538 if (!ast_strlen_zero(p->dop.dialstr)) { 04539 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 04540 if (res < 0) { 04541 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 04542 p->dop.dialstr[0] = '\0'; 04543 return NULL; 04544 } else 04545 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); 04546 } 04547 p->dop.dialstr[0] = '\0'; 04548 break; 04549 default: 04550 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig); 04551 } 04552 break; 04553 case DAHDI_EVENT_HOOKCOMPLETE: 04554 if (p->inalarm) break; 04555 if ((p->radio || (p->oprmode < 0))) break; 04556 switch (mysig) { 04557 case SIG_FXSLS: /* only interesting for FXS */ 04558 case SIG_FXSGS: 04559 case SIG_FXSKS: 04560 case SIG_EM: 04561 case SIG_EM_E1: 04562 case SIG_EMWINK: 04563 case SIG_FEATD: 04564 case SIG_SF: 04565 case SIG_SFWINK: 04566 case SIG_SF_FEATD: 04567 if (!ast_strlen_zero(p->dop.dialstr)) { 04568 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 04569 if (res < 0) { 04570 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 04571 p->dop.dialstr[0] = '\0'; 04572 return NULL; 04573 } else 04574 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); 04575 } 04576 p->dop.dialstr[0] = '\0'; 04577 p->dop.op = DAHDI_DIAL_OP_REPLACE; 04578 break; 04579 case SIG_FEATDMF: 04580 case SIG_FEATDMF_TA: 04581 case SIG_E911: 04582 case SIG_FGC_CAMA: 04583 case SIG_FGC_CAMAMF: 04584 case SIG_FEATB: 04585 case SIG_SF_FEATDMF: 04586 case SIG_SF_FEATB: 04587 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel); 04588 break; 04589 default: 04590 break; 04591 } 04592 break; 04593 case DAHDI_EVENT_POLARITY: 04594 /* 04595 * If we get a Polarity Switch event, check to see 04596 * if we should change the polarity state and 04597 * mark the channel as UP or if this is an indication 04598 * of remote end disconnect. 04599 */ 04600 if (p->polarity == POLARITY_IDLE) { 04601 p->polarity = POLARITY_REV; 04602 if (p->answeronpolarityswitch && 04603 ((ast->_state == AST_STATE_DIALING) || 04604 (ast->_state == AST_STATE_RINGING))) { 04605 ast_log(LOG_DEBUG, "Answering on polarity switch!\n"); 04606 ast_setstate(p->owner, AST_STATE_UP); 04607 if (p->hanguponpolarityswitch) { 04608 gettimeofday(&p->polaritydelaytv, NULL); 04609 } 04610 } else 04611 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state); 04612 } 04613 /* Removed else statement from here as it was preventing hangups from ever happening*/ 04614 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */ 04615 if (p->hanguponpolarityswitch && 04616 (p->polarityonanswerdelay > 0) && 04617 (p->polarity == POLARITY_REV) && 04618 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) { 04619 /* Added log_debug information below to provide a better indication of what is going on */ 04620 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) ); 04621 04622 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) { 04623 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel); 04624 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 04625 p->polarity = POLARITY_IDLE; 04626 } else { 04627 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); 04628 } 04629 } else { 04630 p->polarity = POLARITY_IDLE; 04631 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state); 04632 } 04633 /* Added more log_debug information below to provide a better indication of what is going on */ 04634 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) ); 04635 break; 04636 default: 04637 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel); 04638 } 04639 return &p->subs[index].f; 04640 }
static int dahdi_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 2505 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().
02506 { 02507 int res; 02508 int index,x, law; 02509 /*static int restore_gains(struct dahdi_pvt *p);*/ 02510 struct dahdi_pvt *p = ast->tech_pvt; 02511 struct dahdi_pvt *tmp = NULL; 02512 struct dahdi_pvt *prev = NULL; 02513 struct dahdi_params par; 02514 02515 if (option_debug) 02516 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name); 02517 if (!ast->tech_pvt) { 02518 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 02519 return 0; 02520 } 02521 02522 ast_mutex_lock(&p->lock); 02523 02524 index = dahdi_get_index(ast, p, 1); 02525 02526 if (p->sig == SIG_PRI) { 02527 x = 1; 02528 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 02529 } 02530 02531 x = 0; 02532 dahdi_confmute(p, 0); 02533 restore_gains(p); 02534 if (p->origcid_num) { 02535 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num)); 02536 free(p->origcid_num); 02537 p->origcid_num = NULL; 02538 } 02539 if (p->origcid_name) { 02540 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name)); 02541 free(p->origcid_name); 02542 p->origcid_name = NULL; 02543 } 02544 if (p->dsp) 02545 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 02546 if (p->exten) 02547 p->exten[0] = '\0'; 02548 02549 if (option_debug) 02550 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n", 02551 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 02552 p->ignoredtmf = 0; 02553 02554 if (index > -1) { 02555 /* Real channel, do some fixup */ 02556 p->subs[index].owner = NULL; 02557 p->subs[index].needanswer = 0; 02558 p->subs[index].needflash = 0; 02559 p->subs[index].needringing = 0; 02560 p->subs[index].needbusy = 0; 02561 p->subs[index].needcongestion = 0; 02562 p->subs[index].linear = 0; 02563 p->subs[index].needcallerid = 0; 02564 p->polarity = POLARITY_IDLE; 02565 dahdi_setlinear(p->subs[index].dfd, 0); 02566 if (index == SUB_REAL) { 02567 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) { 02568 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n"); 02569 if (p->subs[SUB_CALLWAIT].inthreeway) { 02570 /* We had flipped over to answer a callwait and now it's gone */ 02571 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n"); 02572 /* Move to the call-wait, but un-own us until they flip back. */ 02573 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 02574 unalloc_sub(p, SUB_CALLWAIT); 02575 p->owner = NULL; 02576 } else { 02577 /* The three way hung up, but we still have a call wait */ 02578 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n"); 02579 swap_subs(p, SUB_THREEWAY, SUB_REAL); 02580 unalloc_sub(p, SUB_THREEWAY); 02581 if (p->subs[SUB_REAL].inthreeway) { 02582 /* This was part of a three way call. Immediately make way for 02583 another call */ 02584 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n"); 02585 p->owner = p->subs[SUB_REAL].owner; 02586 } else { 02587 /* This call hasn't been completed yet... Set owner to NULL */ 02588 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n"); 02589 p->owner = NULL; 02590 } 02591 p->subs[SUB_REAL].inthreeway = 0; 02592 } 02593 } else if (p->subs[SUB_CALLWAIT].dfd > -1) { 02594 /* Move to the call-wait and switch back to them. */ 02595 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 02596 unalloc_sub(p, SUB_CALLWAIT); 02597 p->owner = p->subs[SUB_REAL].owner; 02598 if (p->owner->_state != AST_STATE_UP) 02599 p->subs[SUB_REAL].needanswer = 1; 02600 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 02601 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 02602 } else if (p->subs[SUB_THREEWAY].dfd > -1) { 02603 swap_subs(p, SUB_THREEWAY, SUB_REAL); 02604 unalloc_sub(p, SUB_THREEWAY); 02605 if (p->subs[SUB_REAL].inthreeway) { 02606 /* This was part of a three way call. Immediately make way for 02607 another call */ 02608 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n"); 02609 p->owner = p->subs[SUB_REAL].owner; 02610 } else { 02611 /* This call hasn't been completed yet... Set owner to NULL */ 02612 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n"); 02613 p->owner = NULL; 02614 } 02615 p->subs[SUB_REAL].inthreeway = 0; 02616 } 02617 } else if (index == SUB_CALLWAIT) { 02618 /* Ditch the holding callwait call, and immediately make it availabe */ 02619 if (p->subs[SUB_CALLWAIT].inthreeway) { 02620 /* This is actually part of a three way, placed on hold. Place the third part 02621 on music on hold now */ 02622 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 02623 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 02624 S_OR(p->mohsuggest, NULL), 02625 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 02626 } 02627 p->subs[SUB_THREEWAY].inthreeway = 0; 02628 /* Make it the call wait now */ 02629 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 02630 unalloc_sub(p, SUB_THREEWAY); 02631 } else 02632 unalloc_sub(p, SUB_CALLWAIT); 02633 } else if (index == SUB_THREEWAY) { 02634 if (p->subs[SUB_CALLWAIT].inthreeway) { 02635 /* The other party of the three way call is currently in a call-wait state. 02636 Start music on hold for them, and take the main guy out of the third call */ 02637 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 02638 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 02639 S_OR(p->mohsuggest, NULL), 02640 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 02641 } 02642 p->subs[SUB_CALLWAIT].inthreeway = 0; 02643 } 02644 p->subs[SUB_REAL].inthreeway = 0; 02645 /* If this was part of a three way call index, let us make 02646 another three way call */ 02647 unalloc_sub(p, SUB_THREEWAY); 02648 } else { 02649 /* This wasn't any sort of call, but how are we an index? */ 02650 ast_log(LOG_WARNING, "Index found but not any type of call?\n"); 02651 } 02652 } 02653 02654 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 02655 p->owner = NULL; 02656 p->ringt = 0; 02657 p->distinctivering = 0; 02658 p->confirmanswer = 0; 02659 p->cidrings = 1; 02660 p->outgoing = 0; 02661 p->digital = 0; 02662 p->faxhandled = 0; 02663 p->pulsedial = 0; 02664 p->onhooktime = time(NULL); 02665 #ifdef HAVE_PRI 02666 p->proceeding = 0; 02667 p->progress = 0; 02668 p->alerting = 0; 02669 p->setup_ack = 0; 02670 #endif 02671 if (p->dsp) { 02672 ast_dsp_free(p->dsp); 02673 p->dsp = NULL; 02674 } 02675 02676 law = DAHDI_LAW_DEFAULT; 02677 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 02678 if (res < 0) 02679 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 02680 /* Perform low level hangup if no owner left */ 02681 #ifdef HAVE_PRI 02682 if (p->pri) { 02683 #ifdef SUPPORT_USERUSER 02684 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO"); 02685 #endif 02686 02687 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */ 02688 if (p->call && (!p->bearer || (p->bearer->call == p->call))) { 02689 if (!pri_grab(p, p->pri)) { 02690 if (p->alreadyhungup) { 02691 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n"); 02692 02693 #ifdef SUPPORT_USERUSER 02694 pri_call_set_useruser(p->call, useruser); 02695 #endif 02696 02697 pri_hangup(p->pri->pri, p->call, -1); 02698 p->call = NULL; 02699 if (p->bearer) 02700 p->bearer->call = NULL; 02701 } else { 02702 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE"); 02703 int icause = ast->hangupcause ? ast->hangupcause : -1; 02704 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n"); 02705 02706 #ifdef SUPPORT_USERUSER 02707 pri_call_set_useruser(p->call, useruser); 02708 #endif 02709 02710 p->alreadyhungup = 1; 02711 if (p->bearer) 02712 p->bearer->alreadyhungup = 1; 02713 if (cause) { 02714 if (atoi(cause)) 02715 icause = atoi(cause); 02716 } 02717 pri_hangup(p->pri->pri, p->call, icause); 02718 } 02719 if (res < 0) 02720 ast_log(LOG_WARNING, "pri_disconnect failed\n"); 02721 pri_rel(p->pri); 02722 } else { 02723 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 02724 res = -1; 02725 } 02726 } else { 02727 if (p->bearer) 02728 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call); 02729 p->call = NULL; 02730 res = 0; 02731 } 02732 } 02733 #endif 02734 if (p->sig && (p->sig != SIG_PRI)) 02735 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 02736 if (res < 0) { 02737 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name); 02738 } 02739 switch (p->sig) { 02740 case SIG_FXOGS: 02741 case SIG_FXOLS: 02742 case SIG_FXOKS: 02743 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 02744 if (!res) { 02745 #if 0 02746 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook); 02747 #endif 02748 /* If they're off hook, try playing congestion */ 02749 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0)))) 02750 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 02751 else 02752 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 02753 } 02754 break; 02755 case SIG_FXSGS: 02756 case SIG_FXSLS: 02757 case SIG_FXSKS: 02758 /* Make sure we're not made available for at least two seconds assuming 02759 we were actually used for an inbound or outbound call. */ 02760 if (ast->_state != AST_STATE_RESERVED) { 02761 time(&p->guardtime); 02762 p->guardtime += 2; 02763 } 02764 break; 02765 default: 02766 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 02767 } 02768 if (p->cidspill) 02769 free(p->cidspill); 02770 if (p->sig) 02771 dahdi_disable_ec(p); 02772 x = 0; 02773 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); 02774 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0); 02775 p->didtdd = 0; 02776 p->cidspill = NULL; 02777 p->callwaitcas = 0; 02778 p->callwaiting = p->permcallwaiting; 02779 p->hidecallerid = p->permhidecallerid; 02780 p->dialing = 0; 02781 p->rdnis[0] = '\0'; 02782 update_conf(p); 02783 reset_conf(p); 02784 /* Restore data mode */ 02785 if (p->sig == SIG_PRI) { 02786 x = 0; 02787 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 02788 } 02789 #ifdef HAVE_PRI 02790 if (p->bearer) { 02791 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel); 02792 /* Free up the bearer channel as well, and 02793 don't use its file descriptor anymore */ 02794 update_conf(p->bearer); 02795 reset_conf(p->bearer); 02796 p->bearer->owner = NULL; 02797 p->bearer->realcall = NULL; 02798 p->bearer = NULL; 02799 p->subs[SUB_REAL].dfd = -1; 02800 p->pri = NULL; 02801 } 02802 #endif 02803 if (num_restart_pending == 0) 02804 restart_monitor(); 02805 } 02806 02807 p->callwaitingrepeat = 0; 02808 p->cidcwexpire = 0; 02809 p->oprmode = 0; 02810 ast->tech_pvt = NULL; 02811 ast_mutex_unlock(&p->lock); 02812 ast_module_unref(ast_module_info->self); 02813 if (option_verbose > 2) 02814 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name); 02815 02816 ast_mutex_lock(&iflock); 02817 02818 if (p->restartpending) { 02819 num_restart_pending--; 02820 } 02821 02822 tmp = iflist; 02823 prev = NULL; 02824 if (p->destroy) { 02825 while (tmp) { 02826 if (tmp == p) { 02827 destroy_channel(prev, tmp, 0); 02828 break; 02829 } else { 02830 prev = tmp; 02831 tmp = tmp->next; 02832 } 02833 } 02834 } 02835 ast_mutex_unlock(&iflock); 02836 return 0; 02837 }
static int dahdi_indicate | ( | struct ast_channel * | chan, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 5156 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, dahdi_pvt::alerting, AST_CAUSE_CONGESTION, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_USER_BUSY, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_SOFTHANGUP_DEV, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, dahdi_pvt::call, dahdi_get_index(), dahdi_set_hook(), dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::dop, errno, ast_channel::hangupcause, ISTRUNK, dahdi_pvt::lock, LOG_DEBUG, dahdi_pvt::mohinterpret, ast_channel::name, option_debug, dahdi_pvt::outgoing, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::priindication_oob, dahdi_pvt::prioffset, dahdi_pvt::proceeding, dahdi_pvt::progress, PVT_TO_CHANNEL, dahdi_pvt::radio, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, dahdi_pvt::span, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
05157 { 05158 struct dahdi_pvt *p = chan->tech_pvt; 05159 int res=-1; 05160 int index; 05161 int func = DAHDI_FLASH; 05162 ast_mutex_lock(&p->lock); 05163 index = dahdi_get_index(chan, p, 0); 05164 if (option_debug) 05165 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name); 05166 if (index == SUB_REAL) { 05167 switch (condition) { 05168 case AST_CONTROL_BUSY: 05169 #ifdef HAVE_PRI 05170 if (p->priindication_oob && p->sig == SIG_PRI) { 05171 chan->hangupcause = AST_CAUSE_USER_BUSY; 05172 chan->_softhangup |= AST_SOFTHANGUP_DEV; 05173 res = 0; 05174 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 05175 if (p->pri->pri) { 05176 if (!pri_grab(p, p->pri)) { 05177 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 05178 pri_rel(p->pri); 05179 } 05180 else 05181 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05182 } 05183 p->progress = 1; 05184 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY); 05185 } else 05186 #endif 05187 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY); 05188 break; 05189 case AST_CONTROL_RINGING: 05190 #ifdef HAVE_PRI 05191 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) { 05192 if (p->pri->pri) { 05193 if (!pri_grab(p, p->pri)) { 05194 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 05195 pri_rel(p->pri); 05196 } 05197 else 05198 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05199 } 05200 p->alerting = 1; 05201 } 05202 #endif 05203 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE); 05204 if (chan->_state != AST_STATE_UP) { 05205 if ((chan->_state != AST_STATE_RING) || 05206 ((p->sig != SIG_FXSKS) && 05207 (p->sig != SIG_FXSLS) && 05208 (p->sig != SIG_FXSGS))) 05209 ast_setstate(chan, AST_STATE_RINGING); 05210 } 05211 break; 05212 case AST_CONTROL_PROCEEDING: 05213 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name); 05214 #ifdef HAVE_PRI 05215 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { 05216 if (p->pri->pri) { 05217 if (!pri_grab(p, p->pri)) { 05218 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 05219 pri_rel(p->pri); 05220 } 05221 else 05222 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05223 } 05224 p->proceeding = 1; 05225 } 05226 #endif 05227 /* don't continue in ast_indicate */ 05228 res = 0; 05229 break; 05230 case AST_CONTROL_PROGRESS: 05231 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name); 05232 #ifdef HAVE_PRI 05233 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */ 05234 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 05235 if (p->pri->pri) { 05236 if (!pri_grab(p, p->pri)) { 05237 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 05238 pri_rel(p->pri); 05239 } 05240 else 05241 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05242 } 05243 p->progress = 1; 05244 } 05245 #endif 05246 /* don't continue in ast_indicate */ 05247 res = 0; 05248 break; 05249 case AST_CONTROL_CONGESTION: 05250 chan->hangupcause = AST_CAUSE_CONGESTION; 05251 #ifdef HAVE_PRI 05252 if (p->priindication_oob && p->sig == SIG_PRI) { 05253 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 05254 chan->_softhangup |= AST_SOFTHANGUP_DEV; 05255 res = 0; 05256 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 05257 if (p->pri) { 05258 if (!pri_grab(p, p->pri)) { 05259 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 05260 pri_rel(p->pri); 05261 } else 05262 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05263 } 05264 p->progress = 1; 05265 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 05266 } else 05267 #endif 05268 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 05269 break; 05270 case AST_CONTROL_HOLD: 05271 #ifdef HAVE_PRI 05272 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 05273 if (!pri_grab(p, p->pri)) { 05274 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD); 05275 pri_rel(p->pri); 05276 } else 05277 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05278 } else 05279 #endif 05280 ast_moh_start(chan, data, p->mohinterpret); 05281 break; 05282 case AST_CONTROL_UNHOLD: 05283 #ifdef HAVE_PRI 05284 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 05285 if (!pri_grab(p, p->pri)) { 05286 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL); 05287 pri_rel(p->pri); 05288 } else 05289 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05290 } else 05291 #endif 05292 ast_moh_stop(chan); 05293 break; 05294 case AST_CONTROL_RADIO_KEY: 05295 if (p->radio) 05296 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 05297 res = 0; 05298 break; 05299 case AST_CONTROL_RADIO_UNKEY: 05300 if (p->radio) 05301 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF); 05302 res = 0; 05303 break; 05304 case AST_CONTROL_FLASH: 05305 /* flash hookswitch */ 05306 if (ISTRUNK(p) && (p->sig != SIG_PRI)) { 05307 /* Clear out the dial buffer */ 05308 p->dop.dialstr[0] = '\0'; 05309 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 05310 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 05311 chan->name, strerror(errno)); 05312 } else 05313 res = 0; 05314 } else 05315 res = 0; 05316 break; 05317 case AST_CONTROL_SRCUPDATE: 05318 res = 0; 05319 break; 05320 case -1: 05321 res = tone_zone_play_tone(p->subs[index].dfd, -1); 05322 break; 05323 } 05324 } else 05325 res = 0; 05326 ast_mutex_unlock(&p->lock); 05327 return res; 05328 }
Definition at line 3184 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and master.
Referenced by dahdi_bridge().
03184 { 03185 int x; 03186 if (!slave || !master) { 03187 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n"); 03188 return; 03189 } 03190 for (x = 0; x < MAX_SLAVES; x++) { 03191 if (!master->slaves[x]) { 03192 master->slaves[x] = slave; 03193 break; 03194 } 03195 } 03196 if (x >= MAX_SLAVES) { 03197 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel); 03198 master->slaves[MAX_SLAVES - 1] = slave; 03199 } 03200 if (slave->master) 03201 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel); 03202 slave->master = master; 03203 03204 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x); 03205 }
static struct ast_channel * dahdi_new | ( | struct dahdi_pvt * | , | |
int | , | |||
int | , | |||
int | , | |||
int | , | |||
int | ||||
) | [static] |
Definition at line 5330 of file chan_dahdi.c.
References accountcode, dahdi_pvt::accountcode, dahdi_pvt::adsi, ast_channel::adsicpe, dahdi_pvt::alreadyhungup, ast_channel::amaflags, dahdi_pvt::amaflags, AST_ADSI_UNAVAILABLE, ast_channel_alloc(), ast_copy_string(), ast_dsp_digitmode(), ast_dsp_new(), ast_dsp_set_busy_compare(), ast_dsp_set_busy_count(), ast_dsp_set_busy_pattern(), ast_dsp_set_call_progress_zone(), ast_dsp_set_features(), ast_dsp_set_threshold(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_random(), ast_safe_string_alloc(), AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_transfercapability2str(), dahdi_pvt::bearer, dahdi_pvt::busycompare, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::call_forward, dahdi_pvt::callgroup, ast_channel::callgroup, dahdi_pvt::callingpres, dahdi_pvt::callprogress, CANBUSYDETECT, CANPROGRESSDETECT, CHAN_PSEUDO, chan_tech, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, dahdi_pvt::cid_name, dahdi_pvt::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, dahdi_pvt::cid_ton, ast_callerid::cid_ton, ast_channel::context, dahdi_pvt::context, dahdi_chan_name, dahdi_chan_name_len, dahdi_confmute(), dahdi_setlinear(), dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::dnid, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, DSP_PROGRESS_TALK, dahdi_pvt::dtmfrelax, errno, ast_channel::exten, dahdi_pvt::exten, dahdi_pvt::fake_event, ast_channel::fds, free, global_jbconf, dahdi_pvt::hardwaredtmf, dahdi_pvt::isidlecall, language, dahdi_pvt::language, dahdi_subchannel::linear, LOG_DEBUG, ast_channel::name, ast_channel::nativeformats, NEED_MFDETECT, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::pickupgroup, ast_channel::pickupgroup, dahdi_pvt::pri, PRI_TRANS_CAP_DIGITAL, ast_channel::rawreadformat, ast_channel::rawwriteformat, dahdi_pvt::rdnis, ast_channel::readformat, ast_channel::rings, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSKS, SIG_PRI, dahdi_pvt::silencethreshold, SUB_REAL, dahdi_pvt::subs, ast_channel::tech, ast_channel::tech_pvt, ast_channel::transfercapability, dahdi_pri::trunkgroup, and ast_channel::writeformat.
Referenced by dahdi_handle_event(), dahdi_request(), and handle_init_event().
05331 { 05332 struct ast_channel *tmp; 05333 int deflaw; 05334 int res; 05335 int x,y; 05336 int features; 05337 char *b2 = NULL; 05338 struct dahdi_params ps; 05339 char chanprefix[*dahdi_chan_name_len + 4]; 05340 05341 if (i->subs[index].owner) { 05342 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]); 05343 return NULL; 05344 } 05345 y = 1; 05346 do { 05347 if (b2) 05348 free(b2); 05349 #ifdef HAVE_PRI 05350 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS))) 05351 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y); 05352 else 05353 #endif 05354 if (i->channel == CHAN_PSEUDO) 05355 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random()); 05356 else 05357 b2 = ast_safe_string_alloc("%d-%d", i->channel, y); 05358 for (x = 0; x < 3; x++) { 05359 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6))) 05360 break; 05361 } 05362 y++; 05363 } while (x < 3); 05364 strcpy(chanprefix, dahdi_chan_name); 05365 strcat(chanprefix, "/%s"); 05366 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2); 05367 if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */ 05368 free(b2); 05369 if (!tmp) 05370 return NULL; 05371 tmp->tech = chan_tech; 05372 ps.channo = i->channel; 05373 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps); 05374 if (res) { 05375 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno)); 05376 ps.curlaw = DAHDI_LAW_MULAW; 05377 } 05378 if (ps.curlaw == DAHDI_LAW_ALAW) 05379 deflaw = AST_FORMAT_ALAW; 05380 else 05381 deflaw = AST_FORMAT_ULAW; 05382 if (law) { 05383 if (law == DAHDI_LAW_ALAW) 05384 deflaw = AST_FORMAT_ALAW; 05385 else 05386 deflaw = AST_FORMAT_ULAW; 05387 } 05388 tmp->fds[0] = i->subs[index].dfd; 05389 tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw; 05390 /* Start out assuming ulaw since it's smaller :) */ 05391 tmp->rawreadformat = deflaw; 05392 tmp->readformat = deflaw; 05393 tmp->rawwriteformat = deflaw; 05394 tmp->writeformat = deflaw; 05395 i->subs[index].linear = 0; 05396 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear); 05397 features = 0; 05398 if (index == SUB_REAL) { 05399 if (i->busydetect && CANBUSYDETECT(i)) 05400 features |= DSP_FEATURE_BUSY_DETECT; 05401 if ((i->callprogress & 1) && CANPROGRESSDETECT(i)) 05402 features |= DSP_FEATURE_CALL_PROGRESS; 05403 if ((!i->outgoing && (i->callprogress & 4)) || 05404 (i->outgoing && (i->callprogress & 2))) { 05405 features |= DSP_FEATURE_FAX_DETECT; 05406 } 05407 #ifdef DAHDI_TONEDETECT 05408 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 05409 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) { 05410 #endif 05411 i->hardwaredtmf = 0; 05412 features |= DSP_FEATURE_DTMF_DETECT; 05413 #ifdef DAHDI_TONEDETECT 05414 } else if (NEED_MFDETECT(i)) { 05415 i->hardwaredtmf = 1; 05416 features |= DSP_FEATURE_DTMF_DETECT; 05417 } 05418 #endif 05419 } 05420 if (features) { 05421 if (i->dsp) { 05422 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name); 05423 } else { 05424 if (i->channel != CHAN_PSEUDO) 05425 i->dsp = ast_dsp_new(); 05426 else 05427 i->dsp = NULL; 05428 if (i->dsp) { 05429 i->dsp_features = features; 05430 #ifdef HAVE_PRI 05431 /* We cannot do progress detection until receives PROGRESS message */ 05432 if (i->outgoing && (i->sig == SIG_PRI)) { 05433 /* Remember requested DSP features, don't treat 05434 talking as ANSWER */ 05435 i->dsp_features = features & ~DSP_PROGRESS_TALK; 05436 features = 0; 05437 } 05438 #endif 05439 ast_dsp_set_features(i->dsp, features); 05440 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax); 05441 if (!ast_strlen_zero(progzone)) 05442 ast_dsp_set_call_progress_zone(i->dsp, progzone); 05443 if (i->busydetect && CANBUSYDETECT(i)) { 05444 if(i->silencethreshold > 0) 05445 ast_dsp_set_threshold(i->dsp, i->silencethreshold); 05446 ast_dsp_set_busy_count(i->dsp, i->busycount); 05447 if(i->busytonelength > 0) 05448 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness); 05449 if((i->busytonelength == i->busyquietlength) && i->busycompare) 05450 ast_dsp_set_busy_compare(i->dsp, i->busycompare); 05451 } 05452 } 05453 } 05454 } 05455 05456 if (state == AST_STATE_RING) 05457 tmp->rings = 1; 05458 tmp->tech_pvt = i; 05459 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) { 05460 /* Only FXO signalled stuff can be picked up */ 05461 tmp->callgroup = i->callgroup; 05462 tmp->pickupgroup = i->pickupgroup; 05463 } 05464 if (!ast_strlen_zero(i->language)) 05465 ast_string_field_set(tmp, language, i->language); 05466 if (!i->owner) 05467 i->owner = tmp; 05468 if (!ast_strlen_zero(i->accountcode)) 05469 ast_string_field_set(tmp, accountcode, i->accountcode); 05470 if (i->amaflags) 05471 tmp->amaflags = i->amaflags; 05472 i->subs[index].owner = tmp; 05473 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 05474 ast_string_field_set(tmp, call_forward, i->call_forward); 05475 /* If we've been told "no ADSI" then enforce it */ 05476 if (!i->adsi) 05477 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 05478 if (!ast_strlen_zero(i->exten)) 05479 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 05480 if (!ast_strlen_zero(i->rdnis)) 05481 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 05482 if (!ast_strlen_zero(i->dnid)) 05483 tmp->cid.cid_dnid = ast_strdup(i->dnid); 05484 05485 /* Don't use ast_set_callerid() here because it will 05486 * generate a needless NewCallerID event */ 05487 #ifdef PRI_ANI 05488 if (!ast_strlen_zero(i->cid_ani)) 05489 tmp->cid.cid_ani = ast_strdup(i->cid_ani); 05490 else 05491 tmp->cid.cid_ani = ast_strdup(i->cid_num); 05492 #else 05493 tmp->cid.cid_ani = ast_strdup(i->cid_num); 05494 #endif 05495 tmp->cid.cid_pres = i->callingpres; 05496 tmp->cid.cid_ton = i->cid_ton; 05497 #ifdef HAVE_PRI 05498 tmp->transfercapability = transfercapability; 05499 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability)); 05500 if (transfercapability & PRI_TRANS_CAP_DIGITAL) 05501 i->digital = 1; 05502 /* Assume calls are not idle calls unless we're told differently */ 05503 i->isidlecall = 0; 05504 i->alreadyhungup = 0; 05505 #endif 05506 /* clear the fake event in case we posted one before we had ast_channel */ 05507 i->fake_event = 0; 05508 /* Assure there is no confmute on this channel */ 05509 dahdi_confmute(i, 0); 05510 /* Configure the new channel jb */ 05511 ast_jb_configure(tmp, &global_jbconf); 05512 if (startpbx) { 05513 if (ast_pbx_start(tmp)) { 05514 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 05515 ast_hangup(tmp); 05516 i->owner = NULL; 05517 return NULL; 05518 } 05519 } 05520 05521 ast_module_ref(ast_module_info->self); 05522 05523 return tmp; 05524 }
static int dahdi_open | ( | char * | fn | ) | [static] |
Definition at line 906 of file chan_dahdi.c.
References ast_log(), DAHDI_FILE_CHANNEL, errno, LOG_WARNING, and READ_SIZE.
Referenced by alloc_sub(), chandup(), and mkintf().
00907 { 00908 int fd; 00909 int isnum; 00910 int chan = 0; 00911 int bs; 00912 int x; 00913 isnum = 1; 00914 for (x = 0; x < strlen(fn); x++) { 00915 if (!isdigit(fn[x])) { 00916 isnum = 0; 00917 break; 00918 } 00919 } 00920 if (isnum) { 00921 chan = atoi(fn); 00922 if (chan < 1) { 00923 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn); 00924 return -1; 00925 } 00926 fn = DAHDI_FILE_CHANNEL; 00927 } 00928 fd = open(fn, O_RDWR | O_NONBLOCK); 00929 if (fd < 0) { 00930 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno)); 00931 return -1; 00932 } 00933 if (chan) { 00934 if (ioctl(fd, DAHDI_SPECIFY, &chan)) { 00935 x = errno; 00936 close(fd); 00937 errno = x; 00938 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno)); 00939 return -1; 00940 } 00941 } 00942 bs = READ_SIZE; 00943 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) { 00944 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno)); 00945 x = errno; 00946 close(fd); 00947 errno = x; 00948 return -1; 00949 } 00950 return fd; 00951 }
static void dahdi_pri_error | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 8402 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().
08403 { 08404 int x, y; 08405 int dchan = -1, span = -1; 08406 int dchancount = 0; 08407 08408 if (pri) { 08409 for (x = 0; x < NUM_SPANS; x++) { 08410 for (y = 0; y < NUM_DCHANS; y++) { 08411 if (pris[x].dchans[y]) 08412 dchancount++; 08413 08414 if (pris[x].dchans[y] == pri) 08415 dchan = y; 08416 } 08417 if (dchan >= 0) { 08418 span = x; 08419 break; 08420 } 08421 dchancount = 0; 08422 } 08423 if ((dchan >= 0) && (span >= 0)) { 08424 if (dchancount > 1) 08425 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s); 08426 else 08427 ast_log(LOG_ERROR, "%s", s); 08428 } else 08429 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n"); 08430 } else 08431 ast_log(LOG_ERROR, "%s", s); 08432 08433 ast_mutex_lock(&pridebugfdlock); 08434 08435 if (pridebugfd >= 0) { 08436 if (write(pridebugfd, s, strlen(s)) < 0) { 08437 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 08438 } 08439 } 08440 08441 ast_mutex_unlock(&pridebugfdlock); 08442 }
static void dahdi_pri_message | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 8360 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().
08361 { 08362 int x, y; 08363 int dchan = -1, span = -1; 08364 int dchancount = 0; 08365 08366 if (pri) { 08367 for (x = 0; x < NUM_SPANS; x++) { 08368 for (y = 0; y < NUM_DCHANS; y++) { 08369 if (pris[x].dchans[y]) 08370 dchancount++; 08371 08372 if (pris[x].dchans[y] == pri) 08373 dchan = y; 08374 } 08375 if (dchan >= 0) { 08376 span = x; 08377 break; 08378 } 08379 dchancount = 0; 08380 } 08381 if ((dchan >= 0) && (span >= 0)) { 08382 if (dchancount > 1) 08383 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s); 08384 else 08385 ast_verbose("%s", s); 08386 } else 08387 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n"); 08388 } else 08389 ast_verbose("%s", s); 08390 08391 ast_mutex_lock(&pridebugfdlock); 08392 08393 if (pridebugfd >= 0) { 08394 if (write(pridebugfd, s, strlen(s)) < 0) { 08395 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 08396 } 08397 } 08398 08399 ast_mutex_unlock(&pridebugfdlock); 08400 }
static void dahdi_queue_frame | ( | struct dahdi_pvt * | p, | |
struct ast_frame * | f, | |||
struct dahdi_pri * | pri | |||
) | [static] |
Definition at line 848 of file chan_dahdi.c.
References ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_frame(), DEADLOCK_AVOIDANCE, and f.
Referenced by __action_dialoffhook().
00852 { 00853 /* We must unlock the PRI to avoid the possibility of a deadlock */ 00854 #ifdef HAVE_PRI 00855 if (pri) 00856 ast_mutex_unlock(&pri->lock); 00857 #endif 00858 for (;;) { 00859 if (p->owner) { 00860 if (ast_mutex_trylock(&p->owner->lock)) { 00861 DEADLOCK_AVOIDANCE(&p->lock); 00862 } else { 00863 ast_queue_frame(p->owner, f); 00864 ast_mutex_unlock(&p->owner->lock); 00865 break; 00866 } 00867 } else 00868 break; 00869 } 00870 #ifdef HAVE_PRI 00871 if (pri) 00872 ast_mutex_lock(&pri->lock); 00873 #endif 00874 }
static struct ast_frame * dahdi_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 4760 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.
04761 { 04762 struct dahdi_pvt *p = ast->tech_pvt; 04763 int res; 04764 int index; 04765 void *readbuf; 04766 struct ast_frame *f; 04767 04768 while (ast_mutex_trylock(&p->lock)) { 04769 DEADLOCK_AVOIDANCE(&ast->lock); 04770 } 04771 04772 index = dahdi_get_index(ast, p, 0); 04773 04774 /* Hang up if we don't really exist */ 04775 if (index < 0) { 04776 ast_log(LOG_WARNING, "We dont exist?\n"); 04777 ast_mutex_unlock(&p->lock); 04778 return NULL; 04779 } 04780 04781 if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL; 04782 04783 p->subs[index].f.frametype = AST_FRAME_NULL; 04784 p->subs[index].f.datalen = 0; 04785 p->subs[index].f.samples = 0; 04786 p->subs[index].f.mallocd = 0; 04787 p->subs[index].f.offset = 0; 04788 p->subs[index].f.subclass = 0; 04789 p->subs[index].f.delivery = ast_tv(0,0); 04790 p->subs[index].f.src = "dahdi_read"; 04791 p->subs[index].f.data = NULL; 04792 04793 /* make sure it sends initial key state as first frame */ 04794 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio)) 04795 { 04796 struct dahdi_params ps; 04797 04798 ps.channo = p->channel; 04799 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 04800 ast_mutex_unlock(&p->lock); 04801 return NULL; 04802 } 04803 p->firstradio = 1; 04804 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04805 if (ps.rxisoffhook) 04806 { 04807 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY; 04808 } 04809 else 04810 { 04811 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY; 04812 } 04813 ast_mutex_unlock(&p->lock); 04814 return &p->subs[index].f; 04815 } 04816 if (p->ringt == 1) { 04817 ast_mutex_unlock(&p->lock); 04818 return NULL; 04819 } 04820 else if (p->ringt > 0) 04821 p->ringt--; 04822 04823 if (p->subs[index].needringing) { 04824 /* Send ringing frame if requested */ 04825 p->subs[index].needringing = 0; 04826 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04827 p->subs[index].f.subclass = AST_CONTROL_RINGING; 04828 ast_setstate(ast, AST_STATE_RINGING); 04829 ast_mutex_unlock(&p->lock); 04830 return &p->subs[index].f; 04831 } 04832 04833 if (p->subs[index].needbusy) { 04834 /* Send busy frame if requested */ 04835 p->subs[index].needbusy = 0; 04836 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04837 p->subs[index].f.subclass = AST_CONTROL_BUSY; 04838 ast_mutex_unlock(&p->lock); 04839 return &p->subs[index].f; 04840 } 04841 04842 if (p->subs[index].needcongestion) { 04843 /* Send congestion frame if requested */ 04844 p->subs[index].needcongestion = 0; 04845 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04846 p->subs[index].f.subclass = AST_CONTROL_CONGESTION; 04847 ast_mutex_unlock(&p->lock); 04848 return &p->subs[index].f; 04849 } 04850 04851 if (p->subs[index].needcallerid) { 04852 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL), 04853 S_OR(p->lastcid_name, NULL), 04854 S_OR(p->lastcid_num, NULL) 04855 ); 04856 p->subs[index].needcallerid = 0; 04857 } 04858 04859 if (p->subs[index].needanswer) { 04860 /* Send answer frame if requested */ 04861 p->subs[index].needanswer = 0; 04862 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04863 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 04864 ast_mutex_unlock(&p->lock); 04865 return &p->subs[index].f; 04866 } 04867 04868 if (p->subs[index].needflash) { 04869 /* Send answer frame if requested */ 04870 p->subs[index].needflash = 0; 04871 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04872 p->subs[index].f.subclass = AST_CONTROL_FLASH; 04873 ast_mutex_unlock(&p->lock); 04874 return &p->subs[index].f; 04875 } 04876 04877 if (p->subs[index].needhold) { 04878 /* Send answer frame if requested */ 04879 p->subs[index].needhold = 0; 04880 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04881 p->subs[index].f.subclass = AST_CONTROL_HOLD; 04882 ast_mutex_unlock(&p->lock); 04883 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name); 04884 return &p->subs[index].f; 04885 } 04886 04887 if (p->subs[index].needunhold) { 04888 /* Send answer frame if requested */ 04889 p->subs[index].needunhold = 0; 04890 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04891 p->subs[index].f.subclass = AST_CONTROL_UNHOLD; 04892 ast_mutex_unlock(&p->lock); 04893 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name); 04894 return &p->subs[index].f; 04895 } 04896 04897 if (ast->rawreadformat == AST_FORMAT_SLINEAR) { 04898 if (!p->subs[index].linear) { 04899 p->subs[index].linear = 1; 04900 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 04901 if (res) 04902 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index); 04903 } 04904 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) || 04905 (ast->rawreadformat == AST_FORMAT_ALAW)) { 04906 if (p->subs[index].linear) { 04907 p->subs[index].linear = 0; 04908 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 04909 if (res) 04910 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index); 04911 } 04912 } else { 04913 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat)); 04914 ast_mutex_unlock(&p->lock); 04915 return NULL; 04916 } 04917 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET; 04918 CHECK_BLOCKING(ast); 04919 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE); 04920 ast_clear_flag(ast, AST_FLAG_BLOCKING); 04921 /* Check for hangup */ 04922 if (res < 0) { 04923 f = NULL; 04924 if (res == -1) { 04925 if (errno == EAGAIN) { 04926 /* Return "NULL" frame if there is nobody there */ 04927 ast_mutex_unlock(&p->lock); 04928 return &p->subs[index].f; 04929 } else if (errno == ELAST) { 04930 f = __dahdi_exception(ast); 04931 } else 04932 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno)); 04933 } 04934 ast_mutex_unlock(&p->lock); 04935 return f; 04936 } 04937 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) { 04938 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE); 04939 f = __dahdi_exception(ast); 04940 ast_mutex_unlock(&p->lock); 04941 return f; 04942 } 04943 if (p->tdd) { /* if in TDD mode, see if we receive that */ 04944 int c; 04945 04946 c = tdd_feed(p->tdd,readbuf,READ_SIZE); 04947 if (c < 0) { 04948 ast_log(LOG_DEBUG,"tdd_feed failed\n"); 04949 ast_mutex_unlock(&p->lock); 04950 return NULL; 04951 } 04952 if (c) { /* if a char to return */ 04953 p->subs[index].f.subclass = 0; 04954 p->subs[index].f.frametype = AST_FRAME_TEXT; 04955 p->subs[index].f.mallocd = 0; 04956 p->subs[index].f.offset = AST_FRIENDLY_OFFSET; 04957 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET; 04958 p->subs[index].f.datalen = 1; 04959 *((char *) p->subs[index].f.data) = c; 04960 ast_mutex_unlock(&p->lock); 04961 return &p->subs[index].f; 04962 } 04963 } 04964 /* Ensure the CW timer decrements only on a single subchannel */ 04965 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) { 04966 p->callwaitingrepeat--; 04967 } 04968 if (p->cidcwexpire) 04969 p->cidcwexpire--; 04970 /* Repeat callwaiting */ 04971 if (p->callwaitingrepeat == 1) { 04972 p->callwaitrings++; 04973 dahdi_callwait(ast); 04974 } 04975 /* Expire CID/CW */ 04976 if (p->cidcwexpire == 1) { 04977 if (option_verbose > 2) 04978 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n"); 04979 restore_conference(p); 04980 } 04981 if (p->subs[index].linear) { 04982 p->subs[index].f.datalen = READ_SIZE * 2; 04983 } else 04984 p->subs[index].f.datalen = READ_SIZE; 04985 04986 /* Handle CallerID Transmission */ 04987 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) { 04988 send_callerid(p); 04989 } 04990 04991 p->subs[index].f.frametype = AST_FRAME_VOICE; 04992 p->subs[index].f.subclass = ast->rawreadformat; 04993 p->subs[index].f.samples = READ_SIZE; 04994 p->subs[index].f.mallocd = 0; 04995 p->subs[index].f.offset = AST_FRIENDLY_OFFSET; 04996 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]); 04997 #if 0 04998 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name); 04999 #endif 05000 if (p->dialing || /* Transmitting something */ 05001 (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */ 05002 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */ 05003 ) { 05004 /* Whoops, we're still dialing, or in a state where we shouldn't transmit.... 05005 don't send anything */ 05006 p->subs[index].f.frametype = AST_FRAME_NULL; 05007 p->subs[index].f.subclass = 0; 05008 p->subs[index].f.samples = 0; 05009 p->subs[index].f.mallocd = 0; 05010 p->subs[index].f.offset = 0; 05011 p->subs[index].f.data = NULL; 05012 p->subs[index].f.datalen= 0; 05013 } 05014 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) { 05015 /* Perform busy detection. etc on the dahdi line */ 05016 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f); 05017 if (f) { 05018 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) { 05019 if ((ast->_state == AST_STATE_UP) && !p->outgoing) { 05020 /* Treat this as a "hangup" instead of a "busy" on the assumption that 05021 a busy */ 05022 f = NULL; 05023 } 05024 } else if (f->frametype == AST_FRAME_DTMF) { 05025 #ifdef HAVE_PRI 05026 if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) { 05027 /* Don't accept in-band DTMF when in overlap dial mode */ 05028 f->frametype = AST_FRAME_NULL; 05029 f->subclass = 0; 05030 } 05031 #endif 05032 /* DSP clears us of being pulse */ 05033 p->pulsedial = 0; 05034 } 05035 } 05036 } else 05037 f = &p->subs[index].f; 05038 05039 if (f && (f->frametype == AST_FRAME_DTMF)) 05040 dahdi_handle_dtmfup(ast, index, &f); 05041 05042 /* If we have a fake_event, trigger exception to handle it */ 05043 if (p->fake_event) 05044 ast_set_flag(ast, AST_FLAG_EXCEPTION); 05045 05046 ast_mutex_unlock(&p->lock); 05047 return f; 05048 }
static struct ast_channel * dahdi_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 7960 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().
07961 { 07962 ast_group_t groupmatch = 0; 07963 int channelmatch = -1; 07964 int roundrobin = 0; 07965 int callwait = 0; 07966 int busy = 0; 07967 struct dahdi_pvt *p; 07968 struct ast_channel *tmp = NULL; 07969 char *dest=NULL; 07970 int x; 07971 char *s; 07972 char opt=0; 07973 int res=0, y=0; 07974 int backwards = 0; 07975 #ifdef HAVE_PRI 07976 int crv; 07977 int bearer = -1; 07978 int trunkgroup; 07979 struct dahdi_pri *pri=NULL; 07980 #endif 07981 struct dahdi_pvt *exit, *start, *end; 07982 ast_mutex_t *lock; 07983 int channelmatched = 0; 07984 int groupmatched = 0; 07985 07986 /* Assume we're locking the iflock */ 07987 lock = &iflock; 07988 start = iflist; 07989 end = ifend; 07990 if (data) { 07991 dest = ast_strdupa((char *)data); 07992 } else { 07993 ast_log(LOG_WARNING, "Channel requested with no data\n"); 07994 return NULL; 07995 } 07996 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') { 07997 /* Retrieve the group number */ 07998 char *stringp=NULL; 07999 stringp=dest + 1; 08000 s = strsep(&stringp, "/"); 08001 if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) { 08002 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data); 08003 return NULL; 08004 } 08005 groupmatch = ((ast_group_t) 1 << x); 08006 if (toupper(dest[0]) == 'G') { 08007 if (dest[0] == 'G') { 08008 backwards = 1; 08009 p = ifend; 08010 } else 08011 p = iflist; 08012 } else { 08013 if (dest[0] == 'R') { 08014 backwards = 1; 08015 p = round_robin[x]?round_robin[x]->prev:ifend; 08016 if (!p) 08017 p = ifend; 08018 } else { 08019 p = round_robin[x]?round_robin[x]->next:iflist; 08020 if (!p) 08021 p = iflist; 08022 } 08023 roundrobin = 1; 08024 } 08025 } else { 08026 char *stringp=NULL; 08027 stringp=dest; 08028 s = strsep(&stringp, "/"); 08029 p = iflist; 08030 if (!strcasecmp(s, "pseudo")) { 08031 /* Special case for pseudo */ 08032 x = CHAN_PSEUDO; 08033 channelmatch = x; 08034 } 08035 #ifdef HAVE_PRI 08036 else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) { 08037 if ((trunkgroup < 1) || (crv < 1)) { 08038 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data); 08039 return NULL; 08040 } 08041 res--; 08042 for (x = 0; x < NUM_SPANS; x++) { 08043 if (pris[x].trunkgroup == trunkgroup) { 08044 pri = pris + x; 08045 lock = &pri->lock; 08046 start = pri->crvs; 08047 end = pri->crvend; 08048 break; 08049 } 08050 } 08051 if (!pri) { 08052 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup); 08053 return NULL; 08054 } 08055 channelmatch = crv; 08056 p = pris[x].crvs; 08057 } 08058 #endif 08059 else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) { 08060 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data); 08061 return NULL; 08062 } else { 08063 channelmatch = x; 08064 } 08065 } 08066 /* Search for an unowned channel */ 08067 ast_mutex_lock(lock); 08068 exit = p; 08069 while (p && !tmp) { 08070 if (roundrobin) 08071 round_robin[x] = p; 08072 #if 0 08073 ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch); 08074 #endif 08075 08076 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) { 08077 if (option_debug) 08078 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel); 08079 if (p->inalarm) 08080 goto next; 08081 08082 callwait = (p->owner != NULL); 08083 #ifdef HAVE_PRI 08084 if (pri && (p->subs[SUB_REAL].dfd < 0)) { 08085 if (p->sig != SIG_FXSKS) { 08086 /* Gotta find an actual channel to use for this 08087 CRV if this isn't a callwait */ 08088 bearer = pri_find_empty_chan(pri, 0); 08089 if (bearer < 0) { 08090 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv); 08091 p = NULL; 08092 break; 08093 } 08094 pri_assign_bearer(p, pri, pri->pvts[bearer]); 08095 } else { 08096 if (alloc_sub(p, 0)) { 08097 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n"); 08098 p = NULL; 08099 break; 08100 } else 08101 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n"); 08102 p->pri = pri; 08103 } 08104 } 08105 #endif 08106 if (p->channel == CHAN_PSEUDO) { 08107 p = chandup(p); 08108 if (!p) { 08109 break; 08110 } 08111 } 08112 if (p->owner) { 08113 if (alloc_sub(p, SUB_CALLWAIT)) { 08114 p = NULL; 08115 break; 08116 } 08117 } 08118 p->outgoing = 1; 08119 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0); 08120 #ifdef HAVE_PRI 08121 if (p->bearer) { 08122 /* Log owner to bearer channel, too */ 08123 p->bearer->owner = tmp; 08124 } 08125 #endif 08126 /* Make special notes */ 08127 if (res > 1) { 08128 if (opt == 'c') { 08129 /* Confirm answer */ 08130 p->confirmanswer = 1; 08131 } else if (opt == 'r') { 08132 /* Distinctive ring */ 08133 if (res < 3) 08134 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data); 08135 else 08136 p->distinctivering = y; 08137 } else if (opt == 'd') { 08138 /* If this is an ISDN call, make it digital */ 08139 p->digital = 1; 08140 if (tmp) 08141 tmp->transfercapability = AST_TRANS_CAP_DIGITAL; 08142 } else { 08143 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data); 08144 } 08145 } 08146 /* Note if the call is a call waiting call */ 08147 if (tmp && callwait) 08148 tmp->cdrflags |= AST_CDR_CALLWAIT; 08149 break; 08150 } 08151 next: 08152 if (backwards) { 08153 p = p->prev; 08154 if (!p) 08155 p = end; 08156 } else { 08157 p = p->next; 08158 if (!p) 08159 p = start; 08160 } 08161 /* stop when you roll to the one that we started from */ 08162 if (p == exit) 08163 break; 08164 } 08165 ast_mutex_unlock(lock); 08166 restart_monitor(); 08167 if (callwait) 08168 *cause = AST_CAUSE_BUSY; 08169 else if (!tmp) { 08170 if (channelmatched) { 08171 if (busy) 08172 *cause = AST_CAUSE_BUSY; 08173 } else if (groupmatched) { 08174 *cause = AST_CAUSE_CONGESTION; 08175 } 08176 } 08177 08178 return tmp; 08179 }
static int dahdi_restart | ( | void | ) | [static] |
Definition at line 10090 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().
10091 { 10092 #if defined(HAVE_PRI) 10093 int i, j; 10094 #endif 10095 int cancel_code; 10096 struct dahdi_pvt *p; 10097 10098 ast_mutex_lock(&restart_lock); 10099 10100 if (option_verbose) 10101 ast_verbose("Destroying channels and reloading DAHDI configuration.\n"); 10102 dahdi_softhangup_all(); 10103 if (option_verbose > 3) 10104 ast_verbose("Initial softhangup of all DAHDI channels complete.\n"); 10105 10106 #if defined(HAVE_PRI) 10107 for (i = 0; i < NUM_SPANS; i++) { 10108 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) { 10109 cancel_code = pthread_cancel(pris[i].master); 10110 pthread_kill(pris[i].master, SIGURG); 10111 if (option_debug > 3) 10112 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code); 10113 pthread_join(pris[i].master, NULL); 10114 if (option_debug > 3) 10115 ast_verbose("Joined thread of span %d\n", i); 10116 } 10117 } 10118 #endif 10119 10120 ast_mutex_lock(&monlock); 10121 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 10122 cancel_code = pthread_cancel(monitor_thread); 10123 pthread_kill(monitor_thread, SIGURG); 10124 if (option_debug > 3) 10125 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code); 10126 pthread_join(monitor_thread, NULL); 10127 if (option_debug > 3) 10128 ast_verbose("Joined monitor thread\n"); 10129 } 10130 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */ 10131 10132 ast_mutex_lock(&ss_thread_lock); 10133 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */ 10134 int x = DAHDI_FLASH; 10135 if (option_debug > 2) 10136 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count); 10137 10138 for (p = iflist; p; p = p->next) { 10139 if (p->owner) 10140 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 */ 10141 } 10142 ast_cond_wait(&ss_thread_complete, &ss_thread_lock); 10143 } 10144 10145 /* ensure any created channels before monitor threads were stopped are hungup */ 10146 dahdi_softhangup_all(); 10147 if (option_verbose > 3) 10148 ast_verbose("Final softhangup of all DAHDI channels complete.\n"); 10149 destroy_all_channels(); 10150 if (option_debug) 10151 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels()); 10152 10153 ast_mutex_unlock(&monlock); 10154 10155 #ifdef HAVE_PRI 10156 for (i = 0; i < NUM_SPANS; i++) { 10157 for (j = 0; j < NUM_DCHANS; j++) 10158 dahdi_close_pri_fd(&(pris[i]), j); 10159 } 10160 10161 memset(pris, 0, sizeof(pris)); 10162 for (i = 0; i < NUM_SPANS; i++) { 10163 ast_mutex_init(&pris[i].lock); 10164 pris[i].offset = -1; 10165 pris[i].master = AST_PTHREADT_NULL; 10166 for (j = 0; j < NUM_DCHANS; j++) 10167 pris[i].fds[j] = -1; 10168 } 10169 pri_set_error(dahdi_pri_error); 10170 pri_set_message(dahdi_pri_message); 10171 #endif 10172 10173 if (setup_dahdi(2) != 0) { 10174 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n"); 10175 ast_mutex_unlock(&ss_thread_lock); 10176 return 1; 10177 } 10178 ast_mutex_unlock(&ss_thread_lock); 10179 ast_mutex_unlock(&restart_lock); 10180 return 0; 10181 }
static int dahdi_restart_cmd | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 10183 of file chan_dahdi.c.
References dahdi_restart(), RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
10184 { 10185 if (argc != 2) { 10186 return RESULT_SHOWUSAGE; 10187 } 10188 10189 if (dahdi_restart() != 0) 10190 return RESULT_FAILURE; 10191 return RESULT_SUCCESS; 10192 }
static int dahdi_ring_phone | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3559 of file chan_dahdi.c.
References ast_log(), errno, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), and dahdi_handle_event().
03560 { 03561 int x; 03562 int res; 03563 /* Make sure our transmit state is on hook */ 03564 x = 0; 03565 x = DAHDI_ONHOOK; 03566 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 03567 do { 03568 x = DAHDI_RING; 03569 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 03570 if (res) { 03571 switch (errno) { 03572 case EBUSY: 03573 case EINTR: 03574 /* Wait just in case */ 03575 usleep(10000); 03576 continue; 03577 case EINPROGRESS: 03578 res = 0; 03579 break; 03580 default: 03581 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno)); 03582 res = 0; 03583 } 03584 } 03585 } while (res); 03586 return res; 03587 }
static int dahdi_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 2415 of file chan_dahdi.c.
References send_keypad_facility_exec().
Referenced by load_module().
02416 { 02417 return send_keypad_facility_exec(chan, data); 02418 }
static int dahdi_sendtext | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 11906 of file chan_dahdi.c.
References ASCII_BYTES_PER_CHAR, ast_check_hangup(), ast_free, AST_LAW, ast_log(), ast_malloc, dahdi_pvt::channel, dahdi_get_index(), dahdi_subchannel::dfd, END_SILENCE_LEN, errno, pollfd::events, pollfd::fd, free, HEADER_LEN, HEADER_MS, len(), LOG_ERROR, dahdi_pvt::mate, option_debug, poll(), POLLOUT, PUT_CLID, PUT_CLID_MARKMS, READ_SIZE, pollfd::revents, dahdi_pvt::subs, dahdi_pvt::tdd, TDD_BYTES_PER_CHAR, tdd_generate(), ast_channel::tech_pvt, and TRAILER_MS.
11907 { 11908 #define END_SILENCE_LEN 400 11909 #define HEADER_MS 50 11910 #define TRAILER_MS 5 11911 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) 11912 #define ASCII_BYTES_PER_CHAR 80 11913 11914 unsigned char *buf,*mybuf; 11915 struct dahdi_pvt *p = c->tech_pvt; 11916 struct pollfd fds[1]; 11917 int size,res,fd,len,x; 11918 int bytes=0; 11919 /* Initial carrier (imaginary) */ 11920 float cr = 1.0; 11921 float ci = 0.0; 11922 float scont = 0.0; 11923 int index; 11924 11925 index = dahdi_get_index(c, p, 0); 11926 if (index < 0) { 11927 ast_log(LOG_WARNING, "Huh? I don't exist?\n"); 11928 return -1; 11929 } 11930 if (!text[0]) return(0); /* if nothing to send, dont */ 11931 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */ 11932 if (p->mate) 11933 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN); 11934 else 11935 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN); 11936 if (!buf) 11937 return -1; 11938 mybuf = buf; 11939 if (p->mate) { 11940 int codec = AST_LAW(p); 11941 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */ 11942 PUT_CLID_MARKMS; 11943 } 11944 /* Put actual message */ 11945 for (x = 0; text[x]; x++) { 11946 PUT_CLID(text[x]); 11947 } 11948 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */ 11949 PUT_CLID_MARKMS; 11950 } 11951 len = bytes; 11952 buf = mybuf; 11953 } else { 11954 len = tdd_generate(p->tdd, buf, text); 11955 if (len < 1) { 11956 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text)); 11957 free(mybuf); 11958 return -1; 11959 } 11960 } 11961 memset(buf + len, 0x7f, END_SILENCE_LEN); 11962 len += END_SILENCE_LEN; 11963 fd = p->subs[index].dfd; 11964 while (len) { 11965 if (ast_check_hangup(c)) { 11966 free(mybuf); 11967 return -1; 11968 } 11969 size = len; 11970 if (size > READ_SIZE) 11971 size = READ_SIZE; 11972 fds[0].fd = fd; 11973 fds[0].events = POLLOUT | POLLPRI; 11974 fds[0].revents = 0; 11975 res = poll(fds, 1, -1); 11976 if (!res) { 11977 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel); 11978 continue; 11979 } 11980 /* if got exception */ 11981 if (fds[0].revents & POLLPRI) { 11982 ast_free(mybuf); 11983 return -1; 11984 } 11985 if (!(fds[0].revents & POLLOUT)) { 11986 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel); 11987 continue; 11988 } 11989 res = write(fd, buf, size); 11990 if (res != size) { 11991 if (res == -1) { 11992 free(mybuf); 11993 return -1; 11994 } 11995 if (option_debug) 11996 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 11997 break; 11998 } 11999 len -= size; 12000 buf += size; 12001 } 12002 free(mybuf); 12003 return(0); 12004 }
static int dahdi_set_hook | ( | int | fd, | |
int | hs | |||
) | [inline, static] |
Definition at line 1659 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().
01660 { 01661 int x, res; 01662 01663 x = hs; 01664 res = ioctl(fd, DAHDI_HOOK, &x); 01665 01666 if (res < 0) { 01667 if (errno == EINPROGRESS) 01668 return 0; 01669 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno)); 01670 /* will expectedly fail if phone is off hook during operation, such as during a restart */ 01671 } 01672 01673 return res; 01674 }
static int dahdi_setlaw | ( | int | dfd, | |
int | law | |||
) | [static] |
Definition at line 8527 of file chan_dahdi.c.
08528 { 08529 int res; 08530 res = ioctl(dfd, DAHDI_SETLAW, &law); 08531 if (res) 08532 return res; 08533 return 0; 08534 }
static int dahdi_setlinear | ( | int | dfd, | |
int | linear | |||
) | [static] |
Definition at line 973 of file chan_dahdi.c.
Referenced by dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_write(), send_callerid(), and ss_thread().
00974 { 00975 int res; 00976 res = ioctl(dfd, DAHDI_SETLINEAR, &linear); 00977 if (res) 00978 return res; 00979 return 0; 00980 }
static int dahdi_setoption | ( | struct ast_channel * | chan, | |
int | option, | |||
void * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 2924 of file chan_dahdi.c.
References ast_check_hangup(), ast_dsp_digitmode(), ast_log(), AST_OPTION_AUDIO_MODE, AST_OPTION_ECHOCAN, AST_OPTION_OPRMODE, AST_OPTION_RELAXDTMF, AST_OPTION_RXGAIN, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, AST_OPTION_TXGAIN, ast_tdd_gen_ecdisa(), dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_subchannel::dfd, dahdi_pvt::didtdd, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, errno, pollfd::events, pollfd::fd, dahdi_pvt::law, len(), LOG_DEBUG, LOG_WARNING, dahdi_pvt::mate, oprmode::mode, ast_channel::name, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, option_debug, oprmode::peer, poll(), POLLOUT, POLLPRI, READ_SIZE, pollfd::revents, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_free(), tdd_new(), ast_channel::tech_pvt, and dahdi_pvt::txgain.
02925 { 02926 char *cp; 02927 signed char *scp; 02928 int x; 02929 int index; 02930 struct dahdi_pvt *p = chan->tech_pvt, *pp; 02931 struct oprmode *oprmode; 02932 02933 02934 /* all supported options require data */ 02935 if (!data || (datalen < 1)) { 02936 errno = EINVAL; 02937 return -1; 02938 } 02939 02940 switch (option) { 02941 case AST_OPTION_TXGAIN: 02942 scp = (signed char *) data; 02943 index = dahdi_get_index(chan, p, 0); 02944 if (index < 0) { 02945 ast_log(LOG_WARNING, "No index in TXGAIN?\n"); 02946 return -1; 02947 } 02948 if (option_debug) 02949 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp); 02950 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law); 02951 case AST_OPTION_RXGAIN: 02952 scp = (signed char *) data; 02953 index = dahdi_get_index(chan, p, 0); 02954 if (index < 0) { 02955 ast_log(LOG_WARNING, "No index in RXGAIN?\n"); 02956 return -1; 02957 } 02958 if (option_debug) 02959 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp); 02960 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law); 02961 case AST_OPTION_TONE_VERIFY: 02962 if (!p->dsp) 02963 break; 02964 cp = (char *) data; 02965 switch (*cp) { 02966 case 1: 02967 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name); 02968 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */ 02969 break; 02970 case 2: 02971 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name); 02972 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */ 02973 break; 02974 default: 02975 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name); 02976 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */ 02977 break; 02978 } 02979 break; 02980 case AST_OPTION_TDD: 02981 /* turn on or off TDD */ 02982 cp = (char *) data; 02983 p->mate = 0; 02984 if (!*cp) { /* turn it off */ 02985 if (option_debug) 02986 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name); 02987 if (p->tdd) 02988 tdd_free(p->tdd); 02989 p->tdd = 0; 02990 break; 02991 } 02992 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n", 02993 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name); 02994 dahdi_disable_ec(p); 02995 /* otherwise, turn it on */ 02996 if (!p->didtdd) { /* if havent done it yet */ 02997 unsigned char mybuf[41000], *buf; 02998 int size, res, fd, len; 02999 struct pollfd fds[1]; 03000 03001 buf = mybuf; 03002 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */ 03003 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */ 03004 len = 40000; 03005 index = dahdi_get_index(chan, p, 0); 03006 if (index < 0) { 03007 ast_log(LOG_WARNING, "No index in TDD?\n"); 03008 return -1; 03009 } 03010 fd = p->subs[index].dfd; 03011 while (len) { 03012 if (ast_check_hangup(chan)) 03013 return -1; 03014 size = len; 03015 if (size > READ_SIZE) 03016 size = READ_SIZE; 03017 fds[0].fd = fd; 03018 fds[0].events = POLLPRI | POLLOUT; 03019 fds[0].revents = 0; 03020 res = poll(fds, 1, -1); 03021 if (!res) { 03022 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel); 03023 continue; 03024 } 03025 /* if got exception */ 03026 if (fds[0].revents & POLLPRI) 03027 return -1; 03028 if (!(fds[0].revents & POLLOUT)) { 03029 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel); 03030 continue; 03031 } 03032 res = write(fd, buf, size); 03033 if (res != size) { 03034 if (res == -1) return -1; 03035 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 03036 break; 03037 } 03038 len -= size; 03039 buf += size; 03040 } 03041 p->didtdd = 1; /* set to have done it now */ 03042 } 03043 if (*cp == 2) { /* Mate mode */ 03044 if (p->tdd) 03045 tdd_free(p->tdd); 03046 p->tdd = 0; 03047 p->mate = 1; 03048 break; 03049 } 03050 if (!p->tdd) { /* if we dont have one yet */ 03051 p->tdd = tdd_new(); /* allocate one */ 03052 } 03053 break; 03054 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */ 03055 if (!p->dsp) 03056 break; 03057 cp = (char *) data; 03058 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n", 03059 *cp ? "ON" : "OFF", (int) *cp, chan->name); 03060 p->dtmfrelax = 0; 03061 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 03062 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 03063 break; 03064 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */ 03065 cp = (char *) data; 03066 if (!*cp) { 03067 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name); 03068 x = 0; 03069 dahdi_disable_ec(p); 03070 } else { 03071 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name); 03072 x = 1; 03073 } 03074 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1) 03075 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno)); 03076 break; 03077 case AST_OPTION_OPRMODE: /* Operator services mode */ 03078 oprmode = (struct oprmode *) data; 03079 pp = oprmode->peer->tech_pvt; 03080 p->oprmode = pp->oprmode = 0; 03081 /* setup peers */ 03082 p->oprpeer = pp; 03083 pp->oprpeer = p; 03084 /* setup modes, if any */ 03085 if (oprmode->mode) 03086 { 03087 pp->oprmode = oprmode->mode; 03088 p->oprmode = -oprmode->mode; 03089 } 03090 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n", 03091 oprmode->mode, chan->name,oprmode->peer->name);; 03092 break; 03093 case AST_OPTION_ECHOCAN: 03094 cp = (char *) data; 03095 if (*cp) { 03096 ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name); 03097 dahdi_enable_ec(p); 03098 } else { 03099 ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name); 03100 dahdi_disable_ec(p); 03101 } 03102 break; 03103 } 03104 errno = 0; 03105 03106 return 0; 03107 }
static int dahdi_show_channel | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 10255 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.
10256 { 10257 int channel; 10258 struct dahdi_pvt *tmp = NULL; 10259 struct dahdi_confinfo ci; 10260 struct dahdi_params ps; 10261 int x; 10262 ast_mutex_t *lock; 10263 struct dahdi_pvt *start; 10264 #ifdef HAVE_PRI 10265 char *c; 10266 int trunkgroup; 10267 struct dahdi_pri *pri=NULL; 10268 #endif 10269 10270 lock = &iflock; 10271 start = iflist; 10272 10273 if (argc != 4) 10274 return RESULT_SHOWUSAGE; 10275 #ifdef HAVE_PRI 10276 if ((c = strchr(argv[3], ':'))) { 10277 if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2) 10278 return RESULT_SHOWUSAGE; 10279 if ((trunkgroup < 1) || (channel < 1)) 10280 return RESULT_SHOWUSAGE; 10281 for (x = 0; x < NUM_SPANS; x++) { 10282 if (pris[x].trunkgroup == trunkgroup) { 10283 pri = pris + x; 10284 break; 10285 } 10286 } 10287 if (pri) { 10288 start = pri->crvs; 10289 lock = &pri->lock; 10290 } else { 10291 ast_cli(fd, "No such trunk group %d\n", trunkgroup); 10292 return RESULT_FAILURE; 10293 } 10294 } else 10295 #endif 10296 channel = atoi(argv[3]); 10297 10298 ast_mutex_lock(lock); 10299 tmp = start; 10300 while (tmp) { 10301 if (tmp->channel == channel) { 10302 #ifdef HAVE_PRI 10303 if (pri) 10304 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel); 10305 else 10306 #endif 10307 ast_cli(fd, "Channel: %d\n", tmp->channel); 10308 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd); 10309 ast_cli(fd, "Span: %d\n", tmp->span); 10310 ast_cli(fd, "Extension: %s\n", tmp->exten); 10311 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no"); 10312 ast_cli(fd, "Context: %s\n", tmp->context); 10313 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num); 10314 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton); 10315 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name); 10316 ast_cli(fd, "Destroy: %d\n", tmp->destroy); 10317 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm); 10318 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig)); 10319 ast_cli(fd, "Radio: %d\n", tmp->radio); 10320 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>"); 10321 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)" : ""); 10322 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)" : ""); 10323 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)" : ""); 10324 ast_cli(fd, "Confno: %d\n", tmp->confno); 10325 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno); 10326 ast_cli(fd, "Real in conference: %d\n", tmp->inconference); 10327 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no"); 10328 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no"); 10329 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas); 10330 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown"); 10331 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no"); 10332 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no"); 10333 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF"); 10334 if (tmp->master) 10335 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel); 10336 for (x = 0; x < MAX_SLAVES; x++) { 10337 if (tmp->slaves[x]) 10338 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel); 10339 } 10340 #ifdef HAVE_PRI 10341 if (tmp->pri) { 10342 ast_cli(fd, "PRI Flags: "); 10343 if (tmp->resetting) 10344 ast_cli(fd, "Resetting "); 10345 if (tmp->call) 10346 ast_cli(fd, "Call "); 10347 if (tmp->bearer) 10348 ast_cli(fd, "Bearer "); 10349 ast_cli(fd, "\n"); 10350 if (tmp->logicalspan) 10351 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan); 10352 else 10353 ast_cli(fd, "PRI Logical Span: Implicit\n"); 10354 } 10355 10356 #endif 10357 memset(&ci, 0, sizeof(ci)); 10358 ps.channo = tmp->channel; 10359 if (tmp->subs[SUB_REAL].dfd > -1) { 10360 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 10361 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode); 10362 } 10363 #ifdef DAHDI_GETCONFMUTE 10364 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) { 10365 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No"); 10366 } 10367 #endif 10368 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 10369 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno)); 10370 } else { 10371 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook"); 10372 } 10373 } 10374 if (ISTRUNK(tmp)) { 10375 ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no"); 10376 if (!ast_strlen_zero(progzone)) 10377 ast_cli(fd, "Progress Zone: %s\n", progzone); 10378 ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no"); 10379 if(tmp->busydetect) { 10380 ast_cli(fd, "Busy Count: %d\n", tmp->busycount); 10381 if(tmp->busytonelength > 0) { 10382 ast_cli(fd, "Busy Pattern:\n"); 10383 ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength); 10384 if (tmp->busyquietlength > 0) 10385 ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength); 10386 else 10387 ast_cli(fd, " -- Detect Tone Only\n"); 10388 if(tmp->busyfuzziness > 0) 10389 ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness); 10390 } 10391 } 10392 } 10393 ast_mutex_unlock(lock); 10394 return RESULT_SUCCESS; 10395 } 10396 tmp = tmp->next; 10397 } 10398 10399 ast_cli(fd, "Unable to find given channel %d\n", channel); 10400 ast_mutex_unlock(lock); 10401 return RESULT_FAILURE; 10402 }
static int dahdi_show_channels | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 10194 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.
10195 { 10196 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" 10197 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" 10198 struct dahdi_pvt *tmp = NULL; 10199 char tmps[20] = ""; 10200 ast_mutex_t *lock; 10201 struct dahdi_pvt *start; 10202 #ifdef HAVE_PRI 10203 int trunkgroup; 10204 struct dahdi_pri *pri = NULL; 10205 int x; 10206 #endif 10207 10208 lock = &iflock; 10209 start = iflist; 10210 10211 #ifdef HAVE_PRI 10212 if (argc == 4) { 10213 if ((trunkgroup = atoi(argv[3])) < 1) 10214 return RESULT_SHOWUSAGE; 10215 for (x = 0; x < NUM_SPANS; x++) { 10216 if (pris[x].trunkgroup == trunkgroup) { 10217 pri = pris + x; 10218 break; 10219 } 10220 } 10221 if (pri) { 10222 start = pri->crvs; 10223 lock = &pri->lock; 10224 } else { 10225 ast_cli(fd, "No such trunk group %d\n", trunkgroup); 10226 return RESULT_FAILURE; 10227 } 10228 } else 10229 #endif 10230 if (argc != 3) 10231 return RESULT_SHOWUSAGE; 10232 10233 ast_mutex_lock(lock); 10234 #ifdef HAVE_PRI 10235 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret"); 10236 #else 10237 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret"); 10238 #endif 10239 10240 tmp = start; 10241 while (tmp) { 10242 if (tmp->channel > 0) { 10243 snprintf(tmps, sizeof(tmps), "%d", tmp->channel); 10244 } else 10245 ast_copy_string(tmps, "pseudo", sizeof(tmps)); 10246 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret); 10247 tmp = tmp->next; 10248 } 10249 ast_mutex_unlock(lock); 10250 return RESULT_SUCCESS; 10251 #undef FORMAT 10252 #undef FORMAT2 10253 }
static int dahdi_show_status | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10435 of file chan_dahdi.c.
References alarms, ast_cli(), ast_log(), DAHDI_FILE_CTL, errno, FORMAT, FORMAT2, RESULT_FAILURE, and dahdi_pri::span.
10435 { 10436 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n" 10437 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n" 10438 10439 int span; 10440 int res; 10441 char alarms[50]; 10442 10443 int ctl; 10444 struct dahdi_spaninfo s; 10445 10446 if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) { 10447 ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno)); 10448 ast_cli(fd, "No " DAHDI_NAME " interface found.\n"); 10449 return RESULT_FAILURE; 10450 } 10451 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4"); 10452 10453 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 10454 s.spanno = span; 10455 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 10456 if (res) { 10457 continue; 10458 } 10459 alarms[0] = '\0'; 10460 if (s.alarms > 0) { 10461 if (s.alarms & DAHDI_ALARM_BLUE) 10462 strcat(alarms, "BLU/"); 10463 if (s.alarms & DAHDI_ALARM_YELLOW) 10464 strcat(alarms, "YEL/"); 10465 if (s.alarms & DAHDI_ALARM_RED) 10466 strcat(alarms, "RED/"); 10467 if (s.alarms & DAHDI_ALARM_LOOPBACK) 10468 strcat(alarms, "LB/"); 10469 if (s.alarms & DAHDI_ALARM_RECOVER) 10470 strcat(alarms, "REC/"); 10471 if (s.alarms & DAHDI_ALARM_NOTOPEN) 10472 strcat(alarms, "NOP/"); 10473 if (!strlen(alarms)) 10474 strcat(alarms, "UUU/"); 10475 if (strlen(alarms)) { 10476 /* Strip trailing / */ 10477 alarms[strlen(alarms) - 1] = '\0'; 10478 } 10479 } else { 10480 if (s.numchans) 10481 strcpy(alarms, "OK"); 10482 else 10483 strcpy(alarms, "UNCONFIGURED"); 10484 } 10485 10486 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count); 10487 } 10488 close(ctl); 10489 10490 return RESULT_SUCCESS; 10491 #undef FORMAT 10492 #undef FORMAT2 10493 }
static char* dahdi_sig2str | ( | int | sig | ) | [static] |
Definition at line 1210 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.
01211 { 01212 static char buf[256]; 01213 switch (sig) { 01214 case SIG_EM: 01215 return "E & M Immediate"; 01216 case SIG_EMWINK: 01217 return "E & M Wink"; 01218 case SIG_EM_E1: 01219 return "E & M E1"; 01220 case SIG_FEATD: 01221 return "Feature Group D (DTMF)"; 01222 case SIG_FEATDMF: 01223 return "Feature Group D (MF)"; 01224 case SIG_FEATDMF_TA: 01225 return "Feature Groud D (MF) Tandem Access"; 01226 case SIG_FEATB: 01227 return "Feature Group B (MF)"; 01228 case SIG_E911: 01229 return "E911 (MF)"; 01230 case SIG_FGC_CAMA: 01231 return "FGC/CAMA (Dialpulse)"; 01232 case SIG_FGC_CAMAMF: 01233 return "FGC/CAMA (MF)"; 01234 case SIG_FXSLS: 01235 return "FXS Loopstart"; 01236 case SIG_FXSGS: 01237 return "FXS Groundstart"; 01238 case SIG_FXSKS: 01239 return "FXS Kewlstart"; 01240 case SIG_FXOLS: 01241 return "FXO Loopstart"; 01242 case SIG_FXOGS: 01243 return "FXO Groundstart"; 01244 case SIG_FXOKS: 01245 return "FXO Kewlstart"; 01246 case SIG_PRI: 01247 return "ISDN PRI"; 01248 case SIG_SF: 01249 return "SF (Tone) Immediate"; 01250 case SIG_SFWINK: 01251 return "SF (Tone) Wink"; 01252 case SIG_SF_FEATD: 01253 return "SF (Tone) with Feature Group D (DTMF)"; 01254 case SIG_SF_FEATDMF: 01255 return "SF (Tone) with Feature Group D (MF)"; 01256 case SIG_SF_FEATB: 01257 return "SF (Tone) with Feature Group B (MF)"; 01258 case SIG_GR303FXOKS: 01259 return "GR-303 with FXOKS"; 01260 case SIG_GR303FXSKS: 01261 return "GR-303 with FXSKS"; 01262 case 0: 01263 return "Pseudo"; 01264 default: 01265 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig); 01266 return buf; 01267 } 01268 }
static void dahdi_softhangup_all | ( | void | ) | [static] |
Definition at line 10061 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().
10062 { 10063 struct dahdi_pvt *p; 10064 retry: 10065 ast_mutex_lock(&iflock); 10066 for (p = iflist; p; p = p->next) { 10067 ast_mutex_lock(&p->lock); 10068 if (p->owner && !p->restartpending) { 10069 if (ast_channel_trylock(p->owner)) { 10070 if (option_debug > 2) 10071 ast_verbose("Avoiding deadlock\n"); 10072 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */ 10073 ast_mutex_unlock(&p->lock); 10074 ast_mutex_unlock(&iflock); 10075 goto retry; 10076 } 10077 if (option_debug > 2) 10078 ast_verbose("Softhanging up on %s\n", p->owner->name); 10079 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT); 10080 p->restartpending = 1; 10081 num_restart_pending++; 10082 ast_channel_unlock(p->owner); 10083 } 10084 ast_mutex_unlock(&p->lock); 10085 } 10086 ast_mutex_unlock(&iflock); 10087 }
static void dahdi_train_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1491 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().
01492 { 01493 int x; 01494 int res; 01495 if (p && p->echocancel && p->echotraining) { 01496 x = p->echotraining; 01497 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x); 01498 if (res) 01499 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno)); 01500 else { 01501 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel); 01502 } 01503 } else 01504 ast_log(LOG_DEBUG, "No echo training requested\n"); 01505 }
static void dahdi_unlink | ( | struct dahdi_pvt * | slave, | |
struct dahdi_pvt * | master, | |||
int | needlock | |||
) | [static] |
Definition at line 3128 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().
03129 { 03130 /* Unlink a specific slave or all slaves/masters from a given master */ 03131 int x; 03132 int hasslaves; 03133 if (!master) 03134 return; 03135 if (needlock) { 03136 ast_mutex_lock(&master->lock); 03137 if (slave) { 03138 while (ast_mutex_trylock(&slave->lock)) { 03139 DEADLOCK_AVOIDANCE(&master->lock); 03140 } 03141 } 03142 } 03143 hasslaves = 0; 03144 for (x = 0; x < MAX_SLAVES; x++) { 03145 if (master->slaves[x]) { 03146 if (!slave || (master->slaves[x] == slave)) { 03147 /* Take slave out of the conference */ 03148 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel); 03149 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL); 03150 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL); 03151 master->slaves[x]->master = NULL; 03152 master->slaves[x] = NULL; 03153 } else 03154 hasslaves = 1; 03155 } 03156 if (!hasslaves) 03157 master->inconference = 0; 03158 } 03159 if (!slave) { 03160 if (master->master) { 03161 /* Take master out of the conference */ 03162 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL); 03163 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL); 03164 hasslaves = 0; 03165 for (x = 0; x < MAX_SLAVES; x++) { 03166 if (master->master->slaves[x] == master) 03167 master->master->slaves[x] = NULL; 03168 else if (master->master->slaves[x]) 03169 hasslaves = 1; 03170 } 03171 if (!hasslaves) 03172 master->master->inconference = 0; 03173 } 03174 master->master = NULL; 03175 } 03176 update_conf(master); 03177 if (needlock) { 03178 if (slave) 03179 ast_mutex_unlock(&slave->lock); 03180 ast_mutex_unlock(&master->lock); 03181 } 03182 }
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 5546 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by ss_thread().
05547 { 05548 int j; 05549 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK); 05550 for (;;) 05551 { 05552 /* set bits of interest */ 05553 j = DAHDI_IOMUX_SIGEVENT; 05554 /* wait for some happening */ 05555 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1); 05556 /* exit loop if we have it */ 05557 if (j & DAHDI_IOMUX_SIGEVENT) break; 05558 } 05559 /* get the event info */ 05560 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1); 05561 return 0; 05562 }
static int dahdi_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 5073 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.
05074 { 05075 struct dahdi_pvt *p = ast->tech_pvt; 05076 int res; 05077 int index; 05078 index = dahdi_get_index(ast, p, 0); 05079 if (index < 0) { 05080 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name); 05081 return -1; 05082 } 05083 05084 #if 0 05085 #ifdef HAVE_PRI 05086 ast_mutex_lock(&p->lock); 05087 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { 05088 if (p->pri->pri) { 05089 if (!pri_grab(p, p->pri)) { 05090 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 05091 pri_rel(p->pri); 05092 } else 05093 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05094 } 05095 p->proceeding=1; 05096 } 05097 ast_mutex_unlock(&p->lock); 05098 #endif 05099 #endif 05100 /* Write a frame of (presumably voice) data */ 05101 if (frame->frametype != AST_FRAME_VOICE) { 05102 if (frame->frametype != AST_FRAME_IMAGE) 05103 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); 05104 return 0; 05105 } 05106 if ((frame->subclass != AST_FORMAT_SLINEAR) && 05107 (frame->subclass != AST_FORMAT_ULAW) && 05108 (frame->subclass != AST_FORMAT_ALAW)) { 05109 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass); 05110 return -1; 05111 } 05112 if (p->dialing) { 05113 if (option_debug) 05114 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name); 05115 return 0; 05116 } 05117 if (!p->owner) { 05118 if (option_debug) 05119 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name); 05120 return 0; 05121 } 05122 if (p->cidspill) { 05123 if (option_debug) 05124 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n"); 05125 return 0; 05126 } 05127 /* Return if it's not valid data */ 05128 if (!frame->data || !frame->datalen) 05129 return 0; 05130 05131 if (frame->subclass == AST_FORMAT_SLINEAR) { 05132 if (!p->subs[index].linear) { 05133 p->subs[index].linear = 1; 05134 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 05135 if (res) 05136 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel); 05137 } 05138 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1); 05139 } else { 05140 /* x-law already */ 05141 if (p->subs[index].linear) { 05142 p->subs[index].linear = 0; 05143 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 05144 if (res) 05145 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel); 05146 } 05147 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0); 05148 } 05149 if (res < 0) { 05150 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 05151 return -1; 05152 } 05153 return 0; 05154 }
static void destroy_all_channels | ( | void | ) | [static] |
Definition at line 2331 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().
02332 { 02333 int x; 02334 struct dahdi_pvt *p, *pl; 02335 02336 while (num_restart_pending) { 02337 usleep(1); 02338 } 02339 02340 ast_mutex_lock(&iflock); 02341 /* Destroy all the interfaces and free their memory */ 02342 p = iflist; 02343 while (p) { 02344 /* Free any callerid */ 02345 if (p->cidspill) 02346 ast_free(p->cidspill); 02347 pl = p; 02348 p = p->next; 02349 x = pl->channel; 02350 /* Free associated memory */ 02351 if (pl) 02352 destroy_dahdi_pvt(&pl); 02353 if (option_verbose > 2) 02354 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x); 02355 } 02356 iflist = NULL; 02357 ifcount = 0; 02358 ast_mutex_unlock(&iflock); 02359 }
Definition at line 2281 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().
02282 { 02283 int owned = 0; 02284 int i = 0; 02285 02286 if (!now) { 02287 if (cur->owner) { 02288 owned = 1; 02289 } 02290 02291 for (i = 0; i < 3; i++) { 02292 if (cur->subs[i].owner) { 02293 owned = 1; 02294 } 02295 } 02296 if (!owned) { 02297 if (prev) { 02298 prev->next = cur->next; 02299 if (prev->next) 02300 prev->next->prev = prev; 02301 else 02302 ifend = prev; 02303 } else { 02304 iflist = cur->next; 02305 if (iflist) 02306 iflist->prev = NULL; 02307 else 02308 ifend = NULL; 02309 } 02310 destroy_dahdi_pvt(&cur); 02311 } 02312 } else { 02313 if (prev) { 02314 prev->next = cur->next; 02315 if (prev->next) 02316 prev->next->prev = prev; 02317 else 02318 ifend = prev; 02319 } else { 02320 iflist = cur->next; 02321 if (iflist) 02322 iflist->prev = NULL; 02323 else 02324 ifend = NULL; 02325 } 02326 destroy_dahdi_pvt(&cur); 02327 } 02328 return 0; 02329 }
static void destroy_dahdi_pvt | ( | struct dahdi_pvt ** | pvt | ) | [static] |
Definition at line 2263 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().
02264 { 02265 struct dahdi_pvt *p = *pvt; 02266 /* Remove channel from the list */ 02267 if (p->prev) 02268 p->prev->next = p->next; 02269 if (p->next) 02270 p->next->prev = p->prev; 02271 if (p->use_smdi) 02272 ast_smdi_interface_unref(p->smdi_iface); 02273 ast_mutex_destroy(&p->lock); 02274 dahdi_close_sub(p, SUB_REAL); 02275 if (p->owner) 02276 p->owner->tech_pvt = NULL; 02277 free(p); 02278 *pvt = NULL; 02279 }
static char* dialplan2str | ( | int | dialplan | ) | [static] |
Definition at line 1201 of file chan_dahdi.c.
Referenced by dahdi_call(), and mkintf().
01202 { 01203 if (dialplan == -1) { 01204 return("Dynamically set dialplan in ISDN"); 01205 } 01206 return (pri_plan2str(dialplan)); 01207 }
static int digit_to_dtmfindex | ( | char | digit | ) | [static] |
Definition at line 1034 of file chan_dahdi.c.
Referenced by dahdi_digit_begin().
01035 { 01036 if (isdigit(digit)) 01037 return DAHDI_TONE_DTMF_BASE + (digit - '0'); 01038 else if (digit >= 'A' && digit <= 'D') 01039 return DAHDI_TONE_DTMF_A + (digit - 'A'); 01040 else if (digit >= 'a' && digit <= 'd') 01041 return DAHDI_TONE_DTMF_A + (digit - 'a'); 01042 else if (digit == '*') 01043 return DAHDI_TONE_DTMF_s; 01044 else if (digit == '#') 01045 return DAHDI_TONE_DTMF_p; 01046 else 01047 return -1; 01048 }
static void disable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3207 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().
03208 { 03209 #ifdef DAHDI_TONEDETECT 03210 int val; 03211 #endif 03212 03213 p->ignoredtmf = 1; 03214 03215 #ifdef DAHDI_TONEDETECT 03216 val = 0; 03217 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 03218 #endif 03219 if (!p->hardwaredtmf && p->dsp) { 03220 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT; 03221 ast_dsp_set_features(p->dsp, p->dsp_features); 03222 } 03223 }
static void* do_idle_thread | ( | void * | vchan | ) | [static] |
Definition at line 8305 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().
08306 { 08307 struct ast_channel *chan = vchan; 08308 struct dahdi_pvt *pvt = chan->tech_pvt; 08309 struct ast_frame *f; 08310 char ex[80]; 08311 /* Wait up to 30 seconds for an answer */ 08312 int newms, ms = 30000; 08313 if (option_verbose > 2) 08314 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name); 08315 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial); 08316 if (ast_call(chan, ex, 0)) { 08317 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex); 08318 ast_hangup(chan); 08319 return NULL; 08320 } 08321 while ((newms = ast_waitfor(chan, ms)) > 0) { 08322 f = ast_read(chan); 08323 if (!f) { 08324 /* Got hangup */ 08325 break; 08326 } 08327 if (f->frametype == AST_FRAME_CONTROL) { 08328 switch (f->subclass) { 08329 case AST_CONTROL_ANSWER: 08330 /* Launch the PBX */ 08331 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten)); 08332 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context)); 08333 chan->priority = 1; 08334 if (option_verbose > 3) 08335 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context); 08336 ast_pbx_run(chan); 08337 /* It's already hungup, return immediately */ 08338 return NULL; 08339 case AST_CONTROL_BUSY: 08340 if (option_verbose > 3) 08341 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name); 08342 break; 08343 case AST_CONTROL_CONGESTION: 08344 if (option_verbose > 3) 08345 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name); 08346 break; 08347 }; 08348 } 08349 ast_frfree(f); 08350 ms = newms; 08351 } 08352 /* Hangup the channel since nothing happend */ 08353 ast_hangup(chan); 08354 return NULL; 08355 }
static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 6952 of file chan_dahdi.c.
References ast_calloc, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::cidspill, pollfd::events, pollfd::fd, free, iflist, iflock, last, LOG_DEBUG, dahdi_pvt::next, dahdi_pvt::owner, POLLIN, POLLPRI, dahdi_pvt::radio, pollfd::revents, dahdi_pvt::sig, SUB_REAL, and dahdi_pvt::subs.
Referenced by restart_monitor().
06953 { 06954 int count, res, res2, spoint, pollres=0; 06955 struct dahdi_pvt *i; 06956 struct dahdi_pvt *last = NULL; 06957 time_t thispass = 0, lastpass = 0; 06958 int found; 06959 char buf[1024]; 06960 struct pollfd *pfds=NULL; 06961 int lastalloc = -1; 06962 /* This thread monitors all the frame relay interfaces which are not yet in use 06963 (and thus do not have a separate thread) indefinitely */ 06964 /* From here on out, we die whenever asked */ 06965 #if 0 06966 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 06967 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 06968 return NULL; 06969 } 06970 ast_log(LOG_DEBUG, "Monitor starting...\n"); 06971 #endif 06972 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 06973 06974 for (;;) { 06975 /* Lock the interface list */ 06976 ast_mutex_lock(&iflock); 06977 if (!pfds || (lastalloc != ifcount)) { 06978 if (pfds) { 06979 free(pfds); 06980 pfds = NULL; 06981 } 06982 if (ifcount) { 06983 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) { 06984 ast_mutex_unlock(&iflock); 06985 return NULL; 06986 } 06987 } 06988 lastalloc = ifcount; 06989 } 06990 /* Build the stuff we're going to poll on, that is the socket of every 06991 dahdi_pvt that does not have an associated owner channel */ 06992 count = 0; 06993 i = iflist; 06994 while (i) { 06995 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) { 06996 if (!i->owner && !i->subs[SUB_REAL].owner) { 06997 /* This needs to be watched, as it lacks an owner */ 06998 pfds[count].fd = i->subs[SUB_REAL].dfd; 06999 pfds[count].events = POLLPRI; 07000 pfds[count].revents = 0; 07001 /* Message waiting or r2 channels also get watched for reading */ 07002 if (i->cidspill) 07003 pfds[count].events |= POLLIN; 07004 count++; 07005 } 07006 } 07007 i = i->next; 07008 } 07009 /* Okay, now that we know what to do, release the interface lock */ 07010 ast_mutex_unlock(&iflock); 07011 07012 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 07013 pthread_testcancel(); 07014 /* Wait at least a second for something to happen */ 07015 res = poll(pfds, count, 1000); 07016 pthread_testcancel(); 07017 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 07018 07019 /* Okay, poll has finished. Let's see what happened. */ 07020 if (res < 0) { 07021 if ((errno != EAGAIN) && (errno != EINTR)) 07022 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno)); 07023 continue; 07024 } 07025 /* Alright, lock the interface list again, and let's look and see what has 07026 happened */ 07027 ast_mutex_lock(&iflock); 07028 found = 0; 07029 spoint = 0; 07030 lastpass = thispass; 07031 thispass = time(NULL); 07032 i = iflist; 07033 while (i) { 07034 if (thispass != lastpass) { 07035 if (!found && ((i == last) || ((i == iflist) && !last))) { 07036 last = i; 07037 if (last) { 07038 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) && 07039 (last->sig & __DAHDI_SIG_FXO)) { 07040 res = ast_app_has_voicemail(last->mailbox, NULL); 07041 if (last->msgstate != res) { 07042 int x; 07043 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel); 07044 x = DAHDI_FLUSH_BOTH; 07045 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 07046 if (res2) 07047 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno)); 07048 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) { 07049 /* Turn on on hook transfer for 4 seconds */ 07050 x = 4000; 07051 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x); 07052 last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last)); 07053 last->cidpos = 0; 07054 last->msgstate = res; 07055 last->onhooktime = thispass; 07056 } 07057 found ++; 07058 } 07059 } 07060 last = last->next; 07061 } 07062 } 07063 } 07064 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) { 07065 if (i->radio && !i->owner) 07066 { 07067 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 07068 if (res) 07069 { 07070 if (option_debug) 07071 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel); 07072 /* Don't hold iflock while handling init events */ 07073 ast_mutex_unlock(&iflock); 07074 handle_init_event(i, res); 07075 ast_mutex_lock(&iflock); 07076 } 07077 i = i->next; 07078 continue; 07079 } 07080 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint); 07081 if (pollres & POLLIN) { 07082 if (i->owner || i->subs[SUB_REAL].owner) { 07083 #ifdef HAVE_PRI 07084 if (!i->pri) 07085 #endif 07086 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd); 07087 i = i->next; 07088 continue; 07089 } 07090 if (!i->cidspill) { 07091 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd); 07092 i = i->next; 07093 continue; 07094 } 07095 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf)); 07096 if (res > 0) { 07097 /* We read some number of bytes. Write an equal amount of data */ 07098 if (res > i->cidlen - i->cidpos) 07099 res = i->cidlen - i->cidpos; 07100 res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res); 07101 if (res2 > 0) { 07102 i->cidpos += res2; 07103 if (i->cidpos >= i->cidlen) { 07104 free(i->cidspill); 07105 i->cidspill = 0; 07106 i->cidpos = 0; 07107 i->cidlen = 0; 07108 } 07109 } else { 07110 ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno)); 07111 i->msgstate = -1; 07112 } 07113 } else { 07114 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno)); 07115 } 07116 } 07117 if (pollres & POLLPRI) { 07118 if (i->owner || i->subs[SUB_REAL].owner) { 07119 #ifdef HAVE_PRI 07120 if (!i->pri) 07121 #endif 07122 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd); 07123 i = i->next; 07124 continue; 07125 } 07126 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 07127 if (option_debug) 07128 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel); 07129 /* Don't hold iflock while handling init events */ 07130 ast_mutex_unlock(&iflock); 07131 handle_init_event(i, res); 07132 ast_mutex_lock(&iflock); 07133 } 07134 } 07135 i=i->next; 07136 } 07137 ast_mutex_unlock(&iflock); 07138 } 07139 /* Never reached */ 07140 return NULL; 07141 07142 }
static void enable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3225 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().
03226 { 03227 #ifdef DAHDI_TONEDETECT 03228 int val; 03229 #endif 03230 03231 if (p->channel == CHAN_PSEUDO) 03232 return; 03233 03234 p->ignoredtmf = 0; 03235 03236 #ifdef DAHDI_TONEDETECT 03237 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 03238 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 03239 #endif 03240 if (!p->hardwaredtmf && p->dsp) { 03241 p->dsp_features |= DSP_FEATURE_DTMF_DETECT; 03242 ast_dsp_set_features(p->dsp, p->dsp_features); 03243 } 03244 }
static char* event2str | ( | int | event | ) | [static] |
Definition at line 1191 of file chan_dahdi.c.
Referenced by __dahdi_exception(), dahdi_handle_event(), and ss_thread().
01192 { 01193 static char buf[256]; 01194 if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1)) 01195 return events[event]; 01196 sprintf(buf, "Event %d", event); /* safe */ 01197 return buf; 01198 }
static void fill_rxgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 1556 of file chan_dahdi.c.
References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_rxgain().
01557 { 01558 int j; 01559 int k; 01560 float linear_gain = pow(10.0, gain / 20.0); 01561 01562 switch (law) { 01563 case DAHDI_LAW_ALAW: 01564 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) { 01565 if (gain) { 01566 k = (int) (((float) AST_ALAW(j)) * linear_gain); 01567 if (k > 32767) k = 32767; 01568 if (k < -32767) k = -32767; 01569 g->rxgain[j] = AST_LIN2A(k); 01570 } else { 01571 g->rxgain[j] = j; 01572 } 01573 } 01574 break; 01575 case DAHDI_LAW_MULAW: 01576 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) { 01577 if (gain) { 01578 k = (int) (((float) AST_MULAW(j)) * linear_gain); 01579 if (k > 32767) k = 32767; 01580 if (k < -32767) k = -32767; 01581 g->rxgain[j] = AST_LIN2MU(k); 01582 } else { 01583 g->rxgain[j] = j; 01584 } 01585 } 01586 break; 01587 } 01588 }
static void fill_txgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 1522 of file chan_dahdi.c.
References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_txgain().
01523 { 01524 int j; 01525 int k; 01526 float linear_gain = pow(10.0, gain / 20.0); 01527 01528 switch (law) { 01529 case DAHDI_LAW_ALAW: 01530 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) { 01531 if (gain) { 01532 k = (int) (((float) AST_ALAW(j)) * linear_gain); 01533 if (k > 32767) k = 32767; 01534 if (k < -32767) k = -32767; 01535 g->txgain[j] = AST_LIN2A(k); 01536 } else { 01537 g->txgain[j] = j; 01538 } 01539 } 01540 break; 01541 case DAHDI_LAW_MULAW: 01542 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) { 01543 if (gain) { 01544 k = (int) (((float) AST_MULAW(j)) * linear_gain); 01545 if (k > 32767) k = 32767; 01546 if (k < -32767) k = -32767; 01547 g->txgain[j] = AST_LIN2MU(k); 01548 } else { 01549 g->txgain[j] = j; 01550 } 01551 } 01552 break; 01553 } 01554 }
static struct dahdi_pvt* find_channel | ( | int | channel | ) | [static] |
Definition at line 10593 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().
10594 { 10595 struct dahdi_pvt *p = iflist; 10596 while (p) { 10597 if (p->channel == channel) { 10598 break; 10599 } 10600 p = p->next; 10601 } 10602 return p; 10603 }
static int get_alarms | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3667 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().
03668 { 03669 int res; 03670 struct dahdi_spaninfo zi; 03671 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS) 03672 /* 03673 * The conditional compilation is needed only in asterisk-1.4 for 03674 * backward compatibility with old zaptel drivers that don't have 03675 * a DAHDI_PARAMS.chan_alarms field. 03676 */ 03677 struct dahdi_params params; 03678 #endif 03679 03680 memset(&zi, 0, sizeof(zi)); 03681 zi.spanno = p->span; 03682 03683 /* First check for span alarms */ 03684 if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) { 03685 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno)); 03686 return 0; 03687 } 03688 if (zi.alarms != DAHDI_ALARM_NONE) 03689 return zi.alarms; 03690 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS) 03691 /* No alarms on the span. Check for channel alarms. */ 03692 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0) 03693 return params.chan_alarms; 03694 /* ioctl failed */ 03695 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel); 03696 #endif 03697 return DAHDI_ALARM_NONE; 03698 }
static void handle_alarms | ( | struct dahdi_pvt * | p, | |
int | alarms | |||
) | [static] |
Definition at line 3782 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().
03783 { 03784 const char *alarm_str = alarm2str(alarms); 03785 03786 /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code 03787 * doesn't know what to do with it. Don't confuse users with log messages. */ 03788 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) { 03789 p->unknown_alarm = 1; 03790 return; 03791 } else { 03792 p->unknown_alarm = 0; 03793 } 03794 03795 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); 03796 manager_event(EVENT_FLAG_SYSTEM, "Alarm", 03797 "Alarm: %s\r\n" 03798 "Channel: %d\r\n", 03799 alarm_str, p->channel); 03800 }
static int handle_dahdi_show_cadences | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10408 of file chan_dahdi.c.
References ast_cli(), COLOR_BLACK, COLOR_GREEN, COLOR_MAGENTA, and term_color().
10409 { 10410 int i, j; 10411 for (i = 0; i < num_cadence; i++) { 10412 char output[1024]; 10413 char tmp[16], tmp2[64]; 10414 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1); 10415 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output)); 10416 10417 for (j = 0; j < 16; j++) { 10418 if (cadences[i].ringcadence[j] == 0) 10419 break; 10420 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]); 10421 if (cidrings[i] * 2 - 1 == j) 10422 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1); 10423 else 10424 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1); 10425 if (j != 0) 10426 strncat(output, ",", sizeof(output) - strlen(output) - 1); 10427 strncat(output, tmp2, sizeof(output) - strlen(output) - 1); 10428 } 10429 ast_cli(fd,"%s\n",output); 10430 } 10431 return 0; 10432 }
static int handle_init_event | ( | struct dahdi_pvt * | i, | |
int | event | |||
) | [static] |
Definition at line 6744 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.
06745 { 06746 int res; 06747 pthread_t threadid; 06748 pthread_attr_t attr; 06749 struct ast_channel *chan; 06750 pthread_attr_init(&attr); 06751 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 06752 /* Handle an event on a given channel for the monitor thread. */ 06753 switch (event) { 06754 case DAHDI_EVENT_NONE: 06755 case DAHDI_EVENT_BITSCHANGED: 06756 break; 06757 case DAHDI_EVENT_WINKFLASH: 06758 case DAHDI_EVENT_RINGOFFHOOK: 06759 if (i->inalarm) break; 06760 if (i->radio) break; 06761 /* Got a ring/answer. What kind of channel are we? */ 06762 switch (i->sig) { 06763 case SIG_FXOLS: 06764 case SIG_FXOGS: 06765 case SIG_FXOKS: 06766 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06767 if (res && (errno == EBUSY)) 06768 break; 06769 if (i->cidspill) { 06770 /* Cancel VMWI spill */ 06771 free(i->cidspill); 06772 i->cidspill = NULL; 06773 } 06774 if (i->immediate) { 06775 dahdi_enable_ec(i); 06776 /* The channel is immediately up. Start right away */ 06777 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 06778 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0); 06779 if (!chan) { 06780 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel); 06781 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 06782 if (res < 0) 06783 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 06784 } 06785 } else { 06786 /* Check for callerid, digits, etc */ 06787 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0); 06788 if (chan) { 06789 if (has_voicemail(i)) 06790 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 06791 else 06792 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 06793 if (res < 0) 06794 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel); 06795 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 06796 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 06797 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 06798 if (res < 0) 06799 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 06800 ast_hangup(chan); 06801 } 06802 } else 06803 ast_log(LOG_WARNING, "Unable to create channel\n"); 06804 } 06805 break; 06806 case SIG_FXSLS: 06807 case SIG_FXSGS: 06808 case SIG_FXSKS: 06809 i->ringt = i->ringt_base; 06810 /* Fall through */ 06811 case SIG_EMWINK: 06812 case SIG_FEATD: 06813 case SIG_FEATDMF: 06814 case SIG_FEATDMF_TA: 06815 case SIG_E911: 06816 case SIG_FGC_CAMA: 06817 case SIG_FGC_CAMAMF: 06818 case SIG_FEATB: 06819 case SIG_EM: 06820 case SIG_EM_E1: 06821 case SIG_SFWINK: 06822 case SIG_SF_FEATD: 06823 case SIG_SF_FEATDMF: 06824 case SIG_SF_FEATB: 06825 case SIG_SF: 06826 /* Check for callerid, digits, etc */ 06827 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0); 06828 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 06829 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 06830 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 06831 if (res < 0) 06832 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 06833 ast_hangup(chan); 06834 } else if (!chan) { 06835 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 06836 } 06837 break; 06838 default: 06839 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 06840 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 06841 if (res < 0) 06842 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 06843 return -1; 06844 } 06845 break; 06846 case DAHDI_EVENT_NOALARM: 06847 i->inalarm = 0; 06848 if (!i->unknown_alarm) { 06849 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel); 06850 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 06851 "Channel: %d\r\n", i->channel); 06852 } else { 06853 i->unknown_alarm = 0; 06854 } 06855 break; 06856 case DAHDI_EVENT_ALARM: 06857 i->inalarm = 1; 06858 res = get_alarms(i); 06859 handle_alarms(i, res); 06860 /* fall thru intentionally */ 06861 case DAHDI_EVENT_ONHOOK: 06862 if (i->radio) 06863 break; 06864 /* Back on hook. Hang up. */ 06865 switch (i->sig) { 06866 case SIG_FXOLS: 06867 case SIG_FXOGS: 06868 case SIG_FEATD: 06869 case SIG_FEATDMF: 06870 case SIG_FEATDMF_TA: 06871 case SIG_E911: 06872 case SIG_FGC_CAMA: 06873 case SIG_FGC_CAMAMF: 06874 case SIG_FEATB: 06875 case SIG_EM: 06876 case SIG_EM_E1: 06877 case SIG_EMWINK: 06878 case SIG_SF_FEATD: 06879 case SIG_SF_FEATDMF: 06880 case SIG_SF_FEATB: 06881 case SIG_SF: 06882 case SIG_SFWINK: 06883 case SIG_FXSLS: 06884 case SIG_FXSGS: 06885 case SIG_FXSKS: 06886 case SIG_GR303FXSKS: 06887 dahdi_disable_ec(i); 06888 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 06889 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 06890 break; 06891 case SIG_GR303FXOKS: 06892 case SIG_FXOKS: 06893 dahdi_disable_ec(i); 06894 /* Diddle the battery for the zhone */ 06895 #ifdef ZHONE_HACK 06896 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06897 usleep(1); 06898 #endif 06899 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 06900 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 06901 break; 06902 case SIG_PRI: 06903 dahdi_disable_ec(i); 06904 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 06905 break; 06906 default: 06907 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 06908 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 06909 return -1; 06910 } 06911 break; 06912 case DAHDI_EVENT_POLARITY: 06913 switch (i->sig) { 06914 case SIG_FXSLS: 06915 case SIG_FXSKS: 06916 case SIG_FXSGS: 06917 /* We have already got a PR before the channel was 06918 created, but it wasn't handled. We need polarity 06919 to be REV for remote hangup detection to work. 06920 At least in Spain */ 06921 if (i->hanguponpolarityswitch) 06922 i->polarity = POLARITY_REV; 06923 06924 if (i->cid_start == CID_START_POLARITY) { 06925 i->polarity = POLARITY_REV; 06926 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity " 06927 "CID detection on channel %d\n", 06928 i->channel); 06929 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 06930 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 06931 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 06932 } 06933 } 06934 break; 06935 default: 06936 ast_log(LOG_WARNING, "handle_init_event detected " 06937 "polarity reversal on non-FXO (SIG_FXS) " 06938 "interface %d\n", i->channel); 06939 } 06940 break; 06941 case DAHDI_EVENT_REMOVED: /* destroy channel */ 06942 ast_log(LOG_NOTICE, 06943 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 06944 i->channel); 06945 dahdi_destroy_channel_bynum(i->channel); 06946 break; 06947 } 06948 pthread_attr_destroy(&attr); 06949 return 0; 06950 }
static int handle_pri_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 9804 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
09805 { 09806 int span; 09807 int x; 09808 if (argc < 4) { 09809 return RESULT_SHOWUSAGE; 09810 } 09811 span = atoi(argv[3]); 09812 if ((span < 1) || (span > NUM_SPANS)) { 09813 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS); 09814 return RESULT_SUCCESS; 09815 } 09816 if (!pris[span-1].pri) { 09817 ast_cli(fd, "No PRI running on span %d\n", span); 09818 return RESULT_SUCCESS; 09819 } 09820 for (x = 0; x < NUM_DCHANS; x++) { 09821 if (pris[span-1].dchans[x]) 09822 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 09823 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 09824 PRI_DEBUG_Q921_STATE); 09825 } 09826 ast_cli(fd, "Enabled debugging on span %d\n", span); 09827 return RESULT_SUCCESS; 09828 }
static int handle_pri_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 9832 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
09833 { 09834 int span; 09835 int x; 09836 if (argc < 5) 09837 return RESULT_SHOWUSAGE; 09838 span = atoi(argv[4]); 09839 if ((span < 1) || (span > NUM_SPANS)) { 09840 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS); 09841 return RESULT_SUCCESS; 09842 } 09843 if (!pris[span-1].pri) { 09844 ast_cli(fd, "No PRI running on span %d\n", span); 09845 return RESULT_SUCCESS; 09846 } 09847 for (x = 0; x < NUM_DCHANS; x++) { 09848 if (pris[span-1].dchans[x]) 09849 pri_set_debug(pris[span-1].dchans[x], 0); 09850 } 09851 ast_cli(fd, "Disabled debugging on span %d\n", span); 09852 return RESULT_SUCCESS; 09853 }
static int handle_pri_really_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 9855 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
09856 { 09857 int span; 09858 int x; 09859 if (argc < 5) 09860 return RESULT_SHOWUSAGE; 09861 span = atoi(argv[4]); 09862 if ((span < 1) || (span > NUM_SPANS)) { 09863 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS); 09864 return RESULT_SUCCESS; 09865 } 09866 if (!pris[span-1].pri) { 09867 ast_cli(fd, "No PRI running on span %d\n", span); 09868 return RESULT_SUCCESS; 09869 } 09870 for (x = 0; x < NUM_DCHANS; x++) { 09871 if (pris[span-1].dchans[x]) 09872 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 09873 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 09874 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE); 09875 } 09876 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span); 09877 return RESULT_SUCCESS; 09878 }
static int handle_pri_set_debug_file | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 9757 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.
09758 { 09759 int myfd; 09760 09761 if (!strncasecmp(argv[1], "set", 3)) { 09762 if (argc < 5) 09763 return RESULT_SHOWUSAGE; 09764 09765 if (ast_strlen_zero(argv[4])) 09766 return RESULT_SHOWUSAGE; 09767 09768 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600); 09769 if (myfd < 0) { 09770 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]); 09771 return RESULT_SUCCESS; 09772 } 09773 09774 ast_mutex_lock(&pridebugfdlock); 09775 09776 if (pridebugfd >= 0) 09777 close(pridebugfd); 09778 09779 pridebugfd = myfd; 09780 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename)); 09781 09782 ast_mutex_unlock(&pridebugfdlock); 09783 09784 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]); 09785 } else { 09786 /* Assume it is unset */ 09787 ast_mutex_lock(&pridebugfdlock); 09788 close(pridebugfd); 09789 pridebugfd = -1; 09790 ast_cli(fd, "PRI debug output to file disabled\n"); 09791 ast_mutex_unlock(&pridebugfdlock); 09792 } 09793 09794 return RESULT_SUCCESS; 09795 }
static int handle_pri_show_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 9961 of file chan_dahdi.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), debug, NUM_SPANS, pridebugfdlock, pris, and RESULT_SUCCESS.
09962 { 09963 int x; 09964 int span; 09965 int count=0; 09966 int debug=0; 09967 09968 for (span = 0; span < NUM_SPANS; span++) { 09969 if (pris[span].pri) { 09970 for (x = 0; x < NUM_DCHANS; x++) { 09971 debug = 0; 09972 if (pris[span].dchans[x]) { 09973 debug = pri_get_debug(pris[span].dchans[x]); 09974 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" ); 09975 count++; 09976 } 09977 } 09978 } 09979 09980 } 09981 ast_mutex_lock(&pridebugfdlock); 09982 if (pridebugfd >= 0) 09983 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename); 09984 ast_mutex_unlock(&pridebugfdlock); 09985 09986 if (!count) 09987 ast_cli(fd, "No debug set or no PRI running\n"); 09988 return RESULT_SUCCESS; 09989 }
static int handle_pri_show_span | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 9922 of file chan_dahdi.c.
References ast_cli(), build_status(), free, NUM_SPANS, pri_order(), pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
09923 { 09924 int span; 09925 int x; 09926 char status[256]; 09927 if (argc < 4) 09928 return RESULT_SHOWUSAGE; 09929 span = atoi(argv[3]); 09930 if ((span < 1) || (span > NUM_SPANS)) { 09931 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS); 09932 return RESULT_SUCCESS; 09933 } 09934 if (!pris[span-1].pri) { 09935 ast_cli(fd, "No PRI running on span %d\n", span); 09936 return RESULT_SUCCESS; 09937 } 09938 for (x = 0; x < NUM_DCHANS; x++) { 09939 if (pris[span-1].dchannels[x]) { 09940 #ifdef PRI_DUMP_INFO_STR 09941 char *info_str = NULL; 09942 #endif 09943 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]); 09944 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri); 09945 ast_cli(fd, "Status: %s\n", status); 09946 #ifdef PRI_DUMP_INFO_STR 09947 info_str = pri_dump_info_str(pris[span-1].pri); 09948 if (info_str) { 09949 ast_cli(fd, "%s", info_str); 09950 free(info_str); 09951 } 09952 #else 09953 pri_dump_info(pris[span-1].pri); 09954 #endif 09955 ast_cli(fd, "\n"); 09956 } 09957 } 09958 return RESULT_SUCCESS; 09959 }
static int handle_pri_show_spans | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 9901 of file chan_dahdi.c.
References ast_cli(), build_status(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
09902 { 09903 int span; 09904 int x; 09905 char status[256]; 09906 if (argc != 3) 09907 return RESULT_SHOWUSAGE; 09908 09909 for (span = 0; span < NUM_SPANS; span++) { 09910 if (pris[span].pri) { 09911 for (x = 0; x < NUM_DCHANS; x++) { 09912 if (pris[span].dchannels[x]) { 09913 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri); 09914 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status); 09915 } 09916 } 09917 } 09918 } 09919 return RESULT_SUCCESS; 09920 }
static int handle_pri_version | ( | int | fd, | |
int | agc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 9798 of file chan_dahdi.c.
References ast_cli(), and RESULT_SUCCESS.
09798 { 09799 ast_cli(fd, "libpri version: %s\n", pri_get_version()); 09800 return RESULT_SUCCESS; 09801 }
static int has_voicemail | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1754 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().
01755 { 01756 01757 return ast_app_has_voicemail(p->mailbox, NULL); 01758 }
static int isourconf | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c | |||
) | [static] |
Definition at line 1310 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::confno, and dahdi_subchannel::curconf.
Referenced by conf_del().
01311 { 01312 /* If they're listening to our channel, they're ours */ 01313 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON)) 01314 return 1; 01315 /* If they're a talker on our (allocated) conference, they're ours */ 01316 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER)) 01317 return 1; 01318 return 0; 01319 }
Definition at line 1343 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().
01344 { 01345 int x; 01346 int useslavenative; 01347 struct dahdi_pvt *slave = NULL; 01348 /* Start out optimistic */ 01349 useslavenative = 1; 01350 /* Update conference state in a stateless fashion */ 01351 for (x = 0; x < 3; x++) { 01352 /* Any three-way calling makes slave native mode *definitely* out 01353 of the question */ 01354 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) 01355 useslavenative = 0; 01356 } 01357 /* If we don't have any 3-way calls, check to see if we have 01358 precisely one slave */ 01359 if (useslavenative) { 01360 for (x = 0; x < MAX_SLAVES; x++) { 01361 if (p->slaves[x]) { 01362 if (slave) { 01363 /* Whoops already have a slave! No 01364 slave native and stop right away */ 01365 slave = NULL; 01366 useslavenative = 0; 01367 break; 01368 } else { 01369 /* We have one slave so far */ 01370 slave = p->slaves[x]; 01371 } 01372 } 01373 } 01374 } 01375 /* If no slave, slave native definitely out */ 01376 if (!slave) 01377 useslavenative = 0; 01378 else if (slave->law != p->law) { 01379 useslavenative = 0; 01380 slave = NULL; 01381 } 01382 if (out) 01383 *out = slave; 01384 return useslavenative; 01385 }
static int load_module | ( | void | ) | [static] |
Definition at line 11849 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.
11850 { 11851 int res; 11852 11853 #ifdef HAVE_PRI 11854 int y,i; 11855 memset(pris, 0, sizeof(pris)); 11856 for (y = 0; y < NUM_SPANS; y++) { 11857 ast_mutex_init(&pris[y].lock); 11858 pris[y].offset = -1; 11859 pris[y].master = AST_PTHREADT_NULL; 11860 for (i = 0; i < NUM_DCHANS; i++) 11861 pris[y].fds[i] = -1; 11862 } 11863 pri_set_error(dahdi_pri_error); 11864 pri_set_message(dahdi_pri_message); 11865 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 11866 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec, 11867 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip); 11868 } 11869 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec, 11870 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip); 11871 #endif 11872 if ((res = setup_dahdi(0))) { 11873 return AST_MODULE_LOAD_DECLINE; 11874 } 11875 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 11876 chan_tech = &dahdi_tech; 11877 } else { 11878 chan_tech = &zap_tech; 11879 } 11880 if (ast_channel_register(chan_tech)) { 11881 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type); 11882 __unload_module(); 11883 return -1; 11884 } 11885 #ifdef HAVE_PRI 11886 ast_string_field_init(&inuse, 16); 11887 ast_string_field_set(&inuse, name, "GR-303InUse"); 11888 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry)); 11889 #endif 11890 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 11891 11892 memset(round_robin, 0, sizeof(round_robin)); 11893 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel"); 11894 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel"); 11895 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook"); 11896 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON"); 11897 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF"); 11898 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels"); 11899 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)"); 11900 11901 ast_cond_init(&ss_thread_complete, NULL); 11902 11903 return res; 11904 }
static struct dahdi_pvt* mkintf | ( | int | channel, | |
const struct dahdi_chan_conf * | conf, | |||
struct dahdi_pri * | pri, | |||
int | reloading | |||
) | [static] |
Definition at line 7298 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().
07299 { 07300 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */ 07301 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL; 07302 char fn[80]; 07303 #if 1 07304 struct dahdi_bufferinfo bi; 07305 #endif 07306 int res; 07307 int span=0; 07308 int here = 0; 07309 int x; 07310 struct dahdi_pvt **wlist; 07311 struct dahdi_pvt **wend; 07312 struct dahdi_params p; 07313 07314 wlist = &iflist; 07315 wend = &ifend; 07316 07317 #ifdef HAVE_PRI 07318 if (pri) { 07319 wlist = &pri->crvs; 07320 wend = &pri->crvend; 07321 } 07322 #endif 07323 07324 tmp2 = *wlist; 07325 prev = NULL; 07326 07327 while (tmp2) { 07328 if (!tmp2->destroy) { 07329 if (tmp2->channel == channel) { 07330 tmp = tmp2; 07331 here = 1; 07332 break; 07333 } 07334 if (tmp2->channel > channel) { 07335 break; 07336 } 07337 } 07338 prev = tmp2; 07339 tmp2 = tmp2->next; 07340 } 07341 07342 if (!here && reloading != 1) { 07343 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { 07344 if (tmp) 07345 free(tmp); 07346 return NULL; 07347 } 07348 ast_mutex_init(&tmp->lock); 07349 ifcount++; 07350 for (x = 0; x < 3; x++) 07351 tmp->subs[x].dfd = -1; 07352 tmp->channel = channel; 07353 } 07354 07355 if (tmp) { 07356 int chan_sig = conf->chan.sig; 07357 if (!here) { 07358 if ((channel != CHAN_PSEUDO) && !pri) { 07359 int count = 0; 07360 snprintf(fn, sizeof(fn), "%d", channel); 07361 /* Open non-blocking */ 07362 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 07363 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 */ 07364 usleep(1); 07365 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 07366 count++; 07367 } 07368 /* Allocate a DAHDI structure */ 07369 if (tmp->subs[SUB_REAL].dfd < 0) { 07370 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); 07371 destroy_dahdi_pvt(&tmp); 07372 return NULL; 07373 } 07374 memset(&p, 0, sizeof(p)); 07375 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 07376 if (res < 0) { 07377 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno)); 07378 destroy_dahdi_pvt(&tmp); 07379 return NULL; 07380 } 07381 if (p.sigtype != (conf->chan.sig & 0x3ffff)) { 07382 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)); 07383 destroy_dahdi_pvt(&tmp); 07384 return NULL; 07385 } 07386 tmp->law = p.curlaw; 07387 tmp->span = p.spanno; 07388 span = p.spanno - 1; 07389 } else { 07390 if (channel == CHAN_PSEUDO) 07391 chan_sig = 0; 07392 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) { 07393 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n"); 07394 return NULL; 07395 } 07396 } 07397 #ifdef HAVE_PRI 07398 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) { 07399 int offset; 07400 int myswitchtype; 07401 int matchesdchan; 07402 int x,y; 07403 offset = 0; 07404 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) { 07405 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 07406 destroy_dahdi_pvt(&tmp); 07407 return NULL; 07408 } 07409 if (span >= NUM_SPANS) { 07410 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span); 07411 destroy_dahdi_pvt(&tmp); 07412 return NULL; 07413 } else { 07414 struct dahdi_spaninfo si; 07415 si.spanno = 0; 07416 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) { 07417 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); 07418 destroy_dahdi_pvt(&tmp); 07419 return NULL; 07420 } 07421 /* Store the logical span first based upon the real span */ 07422 tmp->logicalspan = pris[span].prilogicalspan; 07423 pri_resolve_span(&span, channel, (channel - p.chanpos), &si); 07424 if (span < 0) { 07425 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel); 07426 destroy_dahdi_pvt(&tmp); 07427 return NULL; 07428 } 07429 if (chan_sig == SIG_PRI) 07430 myswitchtype = conf->pri.switchtype; 07431 else 07432 myswitchtype = PRI_SWITCH_GR303_TMC; 07433 /* Make sure this isn't a d-channel */ 07434 matchesdchan=0; 07435 for (x = 0; x < NUM_SPANS; x++) { 07436 for (y = 0; y < NUM_DCHANS; y++) { 07437 if (pris[x].dchannels[y] == tmp->channel) { 07438 matchesdchan = 1; 07439 break; 07440 } 07441 } 07442 } 07443 offset = p.chanpos; 07444 if (!matchesdchan) { 07445 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) { 07446 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype)); 07447 destroy_dahdi_pvt(&tmp); 07448 return NULL; 07449 } 07450 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) { 07451 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype)); 07452 destroy_dahdi_pvt(&tmp); 07453 return NULL; 07454 } 07455 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) { 07456 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan)); 07457 destroy_dahdi_pvt(&tmp); 07458 return NULL; 07459 } 07460 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) { 07461 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial); 07462 destroy_dahdi_pvt(&tmp); 07463 return NULL; 07464 } 07465 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) { 07466 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext); 07467 destroy_dahdi_pvt(&tmp); 07468 return NULL; 07469 } 07470 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) { 07471 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused); 07472 destroy_dahdi_pvt(&tmp); 07473 return NULL; 07474 } 07475 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) { 07476 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle); 07477 destroy_dahdi_pvt(&tmp); 07478 return NULL; 07479 } 07480 if (pris[span].numchans >= MAX_CHANNELS) { 07481 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, 07482 pris[span].trunkgroup); 07483 destroy_dahdi_pvt(&tmp); 07484 return NULL; 07485 } 07486 pris[span].nodetype = conf->pri.nodetype; 07487 pris[span].switchtype = myswitchtype; 07488 pris[span].nsf = conf->pri.nsf; 07489 pris[span].dialplan = conf->pri.dialplan; 07490 pris[span].localdialplan = conf->pri.localdialplan; 07491 pris[span].pvts[pris[span].numchans++] = tmp; 07492 pris[span].minunused = conf->pri.minunused; 07493 pris[span].minidle = conf->pri.minidle; 07494 pris[span].overlapdial = conf->pri.overlapdial; 07495 #ifdef HAVE_PRI_INBANDDISCONNECT 07496 pris[span].inbanddisconnect = conf->pri.inbanddisconnect; 07497 #endif 07498 pris[span].facilityenable = conf->pri.facilityenable; 07499 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial)); 07500 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext)); 07501 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix)); 07502 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix)); 07503 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix)); 07504 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix)); 07505 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix)); 07506 pris[span].resetinterval = conf->pri.resetinterval; 07507 07508 tmp->pri = &pris[span]; 07509 tmp->prioffset = offset; 07510 tmp->call = NULL; 07511 } else { 07512 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset); 07513 destroy_dahdi_pvt(&tmp); 07514 return NULL; 07515 } 07516 } 07517 } else { 07518 tmp->prioffset = 0; 07519 } 07520 #endif 07521 } else { 07522 chan_sig = tmp->sig; 07523 memset(&p, 0, sizeof(p)); 07524 if (tmp->subs[SUB_REAL].dfd > -1) 07525 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 07526 } 07527 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */ 07528 switch (chan_sig) { 07529 case SIG_FXSKS: 07530 case SIG_FXSLS: 07531 case SIG_EM: 07532 case SIG_EM_E1: 07533 case SIG_EMWINK: 07534 case SIG_FEATD: 07535 case SIG_FEATDMF: 07536 case SIG_FEATDMF_TA: 07537 case SIG_FEATB: 07538 case SIG_E911: 07539 case SIG_SF: 07540 case SIG_SFWINK: 07541 case SIG_FGC_CAMA: 07542 case SIG_FGC_CAMAMF: 07543 case SIG_SF_FEATD: 07544 case SIG_SF_FEATDMF: 07545 case SIG_SF_FEATB: 07546 p.starttime = 250; 07547 break; 07548 } 07549 07550 if (tmp->radio) { 07551 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */ 07552 p.channo = channel; 07553 p.rxwinktime = 1; 07554 p.rxflashtime = 1; 07555 p.starttime = 1; 07556 p.debouncetime = 5; 07557 } 07558 if (!tmp->radio) { 07559 p.channo = channel; 07560 /* Override timing settings based on config file */ 07561 if (conf->timing.prewinktime >= 0) 07562 p.prewinktime = conf->timing.prewinktime; 07563 if (conf->timing.preflashtime >= 0) 07564 p.preflashtime = conf->timing.preflashtime; 07565 if (conf->timing.winktime >= 0) 07566 p.winktime = conf->timing.winktime; 07567 if (conf->timing.flashtime >= 0) 07568 p.flashtime = conf->timing.flashtime; 07569 if (conf->timing.starttime >= 0) 07570 p.starttime = conf->timing.starttime; 07571 if (conf->timing.rxwinktime >= 0) 07572 p.rxwinktime = conf->timing.rxwinktime; 07573 if (conf->timing.rxflashtime >= 0) 07574 p.rxflashtime = conf->timing.rxflashtime; 07575 if (conf->timing.debouncetime >= 0) 07576 p.debouncetime = conf->timing.debouncetime; 07577 } 07578 07579 /* dont set parms on a pseudo-channel (or CRV) */ 07580 if (tmp->subs[SUB_REAL].dfd >= 0) 07581 { 07582 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p); 07583 if (res < 0) { 07584 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno)); 07585 destroy_dahdi_pvt(&tmp); 07586 return NULL; 07587 } 07588 } 07589 #if 1 07590 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) { 07591 memset(&bi, 0, sizeof(bi)); 07592 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 07593 if (!res) { 07594 bi.txbufpolicy = conf->chan.buf_policy; 07595 bi.rxbufpolicy = conf->chan.buf_policy; 07596 bi.numbufs = conf->chan.buf_no; 07597 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 07598 if (res < 0) { 07599 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno)); 07600 } 07601 } else 07602 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno)); 07603 } 07604 #endif 07605 tmp->immediate = conf->chan.immediate; 07606 tmp->transfertobusy = conf->chan.transfertobusy; 07607 tmp->sig = chan_sig; 07608 tmp->outsigmod = conf->chan.outsigmod; 07609 tmp->ringt_base = ringt_base; 07610 tmp->firstradio = 0; 07611 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS)) 07612 tmp->permcallwaiting = conf->chan.callwaiting; 07613 else 07614 tmp->permcallwaiting = 0; 07615 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */ 07616 tmp->destroy = 0; 07617 tmp->drings = drings; 07618 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection; 07619 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid; 07620 tmp->threewaycalling = conf->chan.threewaycalling; 07621 tmp->adsi = conf->chan.adsi; 07622 tmp->use_smdi = conf->chan.use_smdi; 07623 tmp->permhidecallerid = conf->chan.hidecallerid; 07624 tmp->callreturn = conf->chan.callreturn; 07625 tmp->echocancel = conf->chan.echocancel; 07626 tmp->echotraining = conf->chan.echotraining; 07627 tmp->pulse = conf->chan.pulse; 07628 if (tmp->echocancel) 07629 tmp->echocanbridged = conf->chan.echocanbridged; 07630 else { 07631 if (conf->chan.echocanbridged) 07632 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n"); 07633 tmp->echocanbridged = 0; 07634 } 07635 tmp->busydetect = conf->chan.busydetect; 07636 tmp->busycount = conf->chan.busycount; 07637 tmp->busycompare = conf->chan.busycompare; 07638 tmp->busytonelength = conf->chan.busytonelength; 07639 tmp->busyquietlength = conf->chan.busyquietlength; 07640 tmp->busyfuzziness = conf->chan.busyfuzziness; 07641 tmp->silencethreshold = conf->chan.silencethreshold; 07642 tmp->callprogress = conf->chan.callprogress; 07643 tmp->cancallforward = conf->chan.cancallforward; 07644 tmp->dtmfrelax = conf->chan.dtmfrelax; 07645 tmp->callwaiting = tmp->permcallwaiting; 07646 tmp->hidecallerid = tmp->permhidecallerid; 07647 tmp->channel = channel; 07648 tmp->stripmsd = conf->chan.stripmsd; 07649 tmp->use_callerid = conf->chan.use_callerid; 07650 tmp->cid_signalling = conf->chan.cid_signalling; 07651 tmp->cid_start = conf->chan.cid_start; 07652 tmp->dahditrcallerid = conf->chan.dahditrcallerid; 07653 tmp->restrictcid = conf->chan.restrictcid; 07654 tmp->use_callingpres = conf->chan.use_callingpres; 07655 tmp->priindication_oob = conf->chan.priindication_oob; 07656 tmp->priexclusive = conf->chan.priexclusive; 07657 if (tmp->usedistinctiveringdetection) { 07658 if (!tmp->use_callerid) { 07659 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n"); 07660 tmp->use_callerid = 1; 07661 } 07662 } 07663 07664 if (tmp->cid_signalling == CID_SIG_SMDI) { 07665 if (!tmp->use_smdi) { 07666 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n"); 07667 tmp->use_smdi = 1; 07668 } 07669 } 07670 if (tmp->use_smdi) { 07671 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port); 07672 if (!(tmp->smdi_iface)) { 07673 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n"); 07674 tmp->use_smdi = 0; 07675 } 07676 } 07677 07678 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode)); 07679 tmp->amaflags = conf->chan.amaflags; 07680 if (!here) { 07681 tmp->confno = -1; 07682 tmp->propconfno = -1; 07683 } 07684 tmp->canpark = conf->chan.canpark; 07685 tmp->transfer = conf->chan.transfer; 07686 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext)); 07687 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language)); 07688 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret)); 07689 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest)); 07690 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context)); 07691 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num)); 07692 tmp->cid_ton = 0; 07693 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name)); 07694 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox)); 07695 tmp->msgstate = -1; 07696 tmp->group = conf->chan.group; 07697 tmp->callgroup = conf->chan.callgroup; 07698 tmp->pickupgroup= conf->chan.pickupgroup; 07699 tmp->rxgain = conf->chan.rxgain; 07700 tmp->txgain = conf->chan.txgain; 07701 tmp->tonezone = conf->chan.tonezone; 07702 tmp->onhooktime = time(NULL); 07703 if (tmp->subs[SUB_REAL].dfd > -1) { 07704 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law); 07705 if (tmp->dsp) 07706 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax); 07707 update_conf(tmp); 07708 if (!here) { 07709 if (chan_sig != SIG_PRI) 07710 /* Hang it up to be sure it's good */ 07711 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 07712 } 07713 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone); 07714 #ifdef HAVE_PRI 07715 /* the dchannel is down so put the channel in alarm */ 07716 if (tmp->pri && !pri_is_up(tmp->pri)) { 07717 tmp->inalarm = 1; 07718 } 07719 #endif 07720 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) { 07721 tmp->inalarm = 1; 07722 handle_alarms(tmp, res); 07723 } else { 07724 /* yes, this looks strange... the unknown_alarm flag is only used to 07725 control whether an 'alarm cleared' message gets generated when we 07726 get an indication that the channel is no longer in alarm status. 07727 however, the channel *could* be in an alarm status that we aren't 07728 aware of (since get_alarms() only reports span alarms, not channel 07729 alarms). setting this flag will cause any potential 'alarm cleared' 07730 message to be suppressed, but if a real alarm occurs before that 07731 happens, this flag will get cleared by it and the situation will 07732 be normal. 07733 */ 07734 tmp->unknown_alarm = 1; 07735 } 07736 } 07737 07738 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 07739 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 07740 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 07741 tmp->sendcalleridafter = conf->chan.sendcalleridafter; 07742 07743 } 07744 if (tmp && !here) { 07745 /* nothing on the iflist */ 07746 if (!*wlist) { 07747 *wlist = tmp; 07748 tmp->prev = NULL; 07749 tmp->next = NULL; 07750 *wend = tmp; 07751 } else { 07752 /* at least one member on the iflist */ 07753 struct dahdi_pvt *working = *wlist; 07754 07755 /* check if we maybe have to put it on the begining */ 07756 if (working->channel > tmp->channel) { 07757 tmp->next = *wlist; 07758 tmp->prev = NULL; 07759 (*wlist)->prev = tmp; 07760 *wlist = tmp; 07761 } else { 07762 /* go through all the members and put the member in the right place */ 07763 while (working) { 07764 /* in the middle */ 07765 if (working->next) { 07766 if (working->channel < tmp->channel && working->next->channel > tmp->channel) { 07767 tmp->next = working->next; 07768 tmp->prev = working; 07769 working->next->prev = tmp; 07770 working->next = tmp; 07771 break; 07772 } 07773 } else { 07774 /* the last */ 07775 if (working->channel < tmp->channel) { 07776 working->next = tmp; 07777 tmp->next = NULL; 07778 tmp->prev = working; 07779 *wend = tmp; 07780 break; 07781 } 07782 } 07783 working = working->next; 07784 } 07785 } 07786 } 07787 } 07788 return tmp; 07789 }
static int my_dahdi_write | ( | struct dahdi_pvt * | p, | |
unsigned char * | buf, | |||
int | len, | |||
int | index, | |||
int | linear | |||
) | [static] |
Definition at line 5050 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().
05051 { 05052 int sent=0; 05053 int size; 05054 int res; 05055 int fd; 05056 fd = p->subs[index].dfd; 05057 while (len) { 05058 size = len; 05059 if (size > (linear ? READ_SIZE * 2 : READ_SIZE)) 05060 size = (linear ? READ_SIZE * 2 : READ_SIZE); 05061 res = write(fd, buf, size); 05062 if (res != size) { 05063 if (option_debug) 05064 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 05065 return sent; 05066 } 05067 len -= size; 05068 buf += size; 05069 } 05070 return sent; 05071 }
static int my_getsigstr | ( | struct ast_channel * | chan, | |
char * | str, | |||
const char * | term, | |||
int | ms | |||
) | [static] |
Definition at line 5527 of file chan_dahdi.c.
References ast_waitfordigit().
Referenced by ss_thread().
05528 { 05529 char c; 05530 05531 *str = 0; /* start with empty output buffer */ 05532 for (;;) 05533 { 05534 /* Wait for the first digit (up to specified ms). */ 05535 c = ast_waitfordigit(chan, ms); 05536 /* if timeout, hangup or error, return as such */ 05537 if (c < 1) 05538 return c; 05539 *str++ = c; 05540 *str = 0; 05541 if (strchr(term, c)) 05542 return 1; 05543 } 05544 }
static int pri_active_dchan_fd | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 2466 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().
02467 { 02468 int x = -1; 02469 02470 for (x = 0; x < NUM_DCHANS; x++) { 02471 if ((pri->dchans[x] == pri->pri)) 02472 break; 02473 } 02474 02475 return pri->fds[x]; 02476 }
static int pri_assign_bearer | ( | struct dahdi_pvt * | crv, | |
struct dahdi_pri * | pri, | |||
struct dahdi_pvt * | bearer | |||
) | [static] |
Definition at line 2436 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().
02437 { 02438 bearer->owner = &inuse; 02439 bearer->realcall = crv; 02440 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd; 02441 if (crv->subs[SUB_REAL].owner) 02442 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd; 02443 crv->bearer = bearer; 02444 crv->call = bearer->call; 02445 crv->pri = pri; 02446 return 0; 02447 }
static int pri_check_restart | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 8444 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().
08445 { 08446 do { 08447 pri->resetpos++; 08448 } while ((pri->resetpos < pri->numchans) && 08449 (!pri->pvts[pri->resetpos] || 08450 pri->pvts[pri->resetpos]->call || 08451 pri->pvts[pri->resetpos]->resetting)); 08452 if (pri->resetpos < pri->numchans) { 08453 /* Mark the channel as resetting and restart it */ 08454 pri->pvts[pri->resetpos]->resetting = 1; 08455 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos])); 08456 } else { 08457 pri->resetting = 0; 08458 time(&pri->lastreset); 08459 } 08460 return 0; 08461 }
static int pri_create_spanmap | ( | int | span, | |
int | trunkgroup, | |||
int | logicalspan | |||
) | [static] |
Definition at line 7285 of file chan_dahdi.c.
References ast_log(), dahdi_pri::mastertrunkgroup, dahdi_pri::prilogicalspan, and pris.
Referenced by setup_dahdi().
07286 { 07287 if (pris[span].mastertrunkgroup) { 07288 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); 07289 return -1; 07290 } 07291 pris[span].mastertrunkgroup = trunkgroup; 07292 pris[span].prilogicalspan = logicalspan; 07293 return 0; 07294 }
static int pri_create_trunkgroup | ( | int | trunkgroup, | |
int * | channels | |||
) | [static] |
Definition at line 7222 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().
07223 { 07224 struct dahdi_spaninfo si; 07225 struct dahdi_params p; 07226 int fd; 07227 int span; 07228 int ospan=0; 07229 int x,y; 07230 for (x = 0; x < NUM_SPANS; x++) { 07231 if (pris[x].trunkgroup == trunkgroup) { 07232 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]); 07233 return -1; 07234 } 07235 } 07236 for (y = 0; y < NUM_DCHANS; y++) { 07237 if (!channels[y]) 07238 break; 07239 memset(&si, 0, sizeof(si)); 07240 memset(&p, 0, sizeof(p)); 07241 fd = open(DAHDI_FILE_CHANNEL, O_RDWR); 07242 if (fd < 0) { 07243 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno)); 07244 return -1; 07245 } 07246 x = channels[y]; 07247 if (ioctl(fd, DAHDI_SPECIFY, &x)) { 07248 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno)); 07249 close(fd); 07250 return -1; 07251 } 07252 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) { 07253 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno)); 07254 return -1; 07255 } 07256 if (ioctl(fd, DAHDI_SPANSTAT, &si)) { 07257 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno)); 07258 close(fd); 07259 return -1; 07260 } 07261 span = p.spanno - 1; 07262 if (pris[span].trunkgroup) { 07263 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup); 07264 close(fd); 07265 return -1; 07266 } 07267 if (pris[span].pvts[0]) { 07268 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1); 07269 close(fd); 07270 return -1; 07271 } 07272 if (!y) { 07273 pris[span].trunkgroup = trunkgroup; 07274 pris[span].offset = channels[y] - p.chanpos; 07275 ospan = span; 07276 } 07277 pris[ospan].dchannels[y] = channels[y]; 07278 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED; 07279 pris[span].span = span + 1; 07280 close(fd); 07281 } 07282 return 0; 07283 }
static void* pri_dchannel | ( | void * | vpri | ) | [static] |
Definition at line 8536 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_copy_string(), ast_exists_extension(), AST_FORMAT_ULAW, ast_log(), ast_mutex_lock(), ast_pthread_create_background, AST_SOFTHANGUP_DEV, ast_strlen_zero(), ast_tv(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), dahdi_pvt::call, dahdi_pvt::channel, dahdi_chan_name, dahdi_hangup(), dahdi_request(), dahdi_pri::dchannels, dahdi_pri::dchans, do_idle_thread(), pollfd::events, pollfd::fd, dahdi_pri::fds, dahdi_pri::idlecontext, dahdi_pri::idledial, dahdi_pri::idleext, dahdi_pvt::isidlecall, dahdi_pri::lastreset, dahdi_pri::lock, dahdi_pri::minidle, dahdi_pri::minunused, ast_channel::name, NUM_DCHANS, dahdi_pri::numchans, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pri::pri, pri_check_restart(), pri_is_up(), dahdi_pri::pvts, dahdi_pri::resetinterval, dahdi_pri::resetpos, dahdi_pvt::resetting, dahdi_pri::resetting, pollfd::revents, dahdi_pri::switchtype, and t.
08537 { 08538 struct dahdi_pri *pri = vpri; 08539 pri_event *e; 08540 struct pollfd fds[NUM_DCHANS]; 08541 int res; 08542 int chanpos = 0; 08543 int x; 08544 int haveidles; 08545 int activeidles; 08546 int nextidle = -1; 08547 struct ast_channel *c; 08548 struct timeval tv, lowest, *next; 08549 struct timeval lastidle = { 0, 0 }; 08550 int doidling=0; 08551 char *cc; 08552 char idlen[80]; 08553 struct ast_channel *idle; 08554 pthread_t p; 08555 time_t t; 08556 int i, which=-1; 08557 int numdchans; 08558 int cause=0; 08559 struct dahdi_pvt *crv; 08560 pthread_t threadid; 08561 pthread_attr_t attr; 08562 char ani2str[6]; 08563 char plancallingnum[256]; 08564 char plancallingani[256]; 08565 char calledtonstr[10]; 08566 08567 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08568 08569 gettimeofday(&lastidle, NULL); 08570 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) { 08571 /* Need to do idle dialing, check to be sure though */ 08572 cc = strchr(pri->idleext, '@'); 08573 if (cc) { 08574 *cc = '\0'; 08575 cc++; 08576 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext)); 08577 #if 0 08578 /* Extensions may not be loaded yet */ 08579 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL)) 08580 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext); 08581 else 08582 #endif 08583 doidling = 1; 08584 } else 08585 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext); 08586 } 08587 for (;;) { 08588 for (i = 0; i < NUM_DCHANS; i++) { 08589 if (!pri->dchannels[i]) 08590 break; 08591 fds[i].fd = pri->fds[i]; 08592 fds[i].events = POLLIN | POLLPRI; 08593 fds[i].revents = 0; 08594 } 08595 numdchans = i; 08596 time(&t); 08597 ast_mutex_lock(&pri->lock); 08598 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) { 08599 if (pri->resetting && pri_is_up(pri)) { 08600 if (pri->resetpos < 0) 08601 pri_check_restart(pri); 08602 } else { 08603 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) { 08604 pri->resetting = 1; 08605 pri->resetpos = -1; 08606 } 08607 } 08608 } 08609 /* Look for any idle channels if appropriate */ 08610 if (doidling && pri_is_up(pri)) { 08611 nextidle = -1; 08612 haveidles = 0; 08613 activeidles = 0; 08614 for (x = pri->numchans; x >= 0; x--) { 08615 if (pri->pvts[x] && !pri->pvts[x]->owner && 08616 !pri->pvts[x]->call) { 08617 if (haveidles < pri->minunused) { 08618 haveidles++; 08619 } else if (!pri->pvts[x]->resetting) { 08620 nextidle = x; 08621 break; 08622 } 08623 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) 08624 activeidles++; 08625 } 08626 if (nextidle > -1) { 08627 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) { 08628 /* Don't create a new idle call more than once per second */ 08629 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial); 08630 idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause); 08631 if (idle) { 08632 pri->pvts[nextidle]->isidlecall = 1; 08633 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) { 08634 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name); 08635 dahdi_hangup(idle); 08636 } 08637 } else 08638 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen); 08639 gettimeofday(&lastidle, NULL); 08640 } 08641 } else if ((haveidles < pri->minunused) && 08642 (activeidles > pri->minidle)) { 08643 /* Mark something for hangup if there is something 08644 that can be hungup */ 08645 for (x = pri->numchans; x >= 0; x--) { 08646 /* find a candidate channel */ 08647 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) { 08648 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 08649 haveidles++; 08650 /* Stop if we have enough idle channels or 08651 can't spare any more active idle ones */ 08652 if ((haveidles >= pri->minunused) || 08653 (activeidles <= pri->minidle)) 08654 break; 08655 } 08656 } 08657 } 08658 } 08659 /* Start with reasonable max */ 08660 lowest = ast_tv(60, 0); 08661 for (i = 0; i < NUM_DCHANS; i++) { 08662 /* Find lowest available d-channel */ 08663 if (!pri->dchannels[i]) 08664 break; 08665 if ((next = pri_schedule_next(pri->dchans[i]))) { 08666 /* We need relative time here */ 08667 tv = ast_tvsub(*next, ast_tvnow()); 08668 if (tv.tv_sec < 0) { 08669 tv = ast_tv(0,0); 08670 } 08671 if (doidling || pri->resetting) { 08672 if (tv.tv_sec > 1) { 08673 tv = ast_tv(1, 0); 08674 } 08675 } else { 08676 if (tv.tv_sec > 60) { 08677 tv = ast_tv(60, 0); 08678 } 08679 } 08680 } else if (doidling || pri->resetting) { 08681 /* Make sure we stop at least once per second if we're 08682 monitoring idle channels */ 08683 tv = ast_tv(1,0); 08684 } else { 08685 /* Don't poll for more than 60 seconds */ 08686 tv = ast_tv(60, 0); 08687 } 08688 if (!i || ast_tvcmp(tv, lowest) < 0) { 08689 lowest = tv; 08690 } 08691 } 08692 ast_mutex_unlock(&pri->lock); 08693 08694 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 08695 pthread_testcancel(); 08696 e = NULL; 08697 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000); 08698 pthread_testcancel(); 08699 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08700 08701 ast_mutex_lock(&pri->lock); 08702 if (!res) { 08703 for (which = 0; which < NUM_DCHANS; which++) { 08704 if (!pri->dchans[which]) 08705 break; 08706 /* Just a timeout, run the scheduler */ 08707 e = pri_schedule_run(pri->dchans[which]); 08708 if (e) 08709 break; 08710 } 08711 } else if (res > -1) { 08712 for (which = 0; which < NUM_DCHANS; which++) { 08713 if (!pri->dchans[which]) 08714 break; 08715 if (fds[which].revents & POLLPRI) { 08716 /* Check for an event */ 08717 x = 0; 08718 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x); 08719 if (x) 08720 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); 08721 /* Keep track of alarm state */ 08722 if (x == DAHDI_EVENT_ALARM) { 08723 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP); 08724 pri_find_dchan(pri); 08725 } else if (x == DAHDI_EVENT_NOALARM) { 08726 pri->dchanavail[which] |= DCHAN_NOTINALARM; 08727 pri_restart(pri->dchans[which]); 08728 } 08729 08730 if (option_debug) 08731 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span); 08732 } else if (fds[which].revents & POLLIN) { 08733 e = pri_check_event(pri->dchans[which]); 08734 } 08735 if (e) 08736 break; 08737 } 08738 } else if (errno != EINTR) 08739 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno)); 08740 08741 if (e) { 08742 if (pri->debug) 08743 pri_dump_event(pri->dchans[which], e); 08744 08745 if (e->e != PRI_EVENT_DCHAN_DOWN) { 08746 if (!(pri->dchanavail[which] & DCHAN_UP)) { 08747 if (option_verbose > 1) 08748 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span); 08749 } 08750 pri->dchanavail[which] |= DCHAN_UP; 08751 } else { 08752 if (pri->dchanavail[which] & DCHAN_UP) { 08753 if (option_verbose > 1) 08754 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span); 08755 } 08756 pri->dchanavail[which] &= ~DCHAN_UP; 08757 } 08758 08759 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which])) 08760 /* Must be an NFAS group that has the secondary dchan active */ 08761 pri->pri = pri->dchans[which]; 08762 08763 switch (e->e) { 08764 case PRI_EVENT_DCHAN_UP: 08765 if (!pri->pri) pri_find_dchan(pri); 08766 08767 /* Note presense of D-channel */ 08768 time(&pri->lastreset); 08769 08770 /* Restart in 5 seconds */ 08771 if (pri->resetinterval > -1) { 08772 pri->lastreset -= pri->resetinterval; 08773 pri->lastreset += 5; 08774 } 08775 pri->resetting = 0; 08776 /* Take the channels from inalarm condition */ 08777 for (i = 0; i < pri->numchans; i++) 08778 if (pri->pvts[i]) { 08779 pri->pvts[i]->inalarm = 0; 08780 } 08781 break; 08782 case PRI_EVENT_DCHAN_DOWN: 08783 pri_find_dchan(pri); 08784 if (!pri_is_up(pri)) { 08785 pri->resetting = 0; 08786 /* Hangup active channels and put them in alarm mode */ 08787 for (i = 0; i < pri->numchans; i++) { 08788 struct dahdi_pvt *p = pri->pvts[i]; 08789 if (p) { 08790 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 08791 /* T309 is not enabled : hangup calls when alarm occurs */ 08792 if (p->call) { 08793 if (p->pri && p->pri->pri) { 08794 pri_hangup(p->pri->pri, p->call, -1); 08795 pri_destroycall(p->pri->pri, p->call); 08796 p->call = NULL; 08797 } else 08798 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n"); 08799 } 08800 if (p->realcall) { 08801 pri_hangup_all(p->realcall, pri); 08802 } else if (p->owner) 08803 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 08804 } 08805 p->inalarm = 1; 08806 } 08807 } 08808 } 08809 break; 08810 case PRI_EVENT_RESTART: 08811 if (e->restart.channel > -1) { 08812 chanpos = pri_find_principle(pri, e->restart.channel); 08813 if (chanpos < 0) 08814 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 08815 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 08816 else { 08817 if (option_verbose > 2) 08818 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n", 08819 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 08820 ast_mutex_lock(&pri->pvts[chanpos]->lock); 08821 if (pri->pvts[chanpos]->call) { 08822 pri_destroycall(pri->pri, pri->pvts[chanpos]->call); 08823 pri->pvts[chanpos]->call = NULL; 08824 } 08825 /* Force soft hangup if appropriate */ 08826 if (pri->pvts[chanpos]->realcall) 08827 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 08828 else if (pri->pvts[chanpos]->owner) 08829 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 08830 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 08831 } 08832 } else { 08833 if (option_verbose > 2) 08834 ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span); 08835 for (x = 0; x < pri->numchans; x++) 08836 if (pri->pvts[x]) { 08837 ast_mutex_lock(&pri->pvts[x]->lock); 08838 if (pri->pvts[x]->call) { 08839 pri_destroycall(pri->pri, pri->pvts[x]->call); 08840 pri->pvts[x]->call = NULL; 08841 } 08842 if (pri->pvts[chanpos]->realcall) 08843 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 08844 else if (pri->pvts[x]->owner) 08845 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 08846 ast_mutex_unlock(&pri->pvts[x]->lock); 08847 } 08848 } 08849 break; 08850 case PRI_EVENT_KEYPAD_DIGIT: 08851 chanpos = pri_find_principle(pri, e->digit.channel); 08852 if (chanpos < 0) { 08853 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 08854 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span); 08855 } else { 08856 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call); 08857 if (chanpos > -1) { 08858 ast_mutex_lock(&pri->pvts[chanpos]->lock); 08859 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */ 08860 if (pri->overlapdial && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) { 08861 /* how to do that */ 08862 int digitlen = strlen(e->digit.digits); 08863 char digit; 08864 int i; 08865 for (i = 0; i < digitlen; i++) { 08866 digit = e->digit.digits[i]; 08867 { 08868 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 08869 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 08870 } 08871 } 08872 } 08873 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 08874 } 08875 } 08876 break; 08877 08878 case PRI_EVENT_INFO_RECEIVED: 08879 chanpos = pri_find_principle(pri, e->ring.channel); 08880 if (chanpos < 0) { 08881 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 08882 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 08883 } else { 08884 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call); 08885 if (chanpos > -1) { 08886 ast_mutex_lock(&pri->pvts[chanpos]->lock); 08887 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */ 08888 if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) { 08889 /* how to do that */ 08890 int digitlen = strlen(e->ring.callednum); 08891 char digit; 08892 int i; 08893 for (i = 0; i < digitlen; i++) { 08894 digit = e->ring.callednum[i]; 08895 { 08896 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 08897 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 08898 } 08899 } 08900 } 08901 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 08902 } 08903 } 08904 break; 08905 case PRI_EVENT_RING: 08906 crv = NULL; 08907 if (e->ring.channel == -1) 08908 chanpos = pri_find_empty_chan(pri, 1); 08909 else 08910 chanpos = pri_find_principle(pri, e->ring.channel); 08911 /* if no channel specified find one empty */ 08912 if (chanpos < 0) { 08913 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 08914 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 08915 } else { 08916 ast_mutex_lock(&pri->pvts[chanpos]->lock); 08917 if (pri->pvts[chanpos]->owner) { 08918 if (pri->pvts[chanpos]->call == e->ring.call) { 08919 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 08920 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 08921 break; 08922 } else { 08923 /* This is where we handle initial glare */ 08924 ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n", 08925 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 08926 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 08927 chanpos = -1; 08928 } 08929 } 08930 if (chanpos > -1) 08931 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 08932 } 08933 if ((chanpos < 0) && (e->ring.flexible)) 08934 chanpos = pri_find_empty_chan(pri, 1); 08935 if (chanpos > -1) { 08936 ast_mutex_lock(&pri->pvts[chanpos]->lock); 08937 if (pri->switchtype == PRI_SWITCH_GR303_TMC) { 08938 /* Should be safe to lock CRV AFAIK while bearer is still locked */ 08939 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL)); 08940 if (crv) 08941 ast_mutex_lock(&crv->lock); 08942 if (!crv || crv->owner) { 08943 pri->pvts[chanpos]->call = NULL; 08944 if (crv) { 08945 if (crv->owner) 08946 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV; 08947 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); 08948 } else 08949 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); 08950 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE); 08951 if (crv) 08952 ast_mutex_unlock(&crv->lock); 08953 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 08954 break; 08955 } 08956 } 08957 pri->pvts[chanpos]->call = e->ring.call; 08958 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan); 08959 if (pri->pvts[chanpos]->use_callerid) { 08960 ast_shrink_phone_number(plancallingnum); 08961 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num)); 08962 #ifdef PRI_ANI 08963 if (!ast_strlen_zero(e->ring.callingani)) { 08964 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani); 08965 ast_shrink_phone_number(plancallingani); 08966 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani)); 08967 } else { 08968 pri->pvts[chanpos]->cid_ani[0] = '\0'; 08969 } 08970 #endif 08971 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name)); 08972 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */ 08973 } else { 08974 pri->pvts[chanpos]->cid_num[0] = '\0'; 08975 pri->pvts[chanpos]->cid_ani[0] = '\0'; 08976 pri->pvts[chanpos]->cid_name[0] = '\0'; 08977 pri->pvts[chanpos]->cid_ton = 0; 08978 } 08979 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri, 08980 e->ring.redirectingnum, e->ring.callingplanrdnis); 08981 /* If immediate=yes go to s|1 */ 08982 if (pri->pvts[chanpos]->immediate) { 08983 if (option_verbose > 2) 08984 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n"); 08985 pri->pvts[chanpos]->exten[0] = 's'; 08986 pri->pvts[chanpos]->exten[1] = '\0'; 08987 } 08988 /* Get called number */ 08989 else if (!ast_strlen_zero(e->ring.callednum)) { 08990 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten)); 08991 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 08992 } else if (pri->overlapdial) 08993 pri->pvts[chanpos]->exten[0] = '\0'; 08994 else { 08995 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */ 08996 pri->pvts[chanpos]->exten[0] = 's'; 08997 pri->pvts[chanpos]->exten[1] = '\0'; 08998 } 08999 /* Set DNID on all incoming calls -- even immediate */ 09000 if (!ast_strlen_zero(e->ring.callednum)) 09001 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 09002 /* No number yet, but received "sending complete"? */ 09003 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) { 09004 if (option_verbose > 2) 09005 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n"); 09006 pri->pvts[chanpos]->exten[0] = 's'; 09007 pri->pvts[chanpos]->exten[1] = '\0'; 09008 } 09009 /* Make sure extension exists (or in overlap dial mode, can exist) */ 09010 if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) || 09011 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 09012 /* Setup law */ 09013 int law; 09014 if (pri->switchtype != PRI_SWITCH_GR303_TMC) { 09015 /* Set to audio mode at this point */ 09016 law = 1; 09017 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1) 09018 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno)); 09019 } 09020 if (e->ring.layer1 == PRI_LAYER_1_ALAW) 09021 law = DAHDI_LAW_ALAW; 09022 else 09023 law = DAHDI_LAW_MULAW; 09024 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law); 09025 if (res < 0) 09026 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel); 09027 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law); 09028 if (res < 0) 09029 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel); 09030 if (e->ring.complete || !pri->overlapdial) { 09031 /* Just announce proceeding */ 09032 pri->pvts[chanpos]->proceeding = 1; 09033 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0); 09034 } else { 09035 if (pri->switchtype != PRI_SWITCH_GR303_TMC) 09036 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 09037 else 09038 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 09039 } 09040 /* Get the use_callingpres state */ 09041 pri->pvts[chanpos]->callingpres = e->ring.callingpres; 09042 09043 /* Start PBX */ 09044 if (!e->ring.complete && pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 09045 /* Release the PRI lock while we create the channel */ 09046 ast_mutex_unlock(&pri->lock); 09047 if (crv) { 09048 /* Set bearer and such */ 09049 pri_assign_bearer(crv, pri, pri->pvts[chanpos]); 09050 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 09051 pri->pvts[chanpos]->owner = &inuse; 09052 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel); 09053 } else { 09054 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 09055 } 09056 09057 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09058 09059 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 09060 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 09061 } 09062 if (e->ring.ani2 >= 0) { 09063 snprintf(ani2str, 5, "%.2d", e->ring.ani2); 09064 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 09065 } 09066 09067 #ifdef SUPPORT_USERUSER 09068 if (!ast_strlen_zero(e->ring.useruserinfo)) { 09069 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 09070 } 09071 #endif 09072 09073 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan); 09074 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 09075 if (e->ring.redirectingreason >= 0) 09076 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 09077 09078 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09079 ast_mutex_lock(&pri->lock); 09080 09081 pthread_attr_init(&attr); 09082 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 09083 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) { 09084 if (option_verbose > 2) 09085 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n", 09086 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"), 09087 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 09088 } else { 09089 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 09090 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 09091 if (c) 09092 ast_hangup(c); 09093 else { 09094 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 09095 pri->pvts[chanpos]->call = NULL; 09096 } 09097 } 09098 pthread_attr_destroy(&attr); 09099 } else { 09100 ast_mutex_unlock(&pri->lock); 09101 /* Release PRI lock while we create the channel */ 09102 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype); 09103 if (c) { 09104 char calledtonstr[10]; 09105 09106 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09107 09108 if (e->ring.ani2 >= 0) { 09109 snprintf(ani2str, 5, "%d", e->ring.ani2); 09110 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 09111 } 09112 09113 #ifdef SUPPORT_USERUSER 09114 if (!ast_strlen_zero(e->ring.useruserinfo)) { 09115 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 09116 } 09117 #endif 09118 09119 if (e->ring.redirectingreason >= 0) 09120 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 09121 09122 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan); 09123 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 09124 09125 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09126 ast_mutex_lock(&pri->lock); 09127 09128 if (option_verbose > 2) 09129 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n", 09130 plancallingnum, pri->pvts[chanpos]->exten, 09131 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 09132 dahdi_enable_ec(pri->pvts[chanpos]); 09133 } else { 09134 09135 ast_mutex_lock(&pri->lock); 09136 09137 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 09138 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 09139 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 09140 pri->pvts[chanpos]->call = NULL; 09141 } 09142 } 09143 } else { 09144 if (option_verbose > 2) 09145 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n", 09146 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 09147 pri->pvts[chanpos]->prioffset, pri->span); 09148 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED); 09149 pri->pvts[chanpos]->call = NULL; 09150 pri->pvts[chanpos]->exten[0] = '\0'; 09151 } 09152 if (crv) 09153 ast_mutex_unlock(&crv->lock); 09154 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09155 } else { 09156 if (e->ring.flexible) 09157 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION); 09158 else 09159 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL); 09160 } 09161 break; 09162 case PRI_EVENT_RINGING: 09163 chanpos = pri_find_principle(pri, e->ringing.channel); 09164 if (chanpos < 0) { 09165 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 09166 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 09167 } else { 09168 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call); 09169 if (chanpos < 0) { 09170 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 09171 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 09172 } else { 09173 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09174 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 09175 dahdi_enable_ec(pri->pvts[chanpos]); 09176 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1; 09177 pri->pvts[chanpos]->alerting = 1; 09178 } else 09179 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n"); 09180 #ifdef PRI_PROGRESS_MASK 09181 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) { 09182 #else 09183 if (e->ringing.progress == 8) { 09184 #endif 09185 /* Now we can do call progress detection */ 09186 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 09187 /* RINGING detection isn't required because we got ALERTING signal */ 09188 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING); 09189 pri->pvts[chanpos]->dsp_features = 0; 09190 } 09191 } 09192 09193 #ifdef SUPPORT_USERUSER 09194 if (!ast_strlen_zero(e->ringing.useruserinfo)) { 09195 struct ast_channel *owner = pri->pvts[chanpos]->owner; 09196 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09197 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo); 09198 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09199 } 09200 #endif 09201 09202 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09203 } 09204 } 09205 break; 09206 case PRI_EVENT_PROGRESS: 09207 /* Get chan value if e->e is not PRI_EVNT_RINGING */ 09208 chanpos = pri_find_principle(pri, e->proceeding.channel); 09209 if (chanpos > -1) { 09210 #ifdef PRI_PROGRESS_MASK 09211 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) { 09212 #else 09213 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) { 09214 #endif 09215 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, }; 09216 09217 if (e->proceeding.cause > -1) { 09218 if (option_verbose > 2) 09219 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause); 09220 09221 /* Work around broken, out of spec USER_BUSY cause in a progress message */ 09222 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) { 09223 if (pri->pvts[chanpos]->owner) { 09224 if (option_verbose > 2) 09225 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n"); 09226 09227 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause; 09228 f.subclass = AST_CONTROL_BUSY; 09229 } 09230 } 09231 } 09232 09233 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09234 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n", 09235 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 09236 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 09237 #ifdef PRI_PROGRESS_MASK 09238 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 09239 #else 09240 if (e->proceeding.progress == 8) { 09241 #endif 09242 /* Now we can do call progress detection */ 09243 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 09244 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 09245 pri->pvts[chanpos]->dsp_features = 0; 09246 } 09247 } 09248 pri->pvts[chanpos]->progress = 1; 09249 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09250 } 09251 } 09252 break; 09253 case PRI_EVENT_PROCEEDING: 09254 chanpos = pri_find_principle(pri, e->proceeding.channel); 09255 if (chanpos > -1) { 09256 if (!pri->pvts[chanpos]->proceeding) { 09257 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, }; 09258 09259 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09260 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n", 09261 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 09262 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 09263 #ifdef PRI_PROGRESS_MASK 09264 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 09265 #else 09266 if (e->proceeding.progress == 8) { 09267 #endif 09268 /* Now we can do call progress detection */ 09269 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 09270 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 09271 pri->pvts[chanpos]->dsp_features = 0; 09272 } 09273 /* Bring voice path up */ 09274 f.subclass = AST_CONTROL_PROGRESS; 09275 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 09276 } 09277 pri->pvts[chanpos]->proceeding = 1; 09278 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09279 } 09280 } 09281 break; 09282 case PRI_EVENT_FACNAME: 09283 chanpos = pri_find_principle(pri, e->facname.channel); 09284 if (chanpos < 0) { 09285 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 09286 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 09287 } else { 09288 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call); 09289 if (chanpos < 0) { 09290 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 09291 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 09292 } else { 09293 /* Re-use *69 field for PRI */ 09294 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09295 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num)); 09296 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name)); 09297 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1; 09298 dahdi_enable_ec(pri->pvts[chanpos]); 09299 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09300 } 09301 } 09302 break; 09303 case PRI_EVENT_ANSWER: 09304 chanpos = pri_find_principle(pri, e->answer.channel); 09305 if (chanpos < 0) { 09306 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 09307 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 09308 } else { 09309 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call); 09310 if (chanpos < 0) { 09311 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 09312 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 09313 } else { 09314 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09315 /* Now we can do call progress detection */ 09316 09317 /* We changed this so it turns on the DSP no matter what... progress or no progress. 09318 * By this time, we need DTMF detection and other features that were previously disabled 09319 * -- Matt F */ 09320 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 09321 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 09322 pri->pvts[chanpos]->dsp_features = 0; 09323 } 09324 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) { 09325 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n"); 09326 x = DAHDI_START; 09327 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 09328 if (res < 0) { 09329 if (errno != EINPROGRESS) { 09330 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 09331 } 09332 } 09333 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 09334 pri->pvts[chanpos]->dialing = 1; 09335 /* Send any "w" waited stuff */ 09336 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop); 09337 if (res < 0) { 09338 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno)); 09339 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 09340 } else 09341 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr); 09342 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 09343 } else if (pri->pvts[chanpos]->confirmanswer) { 09344 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel); 09345 } else { 09346 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1; 09347 /* Enable echo cancellation if it's not on already */ 09348 dahdi_enable_ec(pri->pvts[chanpos]); 09349 } 09350 09351 #ifdef SUPPORT_USERUSER 09352 if (!ast_strlen_zero(e->answer.useruserinfo)) { 09353 struct ast_channel *owner = pri->pvts[chanpos]->owner; 09354 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09355 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo); 09356 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09357 } 09358 #endif 09359 09360 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09361 } 09362 } 09363 break; 09364 case PRI_EVENT_HANGUP: 09365 chanpos = pri_find_principle(pri, e->hangup.channel); 09366 if (chanpos < 0) { 09367 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 09368 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 09369 } else { 09370 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 09371 if (chanpos > -1) { 09372 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09373 if (!pri->pvts[chanpos]->alreadyhungup) { 09374 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */ 09375 pri->pvts[chanpos]->alreadyhungup = 1; 09376 if (pri->pvts[chanpos]->realcall) 09377 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 09378 else if (pri->pvts[chanpos]->owner) { 09379 /* Queue a BUSY instead of a hangup if our cause is appropriate */ 09380 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 09381 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP) 09382 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09383 else { 09384 switch (e->hangup.cause) { 09385 case PRI_CAUSE_USER_BUSY: 09386 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 09387 break; 09388 case PRI_CAUSE_CALL_REJECTED: 09389 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 09390 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 09391 case PRI_CAUSE_SWITCH_CONGESTION: 09392 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 09393 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 09394 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 09395 break; 09396 default: 09397 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09398 } 09399 } 09400 } 09401 if (option_verbose > 2) 09402 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n", 09403 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause); 09404 } else { 09405 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 09406 pri->pvts[chanpos]->call = NULL; 09407 } 09408 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 09409 if (option_verbose > 2) 09410 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 09411 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 09412 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 09413 pri->pvts[chanpos]->resetting = 1; 09414 } 09415 if (e->hangup.aoc_units > -1) 09416 if (option_verbose > 2) 09417 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 09418 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 09419 09420 #ifdef SUPPORT_USERUSER 09421 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) { 09422 struct ast_channel *owner = pri->pvts[chanpos]->owner; 09423 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09424 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 09425 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09426 } 09427 #endif 09428 09429 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09430 } else { 09431 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 09432 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 09433 } 09434 } 09435 break; 09436 #ifndef PRI_EVENT_HANGUP_REQ 09437 #error please update libpri 09438 #endif 09439 case PRI_EVENT_HANGUP_REQ: 09440 chanpos = pri_find_principle(pri, e->hangup.channel); 09441 if (chanpos < 0) { 09442 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 09443 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 09444 } else { 09445 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 09446 if (chanpos > -1) { 09447 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09448 if (pri->pvts[chanpos]->realcall) 09449 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 09450 else if (pri->pvts[chanpos]->owner) { 09451 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 09452 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP) 09453 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09454 else { 09455 switch (e->hangup.cause) { 09456 case PRI_CAUSE_USER_BUSY: 09457 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 09458 break; 09459 case PRI_CAUSE_CALL_REJECTED: 09460 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 09461 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 09462 case PRI_CAUSE_SWITCH_CONGESTION: 09463 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 09464 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 09465 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 09466 break; 09467 default: 09468 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09469 } 09470 } 09471 if (option_verbose > 2) 09472 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); 09473 if (e->hangup.aoc_units > -1) 09474 if (option_verbose > 2) 09475 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 09476 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 09477 } else { 09478 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 09479 pri->pvts[chanpos]->call = NULL; 09480 } 09481 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 09482 if (option_verbose > 2) 09483 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n", 09484 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 09485 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 09486 pri->pvts[chanpos]->resetting = 1; 09487 } 09488 09489 #ifdef SUPPORT_USERUSER 09490 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 09491 struct ast_channel *owner = pri->pvts[chanpos]->owner; 09492 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09493 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 09494 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09495 } 09496 #endif 09497 09498 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09499 } else { 09500 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); 09501 } 09502 } 09503 break; 09504 case PRI_EVENT_HANGUP_ACK: 09505 chanpos = pri_find_principle(pri, e->hangup.channel); 09506 if (chanpos < 0) { 09507 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 09508 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 09509 } else { 09510 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 09511 if (chanpos > -1) { 09512 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09513 pri->pvts[chanpos]->call = NULL; 09514 pri->pvts[chanpos]->resetting = 0; 09515 if (pri->pvts[chanpos]->owner) { 09516 if (option_verbose > 2) 09517 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); 09518 } 09519 09520 #ifdef SUPPORT_USERUSER 09521 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 09522 struct ast_channel *owner = pri->pvts[chanpos]->owner; 09523 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09524 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 09525 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09526 } 09527 #endif 09528 09529 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09530 } 09531 } 09532 break; 09533 case PRI_EVENT_CONFIG_ERR: 09534 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err); 09535 break; 09536 case PRI_EVENT_RESTART_ACK: 09537 chanpos = pri_find_principle(pri, e->restartack.channel); 09538 if (chanpos < 0) { 09539 /* Sometime switches (e.g. I421 / British Telecom) don't give us the 09540 channel number, so we have to figure it out... This must be why 09541 everybody resets exactly a channel at a time. */ 09542 for (x = 0; x < pri->numchans; x++) { 09543 if (pri->pvts[x] && pri->pvts[x]->resetting) { 09544 chanpos = x; 09545 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09546 ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 09547 pri->pvts[chanpos]->prioffset, pri->span); 09548 if (pri->pvts[chanpos]->realcall) 09549 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 09550 else if (pri->pvts[chanpos]->owner) { 09551 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 09552 pri->pvts[chanpos]->prioffset, pri->span); 09553 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09554 } 09555 pri->pvts[chanpos]->resetting = 0; 09556 if (option_verbose > 2) 09557 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 09558 pri->pvts[chanpos]->prioffset, pri->span); 09559 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09560 if (pri->resetting) 09561 pri_check_restart(pri); 09562 break; 09563 } 09564 } 09565 if (chanpos < 0) { 09566 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 09567 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 09568 } 09569 } else { 09570 if (pri->pvts[chanpos]) { 09571 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09572 if (pri->pvts[chanpos]->realcall) 09573 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 09574 else if (pri->pvts[chanpos]->owner) { 09575 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n", 09576 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 09577 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 09578 } 09579 pri->pvts[chanpos]->resetting = 0; 09580 if (option_verbose > 2) 09581 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 09582 pri->pvts[chanpos]->prioffset, pri->span); 09583 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09584 if (pri->resetting) 09585 pri_check_restart(pri); 09586 } 09587 } 09588 break; 09589 case PRI_EVENT_SETUP_ACK: 09590 chanpos = pri_find_principle(pri, e->setup_ack.channel); 09591 if (chanpos < 0) { 09592 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 09593 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span); 09594 } else { 09595 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call); 09596 if (chanpos > -1) { 09597 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09598 pri->pvts[chanpos]->setup_ack = 1; 09599 /* Send any queued digits */ 09600 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) { 09601 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]); 09602 pri_information(pri->pri, pri->pvts[chanpos]->call, 09603 pri->pvts[chanpos]->dialdest[x]); 09604 } 09605 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09606 } else 09607 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel); 09608 } 09609 break; 09610 case PRI_EVENT_NOTIFY: 09611 chanpos = pri_find_principle(pri, e->notify.channel); 09612 if (chanpos < 0) { 09613 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n", 09614 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span); 09615 } else { 09616 struct ast_frame f = { AST_FRAME_CONTROL, }; 09617 ast_mutex_lock(&pri->pvts[chanpos]->lock); 09618 switch (e->notify.info) { 09619 case PRI_NOTIFY_REMOTE_HOLD: 09620 f.subclass = AST_CONTROL_HOLD; 09621 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 09622 break; 09623 case PRI_NOTIFY_REMOTE_RETRIEVAL: 09624 f.subclass = AST_CONTROL_UNHOLD; 09625 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 09626 break; 09627 } 09628 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 09629 } 09630 break; 09631 default: 09632 ast_log(LOG_DEBUG, "Event: %d\n", e->e); 09633 } 09634 } 09635 ast_mutex_unlock(&pri->lock); 09636 } 09637 /* Never reached */ 09638 return NULL; 09639 }
Definition at line 8183 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pri::crvs, dahdi_pvt::next, and dahdi_pvt::pri.
08184 { 08185 struct dahdi_pvt *p; 08186 p = pri->crvs; 08187 while (p) { 08188 if (p->channel == crv) 08189 return p; 08190 p = p->next; 08191 } 08192 return NULL; 08193 }
static int pri_find_dchan | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 2478 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, dahdi_pri::dchans, NUM_DCHANS, and dahdi_pri::pri.
02479 { 02480 int oldslot = -1; 02481 struct pri *old; 02482 int newslot = -1; 02483 int x; 02484 old = pri->pri; 02485 for (x = 0; x < NUM_DCHANS; x++) { 02486 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0)) 02487 newslot = x; 02488 if (pri->dchans[x] == old) { 02489 oldslot = x; 02490 } 02491 } 02492 if (newslot < 0) { 02493 newslot = 0; 02494 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n", 02495 pri->dchannels[newslot]); 02496 } 02497 if (old && (oldslot != newslot)) 02498 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n", 02499 pri->dchannels[oldslot], pri->dchannels[newslot]); 02500 pri->pri = pri->dchans[newslot]; 02501 return 0; 02502 }
static int pri_find_empty_chan | ( | struct dahdi_pri * | pri, | |
int | backwards | |||
) | [static] |
Definition at line 7934 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().
07935 { 07936 int x; 07937 if (backwards) 07938 x = pri->numchans; 07939 else 07940 x = 0; 07941 for (;;) { 07942 if (backwards && (x < 0)) 07943 break; 07944 if (!backwards && (x >= pri->numchans)) 07945 break; 07946 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) { 07947 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n", 07948 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset); 07949 return x; 07950 } 07951 if (backwards) 07952 x--; 07953 else 07954 x++; 07955 } 07956 return -1; 07957 }
static int pri_find_principle | ( | struct dahdi_pri * | pri, | |
int | channel | |||
) | [static] |
Definition at line 8196 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.
08197 { 08198 int x; 08199 int span = PRI_SPAN(channel); 08200 int spanfd; 08201 struct dahdi_params param; 08202 int principle = -1; 08203 int explicit = PRI_EXPLICIT(channel); 08204 channel = PRI_CHANNEL(channel); 08205 08206 if (!explicit) { 08207 spanfd = pri_active_dchan_fd(pri); 08208 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m)) 08209 return -1; 08210 span = pris[param.spanno - 1].prilogicalspan; 08211 } 08212 08213 for (x = 0; x < pri->numchans; x++) { 08214 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) { 08215 principle = x; 08216 break; 08217 } 08218 } 08219 08220 return principle; 08221 }
static int pri_fixup_principle | ( | struct dahdi_pri * | pri, | |
int | principle, | |||
q931_call * | c | |||
) | [static] |
Definition at line 8223 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.
08224 { 08225 int x; 08226 struct dahdi_pvt *crv; 08227 if (!c) { 08228 if (principle < 0) 08229 return -1; 08230 return principle; 08231 } 08232 if ((principle > -1) && 08233 (principle < pri->numchans) && 08234 (pri->pvts[principle]) && 08235 (pri->pvts[principle]->call == c)) 08236 return principle; 08237 /* First, check for other bearers */ 08238 for (x = 0; x < pri->numchans; x++) { 08239 if (!pri->pvts[x]) 08240 continue; 08241 if (pri->pvts[x]->call == c) { 08242 /* Found our call */ 08243 if (principle != x) { 08244 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x]; 08245 08246 if (option_verbose > 2) 08247 ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n", 08248 old->channel, new->channel); 08249 if (new->owner) { 08250 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n", 08251 old->channel, new->channel, new->channel); 08252 return -1; 08253 } 08254 /* Fix it all up now */ 08255 new->owner = old->owner; 08256 old->owner = NULL; 08257 if (new->owner) { 08258 ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1); 08259 new->owner->tech_pvt = new; 08260 new->owner->fds[0] = new->subs[SUB_REAL].dfd; 08261 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner; 08262 old->subs[SUB_REAL].owner = NULL; 08263 } else 08264 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); 08265 new->call = old->call; 08266 old->call = NULL; 08267 08268 /* Copy any DSP that may be present */ 08269 new->dsp = old->dsp; 08270 new->dsp_features = old->dsp_features; 08271 old->dsp = NULL; 08272 old->dsp_features = 0; 08273 } 08274 return principle; 08275 } 08276 } 08277 /* Now check for a CRV with no bearer */ 08278 crv = pri->crvs; 08279 while (crv) { 08280 if (crv->call == c) { 08281 /* This is our match... Perform some basic checks */ 08282 if (crv->bearer) 08283 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n"); 08284 else if (pri->pvts[principle]->owner) 08285 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n"); 08286 else { 08287 /* Looks good. Drop the pseudo channel now, clear up the assignment, and 08288 wakeup the potential sleeper */ 08289 dahdi_close_sub(crv, SUB_REAL); 08290 pri->pvts[principle]->call = crv->call; 08291 pri_assign_bearer(crv, pri, pri->pvts[principle]); 08292 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n", 08293 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset, 08294 pri->trunkgroup, crv->channel); 08295 wakeup_sub(crv, SUB_REAL, pri); 08296 } 08297 return principle; 08298 } 08299 crv = crv->next; 08300 } 08301 ast_log(LOG_WARNING, "Call specified, but not found?\n"); 08302 return -1; 08303 }
Definition at line 757 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().
00758 { 00759 int res; 00760 /* Grab the lock first */ 00761 do { 00762 res = ast_mutex_trylock(&pri->lock); 00763 if (res) { 00764 DEADLOCK_AVOIDANCE(&pvt->lock); 00765 } 00766 } while (res); 00767 /* Then break the poll */ 00768 if (pri->master != AST_PTHREADT_NULL) 00769 pthread_kill(pri->master, SIGURG); 00770 return 0; 00771 }
Definition at line 8463 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.
08464 { 08465 int x; 08466 int redo; 08467 ast_mutex_unlock(&pri->lock); 08468 ast_mutex_lock(&p->lock); 08469 do { 08470 redo = 0; 08471 for (x = 0; x < 3; x++) { 08472 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) { 08473 redo++; 08474 DEADLOCK_AVOIDANCE(&p->lock); 08475 } 08476 if (p->subs[x].owner) { 08477 ast_queue_hangup(p->subs[x].owner); 08478 ast_mutex_unlock(&p->subs[x].owner->lock); 08479 } 08480 } 08481 } while (redo); 08482 ast_mutex_unlock(&p->lock); 08483 ast_mutex_lock(&pri->lock); 08484 return 0; 08485 }
static int pri_is_up | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 2426 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, NUM_DCHANS, and dahdi_pvt::pri.
Referenced by pri_dchannel().
02427 { 02428 int x; 02429 for (x = 0; x < NUM_DCHANS; x++) { 02430 if (pri->dchanavail[x] == DCHAN_AVAILABLE) 02431 return 1; 02432 } 02433 return 0; 02434 }
static char* pri_order | ( | int | level | ) | [static] |
Definition at line 2449 of file chan_dahdi.c.
Referenced by handle_pri_show_span().
02450 { 02451 switch (level) { 02452 case 0: 02453 return "Primary"; 02454 case 1: 02455 return "Secondary"; 02456 case 2: 02457 return "Tertiary"; 02458 case 3: 02459 return "Quaternary"; 02460 default: 02461 return "<Unknown>"; 02462 } 02463 }
static void pri_rel | ( | struct dahdi_pri * | pri | ) | [inline, static] |
Definition at line 352 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().
00353 { 00354 ast_mutex_unlock(&pri->lock); 00355 }
static int pri_resolve_span | ( | int * | span, | |
int | channel, | |||
int | offset, | |||
struct dahdi_spaninfo * | si | |||
) | [static] |
Definition at line 7176 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().
07177 { 07178 int x; 07179 int trunkgroup; 07180 /* Get appropriate trunk group if there is one */ 07181 trunkgroup = pris[*span].mastertrunkgroup; 07182 if (trunkgroup) { 07183 /* Select a specific trunk group */ 07184 for (x = 0; x < NUM_SPANS; x++) { 07185 if (pris[x].trunkgroup == trunkgroup) { 07186 *span = x; 07187 return 0; 07188 } 07189 } 07190 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup); 07191 *span = -1; 07192 } else { 07193 if (pris[*span].trunkgroup) { 07194 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup); 07195 *span = -1; 07196 } else if (pris[*span].mastertrunkgroup) { 07197 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup); 07198 *span = -1; 07199 } else { 07200 if (si->totalchans == 31) { 07201 /* E1 */ 07202 pris[*span].dchannels[0] = 16 + offset; 07203 } else if (si->totalchans == 24) { 07204 /* T1 or J1 */ 07205 pris[*span].dchannels[0] = 24 + offset; 07206 } else if (si->totalchans == 3) { 07207 /* BRI */ 07208 pris[*span].dchannels[0] = 3 + offset; 07209 } else { 07210 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); 07211 *span = -1; 07212 return 0; 07213 } 07214 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED; 07215 pris[*span].offset = offset; 07216 pris[*span].span = *span + 1; 07217 } 07218 } 07219 return 0; 07220 }
static int process_dahdi | ( | struct dahdi_chan_conf * | confp, | |
const char * | cat, | |||
struct ast_variable * | v, | |||
int | reload, | |||
int | skipchannels | |||
) | [static] |
Definition at line 10994 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().
10995 { 10996 struct dahdi_pvt *tmp; 10997 int y; 10998 int found_pseudo = 0; 10999 char dahdichan[MAX_CHANLIST_LEN] = {}; 11000 11001 for (; v; v = v->next) { 11002 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 11003 continue; 11004 11005 /* Create the interface list */ 11006 if (!strcasecmp(v->name, "channel") 11007 #ifdef HAVE_PRI 11008 || !strcasecmp(v->name, "crv") 11009 #endif 11010 ) { 11011 int iscrv; 11012 if (skipchannels) 11013 continue; 11014 iscrv = !strcasecmp(v->name, "crv"); 11015 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo)) 11016 return -1; 11017 } else if (!strcasecmp(v->name, "buffers")) { 11018 int res; 11019 char policy[21] = ""; 11020 11021 res = sscanf(v->value, "%d,%20s", &confp->chan.buf_no, policy); 11022 if (res != 2) { 11023 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n"); 11024 confp->chan.buf_no = numbufs; 11025 continue; 11026 } 11027 if (confp->chan.buf_no < 0) 11028 confp->chan.buf_no = numbufs; 11029 if (!strcasecmp(policy, "full")) { 11030 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL; 11031 } else if (!strcasecmp(policy, "immediate")) { 11032 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE; 11033 } else { 11034 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy); 11035 } 11036 } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) { 11037 ast_copy_string(dahdichan, v->value, sizeof(dahdichan)); 11038 if (v->name[0] == 'z' || v->name[0] == 'Z') { 11039 ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat); 11040 } 11041 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) { 11042 if (ast_true(v->value)) 11043 confp->chan.usedistinctiveringdetection = 1; 11044 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) { 11045 if (ast_true(v->value)) 11046 distinctiveringaftercid = 1; 11047 } else if (!strcasecmp(v->name, "dring1context")) { 11048 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData)); 11049 } else if (!strcasecmp(v->name, "dring2context")) { 11050 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData)); 11051 } else if (!strcasecmp(v->name, "dring3context")) { 11052 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData)); 11053 } else if (!strcasecmp(v->name, "dring1")) { 11054 sscanf(v->value, "%d,%d,%d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]); 11055 } else if (!strcasecmp(v->name, "dring2")) { 11056 sscanf(v->value, "%d,%d,%d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]); 11057 } else if (!strcasecmp(v->name, "dring3")) { 11058 sscanf(v->value, "%d,%d,%d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]); 11059 } else if (!strcasecmp(v->name, "usecallerid")) { 11060 confp->chan.use_callerid = ast_true(v->value); 11061 } else if (!strcasecmp(v->name, "cidsignalling")) { 11062 if (!strcasecmp(v->value, "bell")) 11063 confp->chan.cid_signalling = CID_SIG_BELL; 11064 else if (!strcasecmp(v->value, "v23")) 11065 confp->chan.cid_signalling = CID_SIG_V23; 11066 else if (!strcasecmp(v->value, "dtmf")) 11067 confp->chan.cid_signalling = CID_SIG_DTMF; 11068 else if (!strcasecmp(v->value, "smdi")) 11069 confp->chan.cid_signalling = CID_SIG_SMDI; 11070 else if (!strcasecmp(v->value, "v23_jp")) 11071 confp->chan.cid_signalling = CID_SIG_V23_JP; 11072 else if (ast_true(v->value)) 11073 confp->chan.cid_signalling = CID_SIG_BELL; 11074 } else if (!strcasecmp(v->name, "cidstart")) { 11075 if (!strcasecmp(v->value, "ring")) 11076 confp->chan.cid_start = CID_START_RING; 11077 else if (!strcasecmp(v->value, "polarity")) 11078 confp->chan.cid_start = CID_START_POLARITY; 11079 else if (ast_true(v->value)) 11080 confp->chan.cid_start = CID_START_RING; 11081 } else if (!strcasecmp(v->name, "threewaycalling")) { 11082 confp->chan.threewaycalling = ast_true(v->value); 11083 } else if (!strcasecmp(v->name, "cancallforward")) { 11084 confp->chan.cancallforward = ast_true(v->value); 11085 } else if (!strcasecmp(v->name, "relaxdtmf")) { 11086 if (ast_true(v->value)) 11087 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 11088 else 11089 confp->chan.dtmfrelax = 0; 11090 } else if (!strcasecmp(v->name, "mailbox")) { 11091 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox)); 11092 } else if (!strcasecmp(v->name, "hasvoicemail")) { 11093 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) { 11094 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox)); 11095 } 11096 } else if (!strcasecmp(v->name, "adsi")) { 11097 confp->chan.adsi = ast_true(v->value); 11098 } else if (!strcasecmp(v->name, "usesmdi")) { 11099 confp->chan.use_smdi = ast_true(v->value); 11100 } else if (!strcasecmp(v->name, "smdiport")) { 11101 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port)); 11102 } else if (!strcasecmp(v->name, "transfer")) { 11103 confp->chan.transfer = ast_true(v->value); 11104 } else if (!strcasecmp(v->name, "canpark")) { 11105 confp->chan.canpark = ast_true(v->value); 11106 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) { 11107 confp->chan.echocanbridged = ast_true(v->value); 11108 } else if (!strcasecmp(v->name, "busydetect")) { 11109 confp->chan.busydetect = ast_true(v->value); 11110 } else if (!strcasecmp(v->name, "busycount")) { 11111 confp->chan.busycount = atoi(v->value); 11112 } else if (!strcasecmp(v->name, "silencethreshold")) { 11113 confp->chan.silencethreshold = atoi(v->value); 11114 } else if (!strcasecmp(v->name, "busycompare")) { 11115 confp->chan.busycompare = ast_true(v->value); 11116 } else if (!strcasecmp(v->name, "busypattern")) { 11117 int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength); 11118 if (count == 1) 11119 confp->chan.busyquietlength = 0; 11120 else if (count < 1) 11121 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n"); 11122 } else if (!strcasecmp(v->name, "busyfuzziness")) { 11123 confp->chan.busyfuzziness = atoi(v->value); 11124 } else if (!strcasecmp(v->name, "callprogress")) { 11125 if (ast_true(v->value)) 11126 confp->chan.callprogress |= 1; 11127 else 11128 confp->chan.callprogress &= ~1; 11129 } else if (!strcasecmp(v->name, "faxdetect")) { 11130 if (!strcasecmp(v->value, "incoming")) { 11131 confp->chan.callprogress |= 4; 11132 confp->chan.callprogress &= ~2; 11133 } else if (!strcasecmp(v->value, "outgoing")) { 11134 confp->chan.callprogress &= ~4; 11135 confp->chan.callprogress |= 2; 11136 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) 11137 confp->chan.callprogress |= 6; 11138 else 11139 confp->chan.callprogress &= ~6; 11140 } else if (!strcasecmp(v->name, "echocancel")) { 11141 if (!ast_strlen_zero(v->value)) { 11142 y = atoi(v->value); 11143 } else 11144 y = 0; 11145 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024)) 11146 confp->chan.echocancel = y; 11147 else { 11148 confp->chan.echocancel = ast_true(v->value); 11149 if (confp->chan.echocancel) 11150 confp->chan.echocancel=128; 11151 } 11152 } else if (!strcasecmp(v->name, "echotraining")) { 11153 if (sscanf(v->value, "%d", &y) == 1) { 11154 if ((y < 10) || (y > 4000)) { 11155 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno); 11156 } else { 11157 confp->chan.echotraining = y; 11158 } 11159 } else if (ast_true(v->value)) { 11160 confp->chan.echotraining = 400; 11161 } else 11162 confp->chan.echotraining = 0; 11163 } else if (!strcasecmp(v->name, "hidecallerid")) { 11164 confp->chan.hidecallerid = ast_true(v->value); 11165 } else if (!strcasecmp(v->name, "hidecalleridname")) { 11166 confp->chan.hidecalleridname = ast_true(v->value); 11167 } else if (!strcasecmp(v->name, "pulsedial")) { 11168 confp->chan.pulse = ast_true(v->value); 11169 } else if (!strcasecmp(v->name, "callreturn")) { 11170 confp->chan.callreturn = ast_true(v->value); 11171 } else if (!strcasecmp(v->name, "callwaiting")) { 11172 confp->chan.callwaiting = ast_true(v->value); 11173 } else if (!strcasecmp(v->name, "callwaitingcallerid")) { 11174 confp->chan.callwaitingcallerid = ast_true(v->value); 11175 } else if (!strcasecmp(v->name, "context")) { 11176 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context)); 11177 } else if (!strcasecmp(v->name, "language")) { 11178 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language)); 11179 } else if (!strcasecmp(v->name, "progzone")) { 11180 ast_copy_string(progzone, v->value, sizeof(progzone)); 11181 } else if (!strcasecmp(v->name, "mohinterpret") 11182 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) { 11183 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret)); 11184 } else if (!strcasecmp(v->name, "mohsuggest")) { 11185 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest)); 11186 } else if (!strcasecmp(v->name, "stripmsd")) { 11187 confp->chan.stripmsd = atoi(v->value); 11188 } else if (!strcasecmp(v->name, "jitterbuffers")) { 11189 numbufs = atoi(v->value); 11190 } else if (!strcasecmp(v->name, "group")) { 11191 confp->chan.group = ast_get_group(v->value); 11192 } else if (!strcasecmp(v->name, "callgroup")) { 11193 confp->chan.callgroup = ast_get_group(v->value); 11194 } else if (!strcasecmp(v->name, "pickupgroup")) { 11195 confp->chan.pickupgroup = ast_get_group(v->value); 11196 } else if (!strcasecmp(v->name, "immediate")) { 11197 confp->chan.immediate = ast_true(v->value); 11198 } else if (!strcasecmp(v->name, "transfertobusy")) { 11199 confp->chan.transfertobusy = ast_true(v->value); 11200 } else if (!strcasecmp(v->name, "rxgain")) { 11201 if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) { 11202 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value); 11203 } 11204 } else if (!strcasecmp(v->name, "txgain")) { 11205 if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) { 11206 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value); 11207 } 11208 } else if (!strcasecmp(v->name, "tonezone")) { 11209 if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) { 11210 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value); 11211 } 11212 } else if (!strcasecmp(v->name, "callerid")) { 11213 if (!strcasecmp(v->value, "asreceived")) { 11214 confp->chan.cid_num[0] = '\0'; 11215 confp->chan.cid_name[0] = '\0'; 11216 } else { 11217 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num)); 11218 } 11219 } else if (!strcasecmp(v->name, "fullname")) { 11220 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name)); 11221 } else if (!strcasecmp(v->name, "cid_number")) { 11222 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num)); 11223 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) { 11224 confp->chan.dahditrcallerid = ast_true(v->value); 11225 if (strstr(v->name, "zap")) { 11226 ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat); 11227 } 11228 } else if (!strcasecmp(v->name, "restrictcid")) { 11229 confp->chan.restrictcid = ast_true(v->value); 11230 } else if (!strcasecmp(v->name, "usecallingpres")) { 11231 confp->chan.use_callingpres = ast_true(v->value); 11232 } else if (!strcasecmp(v->name, "accountcode")) { 11233 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode)); 11234 } else if (!strcasecmp(v->name, "amaflags")) { 11235 y = ast_cdr_amaflags2int(v->value); 11236 if (y < 0) 11237 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno); 11238 else 11239 confp->chan.amaflags = y; 11240 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) { 11241 confp->chan.polarityonanswerdelay = atoi(v->value); 11242 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) { 11243 confp->chan.answeronpolarityswitch = ast_true(v->value); 11244 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) { 11245 confp->chan.hanguponpolarityswitch = ast_true(v->value); 11246 } else if (!strcasecmp(v->name, "sendcalleridafter")) { 11247 confp->chan.sendcalleridafter = atoi(v->value); 11248 } else if (reload != 1){ 11249 if (!strcasecmp(v->name, "signalling")) { 11250 confp->chan.outsigmod = -1; 11251 if (!strcasecmp(v->value, "em")) { 11252 confp->chan.sig = SIG_EM; 11253 } else if (!strcasecmp(v->value, "em_e1")) { 11254 confp->chan.sig = SIG_EM_E1; 11255 } else if (!strcasecmp(v->value, "em_w")) { 11256 confp->chan.sig = SIG_EMWINK; 11257 confp->chan.radio = 0; 11258 } else if (!strcasecmp(v->value, "fxs_ls")) { 11259 confp->chan.sig = SIG_FXSLS; 11260 confp->chan.radio = 0; 11261 } else if (!strcasecmp(v->value, "fxs_gs")) { 11262 confp->chan.sig = SIG_FXSGS; 11263 confp->chan.radio = 0; 11264 } else if (!strcasecmp(v->value, "fxs_ks")) { 11265 confp->chan.sig = SIG_FXSKS; 11266 confp->chan.radio = 0; 11267 } else if (!strcasecmp(v->value, "fxo_ls")) { 11268 confp->chan.sig = SIG_FXOLS; 11269 confp->chan.radio = 0; 11270 } else if (!strcasecmp(v->value, "fxo_gs")) { 11271 confp->chan.sig = SIG_FXOGS; 11272 confp->chan.radio = 0; 11273 } else if (!strcasecmp(v->value, "fxo_ks")) { 11274 confp->chan.sig = SIG_FXOKS; 11275 confp->chan.radio = 0; 11276 } else if (!strcasecmp(v->value, "fxs_rx")) { 11277 confp->chan.sig = SIG_FXSKS; 11278 confp->chan.radio = 1; 11279 } else if (!strcasecmp(v->value, "fxo_rx")) { 11280 confp->chan.sig = SIG_FXOLS; 11281 confp->chan.radio = 1; 11282 } else if (!strcasecmp(v->value, "fxs_tx")) { 11283 confp->chan.sig = SIG_FXSLS; 11284 confp->chan.radio = 1; 11285 } else if (!strcasecmp(v->value, "fxo_tx")) { 11286 confp->chan.sig = SIG_FXOGS; 11287 confp->chan.radio = 1; 11288 } else if (!strcasecmp(v->value, "em_rx")) { 11289 confp->chan.sig = SIG_EM; 11290 confp->chan.radio = 1; 11291 } else if (!strcasecmp(v->value, "em_tx")) { 11292 confp->chan.sig = SIG_EM; 11293 confp->chan.radio = 1; 11294 } else if (!strcasecmp(v->value, "em_rxtx")) { 11295 confp->chan.sig = SIG_EM; 11296 confp->chan.radio = 2; 11297 } else if (!strcasecmp(v->value, "em_txrx")) { 11298 confp->chan.sig = SIG_EM; 11299 confp->chan.radio = 2; 11300 } else if (!strcasecmp(v->value, "sf")) { 11301 confp->chan.sig = SIG_SF; 11302 confp->chan.radio = 0; 11303 } else if (!strcasecmp(v->value, "sf_w")) { 11304 confp->chan.sig = SIG_SFWINK; 11305 confp->chan.radio = 0; 11306 } else if (!strcasecmp(v->value, "sf_featd")) { 11307 confp->chan.sig = SIG_FEATD; 11308 confp->chan.radio = 0; 11309 } else if (!strcasecmp(v->value, "sf_featdmf")) { 11310 confp->chan.sig = SIG_FEATDMF; 11311 confp->chan.radio = 0; 11312 } else if (!strcasecmp(v->value, "sf_featb")) { 11313 confp->chan.sig = SIG_SF_FEATB; 11314 confp->chan.radio = 0; 11315 } else if (!strcasecmp(v->value, "sf")) { 11316 confp->chan.sig = SIG_SF; 11317 confp->chan.radio = 0; 11318 } else if (!strcasecmp(v->value, "sf_rx")) { 11319 confp->chan.sig = SIG_SF; 11320 confp->chan.radio = 1; 11321 } else if (!strcasecmp(v->value, "sf_tx")) { 11322 confp->chan.sig = SIG_SF; 11323 confp->chan.radio = 1; 11324 } else if (!strcasecmp(v->value, "sf_rxtx")) { 11325 confp->chan.sig = SIG_SF; 11326 confp->chan.radio = 2; 11327 } else if (!strcasecmp(v->value, "sf_txrx")) { 11328 confp->chan.sig = SIG_SF; 11329 confp->chan.radio = 2; 11330 } else if (!strcasecmp(v->value, "featd")) { 11331 confp->chan.sig = SIG_FEATD; 11332 confp->chan.radio = 0; 11333 } else if (!strcasecmp(v->value, "featdmf")) { 11334 confp->chan.sig = SIG_FEATDMF; 11335 confp->chan.radio = 0; 11336 } else if (!strcasecmp(v->value, "featdmf_ta")) { 11337 confp->chan.sig = SIG_FEATDMF_TA; 11338 confp->chan.radio = 0; 11339 } else if (!strcasecmp(v->value, "e911")) { 11340 confp->chan.sig = SIG_E911; 11341 confp->chan.radio = 0; 11342 } else if (!strcasecmp(v->value, "fgccama")) { 11343 confp->chan.sig = SIG_FGC_CAMA; 11344 confp->chan.radio = 0; 11345 } else if (!strcasecmp(v->value, "fgccamamf")) { 11346 confp->chan.sig = SIG_FGC_CAMAMF; 11347 confp->chan.radio = 0; 11348 } else if (!strcasecmp(v->value, "featb")) { 11349 confp->chan.sig = SIG_FEATB; 11350 confp->chan.radio = 0; 11351 #ifdef HAVE_PRI 11352 } else if (!strcasecmp(v->value, "pri_net")) { 11353 confp->chan.radio = 0; 11354 confp->chan.sig = SIG_PRI; 11355 confp->pri.nodetype = PRI_NETWORK; 11356 } else if (!strcasecmp(v->value, "pri_cpe")) { 11357 confp->chan.sig = SIG_PRI; 11358 confp->chan.radio = 0; 11359 confp->pri.nodetype = PRI_CPE; 11360 } else if (!strcasecmp(v->value, "gr303fxoks_net")) { 11361 confp->chan.sig = SIG_GR303FXOKS; 11362 confp->chan.radio = 0; 11363 confp->pri.nodetype = PRI_NETWORK; 11364 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) { 11365 confp->chan.sig = SIG_GR303FXSKS; 11366 confp->chan.radio = 0; 11367 confp->pri.nodetype = PRI_CPE; 11368 #endif 11369 } else { 11370 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value); 11371 } 11372 } else if (!strcasecmp(v->name, "outsignalling")) { 11373 if (!strcasecmp(v->value, "em")) { 11374 confp->chan.outsigmod = SIG_EM; 11375 } else if (!strcasecmp(v->value, "em_e1")) { 11376 confp->chan.outsigmod = SIG_EM_E1; 11377 } else if (!strcasecmp(v->value, "em_w")) { 11378 confp->chan.outsigmod = SIG_EMWINK; 11379 } else if (!strcasecmp(v->value, "sf")) { 11380 confp->chan.outsigmod = SIG_SF; 11381 } else if (!strcasecmp(v->value, "sf_w")) { 11382 confp->chan.outsigmod = SIG_SFWINK; 11383 } else if (!strcasecmp(v->value, "sf_featd")) { 11384 confp->chan.outsigmod = SIG_FEATD; 11385 } else if (!strcasecmp(v->value, "sf_featdmf")) { 11386 confp->chan.outsigmod = SIG_FEATDMF; 11387 } else if (!strcasecmp(v->value, "sf_featb")) { 11388 confp->chan.outsigmod = SIG_SF_FEATB; 11389 } else if (!strcasecmp(v->value, "sf")) { 11390 confp->chan.outsigmod = SIG_SF; 11391 } else if (!strcasecmp(v->value, "featd")) { 11392 confp->chan.outsigmod = SIG_FEATD; 11393 } else if (!strcasecmp(v->value, "featdmf")) { 11394 confp->chan.outsigmod = SIG_FEATDMF; 11395 } else if (!strcasecmp(v->value, "featdmf_ta")) { 11396 confp->chan.outsigmod = SIG_FEATDMF_TA; 11397 } else if (!strcasecmp(v->value, "e911")) { 11398 confp->chan.outsigmod = SIG_E911; 11399 } else if (!strcasecmp(v->value, "fgccama")) { 11400 confp->chan.outsigmod = SIG_FGC_CAMA; 11401 } else if (!strcasecmp(v->value, "fgccamamf")) { 11402 confp->chan.outsigmod = SIG_FGC_CAMAMF; 11403 } else if (!strcasecmp(v->value, "featb")) { 11404 confp->chan.outsigmod = SIG_FEATB; 11405 } else { 11406 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value); 11407 } 11408 #ifdef HAVE_PRI 11409 } else if (!strcasecmp(v->name, "pridialplan")) { 11410 if (!strcasecmp(v->value, "national")) { 11411 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1; 11412 } else if (!strcasecmp(v->value, "unknown")) { 11413 confp->pri.dialplan = PRI_UNKNOWN + 1; 11414 } else if (!strcasecmp(v->value, "private")) { 11415 confp->pri.dialplan = PRI_PRIVATE + 1; 11416 } else if (!strcasecmp(v->value, "international")) { 11417 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1; 11418 } else if (!strcasecmp(v->value, "local")) { 11419 confp->pri.dialplan = PRI_LOCAL_ISDN + 1; 11420 } else if (!strcasecmp(v->value, "dynamic")) { 11421 confp->pri.dialplan = -1; 11422 } else { 11423 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 11424 } 11425 } else if (!strcasecmp(v->name, "prilocaldialplan")) { 11426 if (!strcasecmp(v->value, "national")) { 11427 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1; 11428 } else if (!strcasecmp(v->value, "unknown")) { 11429 confp->pri.localdialplan = PRI_UNKNOWN + 1; 11430 } else if (!strcasecmp(v->value, "private")) { 11431 confp->pri.localdialplan = PRI_PRIVATE + 1; 11432 } else if (!strcasecmp(v->value, "international")) { 11433 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1; 11434 } else if (!strcasecmp(v->value, "local")) { 11435 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1; 11436 } else if (!strcasecmp(v->value, "dynamic")) { 11437 confp->pri.localdialplan = -1; 11438 } else { 11439 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 11440 } 11441 } else if (!strcasecmp(v->name, "switchtype")) { 11442 if (!strcasecmp(v->value, "national")) 11443 confp->pri.switchtype = PRI_SWITCH_NI2; 11444 else if (!strcasecmp(v->value, "ni1")) 11445 confp->pri.switchtype = PRI_SWITCH_NI1; 11446 else if (!strcasecmp(v->value, "dms100")) 11447 confp->pri.switchtype = PRI_SWITCH_DMS100; 11448 else if (!strcasecmp(v->value, "4ess")) 11449 confp->pri.switchtype = PRI_SWITCH_ATT4ESS; 11450 else if (!strcasecmp(v->value, "5ess")) 11451 confp->pri.switchtype = PRI_SWITCH_LUCENT5E; 11452 else if (!strcasecmp(v->value, "euroisdn")) 11453 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1; 11454 else if (!strcasecmp(v->value, "qsig")) 11455 confp->pri.switchtype = PRI_SWITCH_QSIG; 11456 else { 11457 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value); 11458 return -1; 11459 } 11460 } else if (!strcasecmp(v->name, "nsf")) { 11461 if (!strcasecmp(v->value, "sdn")) 11462 confp->pri.nsf = PRI_NSF_SDN; 11463 else if (!strcasecmp(v->value, "megacom")) 11464 confp->pri.nsf = PRI_NSF_MEGACOM; 11465 else if (!strcasecmp(v->value, "tollfreemegacom")) 11466 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM; 11467 else if (!strcasecmp(v->value, "accunet")) 11468 confp->pri.nsf = PRI_NSF_ACCUNET; 11469 else if (!strcasecmp(v->value, "none")) 11470 confp->pri.nsf = PRI_NSF_NONE; 11471 else { 11472 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value); 11473 confp->pri.nsf = PRI_NSF_NONE; 11474 } 11475 } else if (!strcasecmp(v->name, "priindication")) { 11476 if (!strcasecmp(v->value, "outofband")) 11477 confp->chan.priindication_oob = 1; 11478 else if (!strcasecmp(v->value, "inband")) 11479 confp->chan.priindication_oob = 0; 11480 else 11481 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n", 11482 v->value, v->lineno); 11483 } else if (!strcasecmp(v->name, "priexclusive")) { 11484 confp->chan.priexclusive = ast_true(v->value); 11485 } else if (!strcasecmp(v->name, "internationalprefix")) { 11486 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix)); 11487 } else if (!strcasecmp(v->name, "nationalprefix")) { 11488 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix)); 11489 } else if (!strcasecmp(v->name, "localprefix")) { 11490 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix)); 11491 } else if (!strcasecmp(v->name, "privateprefix")) { 11492 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix)); 11493 } else if (!strcasecmp(v->name, "unknownprefix")) { 11494 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix)); 11495 } else if (!strcasecmp(v->name, "resetinterval")) { 11496 if (!strcasecmp(v->value, "never")) 11497 confp->pri.resetinterval = -1; 11498 else if (atoi(v->value) >= 60) 11499 confp->pri.resetinterval = atoi(v->value); 11500 else 11501 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n", 11502 v->value, v->lineno); 11503 } else if (!strcasecmp(v->name, "minunused")) { 11504 confp->pri.minunused = atoi(v->value); 11505 } else if (!strcasecmp(v->name, "minidle")) { 11506 confp->pri.minidle = atoi(v->value); 11507 } else if (!strcasecmp(v->name, "idleext")) { 11508 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext)); 11509 } else if (!strcasecmp(v->name, "idledial")) { 11510 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial)); 11511 } else if (!strcasecmp(v->name, "overlapdial")) { 11512 confp->pri.overlapdial = ast_true(v->value); 11513 #ifdef HAVE_PRI_INBANDDISCONNECT 11514 } else if (!strcasecmp(v->name, "inbanddisconnect")) { 11515 confp->pri.inbanddisconnect = ast_true(v->value); 11516 #endif 11517 } else if (!strcasecmp(v->name, "pritimer")) { 11518 #ifdef PRI_GETSET_TIMERS 11519 char *timerc, *c; 11520 int timer, timeridx; 11521 c = v->value; 11522 timerc = strsep(&c, ","); 11523 if (timerc) { 11524 timer = atoi(c); 11525 if (!timer) 11526 ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer\n", timerc); 11527 else { 11528 if ((timeridx = pri_timer2idx(timerc)) >= 0) 11529 pritimers[timeridx] = timer; 11530 else 11531 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer\n", timerc); 11532 } 11533 } else 11534 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string\n", v->value); 11535 11536 } else if (!strcasecmp(v->name, "facilityenable")) { 11537 confp->pri.facilityenable = ast_true(v->value); 11538 #endif /* PRI_GETSET_TIMERS */ 11539 #endif /* HAVE_PRI */ 11540 } else if (!strcasecmp(v->name, "cadence")) { 11541 /* setup to scan our argument */ 11542 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 11543 int i; 11544 struct dahdi_ring_cadence new_cadence; 11545 int cid_location = -1; 11546 int firstcadencepos = 0; 11547 char original_args[80]; 11548 int cadence_is_ok = 1; 11549 11550 ast_copy_string(original_args, v->value, sizeof(original_args)); 11551 /* 16 cadences allowed (8 pairs) */ 11552 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]); 11553 11554 /* Cadence must be even (on/off) */ 11555 if (element_count % 2 == 1) { 11556 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args); 11557 cadence_is_ok = 0; 11558 } 11559 11560 /* Ring cadences cannot be negative */ 11561 for (i = 0; i < element_count; i++) { 11562 if (c[i] == 0) { 11563 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args); 11564 cadence_is_ok = 0; 11565 break; 11566 } else if (c[i] < 0) { 11567 if (i % 2 == 1) { 11568 /* Silence duration, negative possibly okay */ 11569 if (cid_location == -1) { 11570 cid_location = i; 11571 c[i] *= -1; 11572 } else { 11573 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args); 11574 cadence_is_ok = 0; 11575 break; 11576 } 11577 } else { 11578 if (firstcadencepos == 0) { 11579 firstcadencepos = i; /* only recorded to avoid duplicate specification */ 11580 /* duration will be passed negative to the DAHDI driver */ 11581 } else { 11582 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args); 11583 cadence_is_ok = 0; 11584 break; 11585 } 11586 } 11587 } 11588 } 11589 11590 /* Substitute our scanned cadence */ 11591 for (i = 0; i < 16; i++) { 11592 new_cadence.ringcadence[i] = c[i]; 11593 } 11594 11595 if (cadence_is_ok) { 11596 /* ---we scanned it without getting annoyed; now some sanity checks--- */ 11597 if (element_count < 2) { 11598 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args); 11599 } else { 11600 if (cid_location == -1) { 11601 /* user didn't say; default to first pause */ 11602 cid_location = 1; 11603 } else { 11604 /* convert element_index to cidrings value */ 11605 cid_location = (cid_location + 1) / 2; 11606 } 11607 /* ---we like their cadence; try to install it--- */ 11608 if (!user_has_defined_cadences++) 11609 /* this is the first user-defined cadence; clear the default user cadences */ 11610 num_cadence = 0; 11611 if ((num_cadence+1) >= NUM_CADENCE_MAX) 11612 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args); 11613 else { 11614 cadences[num_cadence] = new_cadence; 11615 cidrings[num_cadence++] = cid_location; 11616 if (option_verbose > 2) 11617 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args); 11618 } 11619 } 11620 } 11621 } else if (!strcasecmp(v->name, "ringtimeout")) { 11622 ringt_base = (atoi(v->value) * 8) / READ_SIZE; 11623 } else if (!strcasecmp(v->name, "prewink")) { 11624 confp->timing.prewinktime = atoi(v->value); 11625 } else if (!strcasecmp(v->name, "preflash")) { 11626 confp->timing.preflashtime = atoi(v->value); 11627 } else if (!strcasecmp(v->name, "wink")) { 11628 confp->timing.winktime = atoi(v->value); 11629 } else if (!strcasecmp(v->name, "flash")) { 11630 confp->timing.flashtime = atoi(v->value); 11631 } else if (!strcasecmp(v->name, "start")) { 11632 confp->timing.starttime = atoi(v->value); 11633 } else if (!strcasecmp(v->name, "rxwink")) { 11634 confp->timing.rxwinktime = atoi(v->value); 11635 } else if (!strcasecmp(v->name, "rxflash")) { 11636 confp->timing.rxflashtime = atoi(v->value); 11637 } else if (!strcasecmp(v->name, "debounce")) { 11638 confp->timing.debouncetime = atoi(v->value); 11639 } else if (!strcasecmp(v->name, "toneduration")) { 11640 int toneduration; 11641 int ctlfd; 11642 int res; 11643 struct dahdi_dialparams dps; 11644 11645 ctlfd = open(DAHDI_FILE_CTL, O_RDWR); 11646 11647 if (ctlfd == -1) { 11648 ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n"); 11649 return -1; 11650 } 11651 11652 toneduration = atoi(v->value); 11653 if (toneduration > -1) { 11654 memset(&dps, 0, sizeof(dps)); 11655 11656 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration; 11657 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps); 11658 if (res < 0) { 11659 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno)); 11660 return -1; 11661 } 11662 } 11663 close(ctlfd); 11664 } else if (!strcasecmp(v->name, "defaultcic")) { 11665 ast_copy_string(defaultcic, v->value, sizeof(defaultcic)); 11666 } else if (!strcasecmp(v->name, "defaultozz")) { 11667 ast_copy_string(defaultozz, v->value, sizeof(defaultozz)); 11668 } 11669 } else if (!skipchannels) 11670 ast_log(LOG_WARNING, "Ignoring %s\n", v->name); 11671 } 11672 if (dahdichan[0]) { 11673 /* The user has set 'dahdichan' */ 11674 /*< \todo pass proper line number instead of 0 */ 11675 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) { 11676 return -1; 11677 } 11678 } 11679 /*< \todo why check for the pseudo in the per-channel section. 11680 * Any actual use for manual setup of the pseudo channel? */ 11681 if (!found_pseudo && reload == 0) { 11682 /* use the default configuration for a channel, so 11683 that any settings from real configured channels 11684 don't "leak" into the pseudo channel config 11685 */ 11686 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 11687 11688 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload); 11689 11690 if (tmp) { 11691 if (option_verbose > 2) 11692 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n"); 11693 } else { 11694 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n"); 11695 } 11696 } 11697 return 0; 11698 }
static char* redirectingreason2str | ( | int | redirectingreason | ) | [static] |
Definition at line 8487 of file chan_dahdi.c.
Referenced by __oh323_new().
08488 { 08489 switch (redirectingreason) { 08490 case 0: 08491 return "UNKNOWN"; 08492 case 1: 08493 return "BUSY"; 08494 case 2: 08495 return "NO_REPLY"; 08496 case 0xF: 08497 return "UNCONDITIONAL"; 08498 default: 08499 return "NOREDIRECT"; 08500 } 08501 }
static int reload | ( | void | ) | [static] |
Definition at line 12007 of file chan_dahdi.c.
References ast_log(), and setup_dahdi().
12008 { 12009 int res = 0; 12010 12011 res = setup_dahdi(1); 12012 if (res) { 12013 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n"); 12014 return -1; 12015 } 12016 return 0; 12017 }
static int reset_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1387 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().
01388 { 01389 struct dahdi_confinfo zi; 01390 memset(&zi, 0, sizeof(zi)); 01391 p->confno = -1; 01392 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf)); 01393 if (p->subs[SUB_REAL].dfd > -1) { 01394 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi)) 01395 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno)); 01396 } 01397 return 0; 01398 }
static int restart_monitor | ( | void | ) | [static] |
Definition at line 7144 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().
07145 { 07146 pthread_attr_t attr; 07147 pthread_attr_init(&attr); 07148 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 07149 /* If we're supposed to be stopped -- stay stopped */ 07150 if (monitor_thread == AST_PTHREADT_STOP) 07151 return 0; 07152 ast_mutex_lock(&monlock); 07153 if (monitor_thread == pthread_self()) { 07154 ast_mutex_unlock(&monlock); 07155 ast_log(LOG_WARNING, "Cannot kill myself\n"); 07156 return -1; 07157 } 07158 if (monitor_thread != AST_PTHREADT_NULL) { 07159 /* Wake up the thread */ 07160 pthread_kill(monitor_thread, SIGURG); 07161 } else { 07162 /* Start a new monitor */ 07163 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) { 07164 ast_mutex_unlock(&monlock); 07165 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 07166 pthread_attr_destroy(&attr); 07167 return -1; 07168 } 07169 } 07170 ast_mutex_unlock(&monlock); 07171 pthread_attr_destroy(&attr); 07172 return 0; 07173 }
static int restore_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1720 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().
01721 { 01722 int res; 01723 if (p->saveconf.confmode) { 01724 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf); 01725 p->saveconf.confmode = 0; 01726 if (res) { 01727 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno)); 01728 return -1; 01729 } 01730 } 01731 if (option_debug) 01732 ast_log(LOG_DEBUG, "Restored conferencing\n"); 01733 return 0; 01734 }
static int restore_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1646 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().
01647 { 01648 int res; 01649 01650 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 01651 if (res) { 01652 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno)); 01653 return -1; 01654 } 01655 01656 return 0; 01657 }
static int save_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1692 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().
01693 { 01694 struct dahdi_confinfo c; 01695 int res; 01696 if (p->saveconf.confmode) { 01697 ast_log(LOG_WARNING, "Can't save conference -- already in use\n"); 01698 return -1; 01699 } 01700 p->saveconf.chan = 0; 01701 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf); 01702 if (res) { 01703 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno)); 01704 p->saveconf.confmode = 0; 01705 return -1; 01706 } 01707 c.chan = 0; 01708 c.confno = 0; 01709 c.confmode = DAHDI_CONF_NORMAL; 01710 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c); 01711 if (res) { 01712 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno)); 01713 return -1; 01714 } 01715 if (option_debug) 01716 ast_log(LOG_DEBUG, "Disabled conferencing\n"); 01717 return 0; 01718 }
static int send_callerid | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1760 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().
01761 { 01762 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */ 01763 int res; 01764 /* Take out of linear mode if necessary */ 01765 if (p->subs[SUB_REAL].linear) { 01766 p->subs[SUB_REAL].linear = 0; 01767 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 01768 } 01769 while (p->cidpos < p->cidlen) { 01770 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos); 01771 if (res < 0) { 01772 if (errno == EAGAIN) 01773 return 0; 01774 else { 01775 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 01776 return -1; 01777 } 01778 } 01779 if (!res) 01780 return 0; 01781 p->cidpos += res; 01782 } 01783 free(p->cidspill); 01784 p->cidspill = NULL; 01785 if (p->callwaitcas) { 01786 /* Wait for CID/CW to expire */ 01787 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES; 01788 } else 01789 restore_conference(p); 01790 return 0; 01791 }
static int send_cwcidspill | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1738 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().
01739 { 01740 p->callwaitcas = 0; 01741 p->cidcwexpire = 0; 01742 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) 01743 return -1; 01744 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p)); 01745 /* Make sure we account for the end */ 01746 p->cidlen += READ_SIZE * 4; 01747 p->cidpos = 0; 01748 send_callerid(p); 01749 if (option_verbose > 2) 01750 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num); 01751 return 0; 01752 }
static int send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 2375 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().
02376 { 02377 /* Data will be our digit string */ 02378 struct dahdi_pvt *p; 02379 char *digits = (char *) data; 02380 02381 if (ast_strlen_zero(digits)) { 02382 ast_log(LOG_DEBUG, "No digit string sent to application!\n"); 02383 return -1; 02384 } 02385 02386 p = (struct dahdi_pvt *)chan->tech_pvt; 02387 02388 if (!p) { 02389 ast_log(LOG_DEBUG, "Unable to find technology private\n"); 02390 return -1; 02391 } 02392 02393 ast_mutex_lock(&p->lock); 02394 02395 if (!p->pri || !p->call) { 02396 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n"); 02397 ast_mutex_unlock(&p->lock); 02398 return -1; 02399 } 02400 02401 if (!pri_grab(p, p->pri)) { 02402 pri_keypad_facility(p->pri->pri, p->call, digits); 02403 pri_rel(p->pri); 02404 } else { 02405 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n"); 02406 ast_mutex_unlock(&p->lock); 02407 return -1; 02408 } 02409 02410 ast_mutex_unlock(&p->lock); 02411 02412 return 0; 02413 }
static int set_actual_gain | ( | int | fd, | |
int | chan, | |||
float | rxgain, | |||
float | txgain, | |||
int | law | |||
) | [static] |
Definition at line 1627 of file chan_dahdi.c.
References set_actual_rxgain(), and set_actual_txgain().
Referenced by bump_gains(), dahdi_call(), and restore_gains().
01628 { 01629 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law); 01630 }
static int set_actual_rxgain | ( | int | fd, | |
int | chan, | |||
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 1609 of file chan_dahdi.c.
References ast_log(), errno, fill_rxgain(), and LOG_DEBUG.
Referenced by dahdi_setoption(), and set_actual_gain().
01610 { 01611 struct dahdi_gains g; 01612 int res; 01613 01614 memset(&g, 0, sizeof(g)); 01615 g.chan = chan; 01616 res = ioctl(fd, DAHDI_GETGAINS, &g); 01617 if (res) { 01618 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno)); 01619 return res; 01620 } 01621 01622 fill_rxgain(&g, gain, law); 01623 01624 return ioctl(fd, DAHDI_SETGAINS, &g); 01625 }
static int set_actual_txgain | ( | int | fd, | |
int | chan, | |||
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 1590 of file chan_dahdi.c.
References ast_log(), errno, fill_txgain(), LOG_DEBUG, and option_debug.
Referenced by dahdi_setoption(), and set_actual_gain().
01591 { 01592 struct dahdi_gains g; 01593 int res; 01594 01595 memset(&g, 0, sizeof(g)); 01596 g.chan = chan; 01597 res = ioctl(fd, DAHDI_GETGAINS, &g); 01598 if (res) { 01599 if (option_debug) 01600 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno)); 01601 return res; 01602 } 01603 01604 fill_txgain(&g, gain, law); 01605 01606 return ioctl(fd, DAHDI_SETGAINS, &g); 01607 }
static int setup_dahdi | ( | int | reload | ) | [static] |
Definition at line 11700 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().
11701 { 11702 struct ast_config *cfg; 11703 struct ast_variable *v; 11704 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 11705 int res; 11706 11707 #ifdef HAVE_PRI 11708 char *c; 11709 int spanno; 11710 int i, x; 11711 int logicalspan; 11712 int trunkgroup; 11713 int dchannels[NUM_DCHANS]; 11714 #endif 11715 11716 #ifdef HAVE_ZAPTEL 11717 int load_from_zapata_conf = 1; 11718 #else 11719 int load_from_zapata_conf = (dahdi_chan_mode == CHAN_ZAP_MODE); 11720 #endif 11721 11722 if (load_from_zapata_conf) { 11723 if (!(cfg = ast_config_load("zapata.conf"))) { 11724 ast_log(LOG_ERROR, "Unable to load zapata.conf\n"); 11725 return 0; 11726 } 11727 } else { 11728 if (!(cfg = ast_config_load("chan_dahdi.conf"))) { 11729 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n"); 11730 return 0; 11731 } 11732 } 11733 11734 /* It's a little silly to lock it, but we mind as well just to be sure */ 11735 ast_mutex_lock(&iflock); 11736 #ifdef HAVE_PRI 11737 if (reload != 1) { 11738 /* Process trunkgroups first */ 11739 v = ast_variable_browse(cfg, "trunkgroups"); 11740 while (v) { 11741 if (!strcasecmp(v->name, "trunkgroup")) { 11742 trunkgroup = atoi(v->value); 11743 if (trunkgroup > 0) { 11744 if ((c = strchr(v->value, ','))) { 11745 i = 0; 11746 memset(dchannels, 0, sizeof(dchannels)); 11747 while (c && (i < NUM_DCHANS)) { 11748 dchannels[i] = atoi(c + 1); 11749 if (dchannels[i] < 0) { 11750 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); 11751 } else 11752 i++; 11753 c = strchr(c + 1, ','); 11754 } 11755 if (i) { 11756 if (pri_create_trunkgroup(trunkgroup, dchannels)) { 11757 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); 11758 } else if (option_verbose > 1) 11759 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"); 11760 } else 11761 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 11762 } else 11763 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 11764 } else 11765 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno); 11766 } else if (!strcasecmp(v->name, "spanmap")) { 11767 spanno = atoi(v->value); 11768 if (spanno > 0) { 11769 if ((c = strchr(v->value, ','))) { 11770 trunkgroup = atoi(c + 1); 11771 if (trunkgroup > 0) { 11772 if ((c = strchr(c + 1, ','))) 11773 logicalspan = atoi(c + 1); 11774 else 11775 logicalspan = 0; 11776 if (logicalspan >= 0) { 11777 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { 11778 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 11779 } else if (option_verbose > 1) 11780 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 11781 } else 11782 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); 11783 } else 11784 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno); 11785 } else 11786 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno); 11787 } else 11788 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno); 11789 } else { 11790 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); 11791 } 11792 v = v->next; 11793 } 11794 } 11795 #endif 11796 11797 /* Copy the default jb config over global_jbconf */ 11798 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 11799 11800 v = ast_variable_browse(cfg, "channels"); 11801 res = process_dahdi(&conf, "", v, reload, 0); 11802 ast_mutex_unlock(&iflock); 11803 ast_config_destroy(cfg); 11804 if (res) 11805 return res; 11806 cfg = ast_config_load("users.conf"); 11807 if (cfg) { 11808 char *cat; 11809 const char *chans; 11810 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1); 11811 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) { 11812 if (!strcasecmp(cat, "general")) 11813 continue; 11814 chans = ast_variable_retrieve(cfg, cat, "dahdichan"); 11815 if (!ast_strlen_zero(chans)) { 11816 struct dahdi_chan_conf sect_conf; 11817 memcpy(§_conf, &conf, sizeof(sect_conf)); 11818 11819 process_dahdi(§_conf, cat, ast_variable_browse(cfg, cat), reload, 0); 11820 } 11821 } 11822 ast_config_destroy(cfg); 11823 } 11824 #ifdef HAVE_PRI 11825 if (reload != 1) { 11826 for (x = 0; x < NUM_SPANS; x++) { 11827 if (pris[x].pvts[0]) { 11828 if (start_pri(pris + x)) { 11829 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1); 11830 return -1; 11831 } else if (option_verbose > 1) 11832 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1); 11833 } 11834 } 11835 } 11836 #endif 11837 /* And start the monitor for the first time */ 11838 restart_monitor(); 11839 return 0; 11840 }
static void * ss_thread | ( | void * | data | ) | [static] |
Definition at line 5564 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().
05565 { 05566 struct ast_channel *chan = data; 05567 struct dahdi_pvt *p = chan->tech_pvt; 05568 char exten[AST_MAX_EXTENSION] = ""; 05569 char exten2[AST_MAX_EXTENSION] = ""; 05570 unsigned char buf[256]; 05571 char dtmfcid[300]; 05572 char dtmfbuf[300]; 05573 struct callerid_state *cs = NULL; 05574 char *name = NULL, *number = NULL; 05575 int distMatches; 05576 int curRingData[3]; 05577 int receivedRingT; 05578 int counter1; 05579 int counter; 05580 int samples = 0; 05581 struct ast_smdi_md_message *smdi_msg = NULL; 05582 int flags; 05583 int i; 05584 int timeout; 05585 int getforward = 0; 05586 char *s1, *s2; 05587 int len = 0; 05588 int res; 05589 int index; 05590 05591 ast_mutex_lock(&ss_thread_lock); 05592 ss_thread_count++; 05593 ast_mutex_unlock(&ss_thread_lock); 05594 /* in the bizarre case where the channel has become a zombie before we 05595 even get started here, abort safely 05596 */ 05597 if (!p) { 05598 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name); 05599 ast_hangup(chan); 05600 goto quit; 05601 } 05602 if (option_verbose > 2) 05603 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name); 05604 index = dahdi_get_index(chan, p, 1); 05605 if (index < 0) { 05606 ast_log(LOG_WARNING, "Huh?\n"); 05607 ast_hangup(chan); 05608 goto quit; 05609 } 05610 if (p->dsp) 05611 ast_dsp_digitreset(p->dsp); 05612 switch (p->sig) { 05613 #ifdef HAVE_PRI 05614 case SIG_PRI: 05615 /* Now loop looking for an extension */ 05616 ast_copy_string(exten, p->exten, sizeof(exten)); 05617 len = strlen(exten); 05618 res = 0; 05619 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 05620 if (len && !ast_ignore_pattern(chan->context, exten)) 05621 tone_zone_play_tone(p->subs[index].dfd, -1); 05622 else 05623 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 05624 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) 05625 timeout = matchdigittimeout; 05626 else 05627 timeout = gendigittimeout; 05628 res = ast_waitfordigit(chan, timeout); 05629 if (res < 0) { 05630 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 05631 ast_hangup(chan); 05632 goto quit; 05633 } else if (res) { 05634 exten[len++] = res; 05635 exten[len] = '\0'; 05636 } else 05637 break; 05638 } 05639 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */ 05640 if (ast_strlen_zero(exten)) { 05641 if (option_verbose > 2) 05642 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n"); 05643 exten[0] = 's'; 05644 exten[1] = '\0'; 05645 } 05646 tone_zone_play_tone(p->subs[index].dfd, -1); 05647 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) { 05648 /* Start the real PBX */ 05649 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 05650 if (p->dsp) ast_dsp_digitreset(p->dsp); 05651 dahdi_enable_ec(p); 05652 ast_setstate(chan, AST_STATE_RING); 05653 res = ast_pbx_run(chan); 05654 if (res) { 05655 ast_log(LOG_WARNING, "PBX exited non-zero!\n"); 05656 } 05657 } else { 05658 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context); 05659 chan->hangupcause = AST_CAUSE_UNALLOCATED; 05660 ast_hangup(chan); 05661 p->exten[0] = '\0'; 05662 /* Since we send release complete here, we won't get one */ 05663 p->call = NULL; 05664 } 05665 goto quit; 05666 break; 05667 #endif 05668 case SIG_FEATD: 05669 case SIG_FEATDMF: 05670 case SIG_FEATDMF_TA: 05671 case SIG_E911: 05672 case SIG_FGC_CAMAMF: 05673 case SIG_FEATB: 05674 case SIG_EMWINK: 05675 case SIG_SF_FEATD: 05676 case SIG_SF_FEATDMF: 05677 case SIG_SF_FEATB: 05678 case SIG_SFWINK: 05679 if (dahdi_wink(p, index)) 05680 goto quit; 05681 /* Fall through */ 05682 case SIG_EM: 05683 case SIG_EM_E1: 05684 case SIG_SF: 05685 case SIG_FGC_CAMA: 05686 res = tone_zone_play_tone(p->subs[index].dfd, -1); 05687 if (p->dsp) 05688 ast_dsp_digitreset(p->dsp); 05689 /* set digit mode appropriately */ 05690 if (p->dsp) { 05691 if (NEED_MFDETECT(p)) 05692 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 05693 else 05694 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 05695 } 05696 memset(dtmfbuf, 0, sizeof(dtmfbuf)); 05697 /* Wait for the first digit only if immediate=no */ 05698 if (!p->immediate) 05699 /* Wait for the first digit (up to 5 seconds). */ 05700 res = ast_waitfordigit(chan, 5000); 05701 else 05702 res = 0; 05703 if (res > 0) { 05704 /* save first char */ 05705 dtmfbuf[0] = res; 05706 switch (p->sig) { 05707 case SIG_FEATD: 05708 case SIG_SF_FEATD: 05709 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 05710 if (res > 0) 05711 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 05712 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 05713 break; 05714 case SIG_FEATDMF_TA: 05715 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 05716 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 05717 if (dahdi_wink(p, index)) goto quit; 05718 dtmfbuf[0] = 0; 05719 /* Wait for the first digit (up to 5 seconds). */ 05720 res = ast_waitfordigit(chan, 5000); 05721 if (res <= 0) break; 05722 dtmfbuf[0] = res; 05723 /* fall through intentionally */ 05724 case SIG_FEATDMF: 05725 case SIG_E911: 05726 case SIG_FGC_CAMAMF: 05727 case SIG_SF_FEATDMF: 05728 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 05729 /* if international caca, do it again to get real ANO */ 05730 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14)) 05731 { 05732 if (dahdi_wink(p, index)) goto quit; 05733 dtmfbuf[0] = 0; 05734 /* Wait for the first digit (up to 5 seconds). */ 05735 res = ast_waitfordigit(chan, 5000); 05736 if (res <= 0) break; 05737 dtmfbuf[0] = res; 05738 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 05739 } 05740 if (res > 0) { 05741 /* if E911, take off hook */ 05742 if (p->sig == SIG_E911) 05743 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 05744 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000); 05745 } 05746 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 05747 break; 05748 case SIG_FEATB: 05749 case SIG_SF_FEATB: 05750 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 05751 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 05752 break; 05753 case SIG_EMWINK: 05754 /* if we received a '*', we are actually receiving Feature Group D 05755 dial syntax, so use that mode; otherwise, fall through to normal 05756 mode 05757 */ 05758 if (res == '*') { 05759 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 05760 if (res > 0) 05761 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 05762 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 05763 break; 05764 } 05765 default: 05766 /* If we got the first digit, get the rest */ 05767 len = 1; 05768 dtmfbuf[len] = '\0'; 05769 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 05770 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 05771 timeout = matchdigittimeout; 05772 } else { 05773 timeout = gendigittimeout; 05774 } 05775 res = ast_waitfordigit(chan, timeout); 05776 if (res < 0) { 05777 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 05778 ast_hangup(chan); 05779 goto quit; 05780 } else if (res) { 05781 dtmfbuf[len++] = res; 05782 dtmfbuf[len] = '\0'; 05783 } else { 05784 break; 05785 } 05786 } 05787 break; 05788 } 05789 } 05790 if (res == -1) { 05791 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno)); 05792 ast_hangup(chan); 05793 goto quit; 05794 } else if (res < 0) { 05795 ast_log(LOG_DEBUG, "Got hung up before digits finished\n"); 05796 ast_hangup(chan); 05797 goto quit; 05798 } 05799 05800 if (p->sig == SIG_FGC_CAMA) { 05801 char anibuf[100]; 05802 05803 if (ast_safe_sleep(chan,1000) == -1) { 05804 ast_hangup(chan); 05805 goto quit; 05806 } 05807 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 05808 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 05809 res = my_getsigstr(chan, anibuf, "#", 10000); 05810 if ((res > 0) && (strlen(anibuf) > 2)) { 05811 if (anibuf[strlen(anibuf) - 1] == '#') 05812 anibuf[strlen(anibuf) - 1] = 0; 05813 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2); 05814 } 05815 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 05816 } 05817 05818 ast_copy_string(exten, dtmfbuf, sizeof(exten)); 05819 if (ast_strlen_zero(exten)) 05820 ast_copy_string(exten, "s", sizeof(exten)); 05821 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) { 05822 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */ 05823 if (exten[0] == '*') { 05824 char *stringp=NULL; 05825 ast_copy_string(exten2, exten, sizeof(exten2)); 05826 /* Parse out extension and callerid */ 05827 stringp=exten2 +1; 05828 s1 = strsep(&stringp, "*"); 05829 s2 = strsep(&stringp, "*"); 05830 if (s2) { 05831 if (!ast_strlen_zero(p->cid_num)) 05832 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 05833 else 05834 ast_set_callerid(chan, s1, NULL, s1); 05835 ast_copy_string(exten, s2, sizeof(exten)); 05836 } else 05837 ast_copy_string(exten, s1, sizeof(exten)); 05838 } else if (p->sig == SIG_FEATD) 05839 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 05840 } 05841 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 05842 if (exten[0] == '*') { 05843 char *stringp=NULL; 05844 ast_copy_string(exten2, exten, sizeof(exten2)); 05845 /* Parse out extension and callerid */ 05846 stringp=exten2 +1; 05847 s1 = strsep(&stringp, "#"); 05848 s2 = strsep(&stringp, "#"); 05849 if (s2) { 05850 if (!ast_strlen_zero(p->cid_num)) 05851 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 05852 else 05853 if (*(s1 + 2)) 05854 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2); 05855 ast_copy_string(exten, s2 + 1, sizeof(exten)); 05856 } else 05857 ast_copy_string(exten, s1 + 2, sizeof(exten)); 05858 } else 05859 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 05860 } 05861 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) { 05862 if (exten[0] == '*') { 05863 char *stringp=NULL; 05864 ast_copy_string(exten2, exten, sizeof(exten2)); 05865 /* Parse out extension and callerid */ 05866 stringp=exten2 +1; 05867 s1 = strsep(&stringp, "#"); 05868 s2 = strsep(&stringp, "#"); 05869 if (s2 && (*(s2 + 1) == '0')) { 05870 if (*(s2 + 2)) 05871 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2); 05872 } 05873 if (s1) ast_copy_string(exten, s1, sizeof(exten)); 05874 else ast_copy_string(exten, "911", sizeof(exten)); 05875 } else 05876 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel); 05877 } 05878 if (p->sig == SIG_FEATB) { 05879 if (exten[0] == '*') { 05880 char *stringp=NULL; 05881 ast_copy_string(exten2, exten, sizeof(exten2)); 05882 /* Parse out extension and callerid */ 05883 stringp=exten2 +1; 05884 s1 = strsep(&stringp, "#"); 05885 ast_copy_string(exten, exten2 + 1, sizeof(exten)); 05886 } else 05887 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel); 05888 } 05889 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 05890 dahdi_wink(p, index); 05891 /* some switches require a minimum guard time between 05892 the last FGD wink and something that answers 05893 immediately. This ensures it */ 05894 if (ast_safe_sleep(chan,100)) goto quit; 05895 } 05896 dahdi_enable_ec(p); 05897 if (NEED_MFDETECT(p)) { 05898 if (p->dsp) { 05899 if (!p->hardwaredtmf) 05900 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 05901 else { 05902 ast_dsp_free(p->dsp); 05903 p->dsp = NULL; 05904 } 05905 } 05906 } 05907 05908 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) { 05909 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 05910 if (p->dsp) ast_dsp_digitreset(p->dsp); 05911 res = ast_pbx_run(chan); 05912 if (res) { 05913 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 05914 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 05915 } 05916 goto quit; 05917 } else { 05918 if (option_verbose > 2) 05919 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context); 05920 sleep(2); 05921 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO); 05922 if (res < 0) 05923 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel); 05924 else 05925 sleep(1); 05926 res = ast_streamfile(chan, "ss-noservice", chan->language); 05927 if (res >= 0) 05928 ast_waitstream(chan, ""); 05929 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 05930 ast_hangup(chan); 05931 goto quit; 05932 } 05933 break; 05934 case SIG_FXOLS: 05935 case SIG_FXOGS: 05936 case SIG_FXOKS: 05937 /* Read the first digit */ 05938 timeout = firstdigittimeout; 05939 /* If starting a threeway call, never timeout on the first digit so someone 05940 can use flash-hook as a "hold" feature */ 05941 if (p->subs[SUB_THREEWAY].owner) 05942 timeout = 999999; 05943 while (len < AST_MAX_EXTENSION-1) { 05944 /* Read digit unless it's supposed to be immediate, in which case the 05945 only answer is 's' */ 05946 if (p->immediate) 05947 res = 's'; 05948 else 05949 res = ast_waitfordigit(chan, timeout); 05950 timeout = 0; 05951 if (res < 0) { 05952 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 05953 res = tone_zone_play_tone(p->subs[index].dfd, -1); 05954 ast_hangup(chan); 05955 goto quit; 05956 } else if (res) { 05957 exten[len++]=res; 05958 exten[len] = '\0'; 05959 } 05960 if (!ast_ignore_pattern(chan->context, exten)) 05961 tone_zone_play_tone(p->subs[index].dfd, -1); 05962 else 05963 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 05964 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) { 05965 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 05966 if (getforward) { 05967 /* Record this as the forwarding extension */ 05968 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 05969 if (option_verbose > 2) 05970 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel); 05971 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 05972 if (res) 05973 break; 05974 usleep(500000); 05975 res = tone_zone_play_tone(p->subs[index].dfd, -1); 05976 sleep(1); 05977 memset(exten, 0, sizeof(exten)); 05978 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 05979 len = 0; 05980 getforward = 0; 05981 } else { 05982 res = tone_zone_play_tone(p->subs[index].dfd, -1); 05983 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 05984 if (!ast_strlen_zero(p->cid_num)) { 05985 if (!p->hidecallerid) 05986 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 05987 else 05988 ast_set_callerid(chan, NULL, NULL, p->cid_num); 05989 } 05990 if (!ast_strlen_zero(p->cid_name)) { 05991 if (!p->hidecallerid) 05992 ast_set_callerid(chan, NULL, p->cid_name, NULL); 05993 } 05994 ast_setstate(chan, AST_STATE_RING); 05995 dahdi_enable_ec(p); 05996 res = ast_pbx_run(chan); 05997 if (res) { 05998 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 05999 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06000 } 06001 goto quit; 06002 } 06003 } else { 06004 /* It's a match, but they just typed a digit, and there is an ambiguous match, 06005 so just set the timeout to matchdigittimeout and wait some more */ 06006 timeout = matchdigittimeout; 06007 } 06008 } else if (res == 0) { 06009 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n"); 06010 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06011 dahdi_wait_event(p->subs[index].dfd); 06012 ast_hangup(chan); 06013 goto quit; 06014 } else if (p->callwaiting && !strcmp(exten, "*70")) { 06015 if (option_verbose > 2) 06016 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name); 06017 /* Disable call waiting if enabled */ 06018 p->callwaiting = 0; 06019 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06020 if (res) { 06021 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 06022 chan->name, strerror(errno)); 06023 } 06024 len = 0; 06025 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len); 06026 memset(exten, 0, sizeof(exten)); 06027 timeout = firstdigittimeout; 06028 06029 } else if (!strcmp(exten,ast_pickup_ext())) { 06030 /* Scan all channels and see if there are any 06031 * ringing channels that have call groups 06032 * that equal this channels pickup group 06033 */ 06034 if (index == SUB_REAL) { 06035 /* Switch us from Third call to Call Wait */ 06036 if (p->subs[SUB_THREEWAY].owner) { 06037 /* If you make a threeway call and the *8# a call, it should actually 06038 look like a callwait */ 06039 alloc_sub(p, SUB_CALLWAIT); 06040 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 06041 unalloc_sub(p, SUB_THREEWAY); 06042 } 06043 dahdi_enable_ec(p); 06044 if (ast_pickup_call(chan)) { 06045 ast_log(LOG_DEBUG, "No call pickup possible...\n"); 06046 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06047 dahdi_wait_event(p->subs[index].dfd); 06048 } 06049 ast_hangup(chan); 06050 goto quit; 06051 } else { 06052 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n"); 06053 ast_hangup(chan); 06054 goto quit; 06055 } 06056 06057 } else if (!p->hidecallerid && !strcmp(exten, "*67")) { 06058 if (option_verbose > 2) 06059 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name); 06060 /* Disable Caller*ID if enabled */ 06061 p->hidecallerid = 1; 06062 if (chan->cid.cid_num) 06063 free(chan->cid.cid_num); 06064 chan->cid.cid_num = NULL; 06065 if (chan->cid.cid_name) 06066 free(chan->cid.cid_name); 06067 chan->cid.cid_name = NULL; 06068 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06069 if (res) { 06070 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 06071 chan->name, strerror(errno)); 06072 } 06073 len = 0; 06074 memset(exten, 0, sizeof(exten)); 06075 timeout = firstdigittimeout; 06076 } else if (p->callreturn && !strcmp(exten, "*69")) { 06077 res = 0; 06078 if (!ast_strlen_zero(p->lastcid_num)) { 06079 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language); 06080 } 06081 if (!res) 06082 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06083 break; 06084 } else if (!strcmp(exten, "*78")) { 06085 /* Do not disturb */ 06086 if (option_verbose > 2) 06087 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel); 06088 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 06089 "Channel: %s/%d\r\n" 06090 "Status: enabled\r\n", dahdi_chan_name, p->channel); 06091 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06092 p->dnd = 1; 06093 getforward = 0; 06094 memset(exten, 0, sizeof(exten)); 06095 len = 0; 06096 } else if (!strcmp(exten, "*79")) { 06097 /* Do not disturb */ 06098 if (option_verbose > 2) 06099 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel); 06100 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 06101 "Channel: %s/%d\r\n" 06102 "Status: disabled\r\n", dahdi_chan_name, p->channel); 06103 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06104 p->dnd = 0; 06105 getforward = 0; 06106 memset(exten, 0, sizeof(exten)); 06107 len = 0; 06108 } else if (p->cancallforward && !strcmp(exten, "*72")) { 06109 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06110 getforward = 1; 06111 memset(exten, 0, sizeof(exten)); 06112 len = 0; 06113 } else if (p->cancallforward && !strcmp(exten, "*73")) { 06114 if (option_verbose > 2) 06115 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel); 06116 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06117 memset(p->call_forward, 0, sizeof(p->call_forward)); 06118 getforward = 0; 06119 memset(exten, 0, sizeof(exten)); 06120 len = 0; 06121 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 06122 p->subs[SUB_THREEWAY].owner && 06123 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 06124 /* This is a three way call, the main call being a real channel, 06125 and we're parking the first call. */ 06126 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL); 06127 if (option_verbose > 2) 06128 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name); 06129 break; 06130 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) { 06131 if (option_verbose > 2) 06132 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num); 06133 res = ast_db_put("blacklist", p->lastcid_num, "1"); 06134 if (!res) { 06135 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06136 memset(exten, 0, sizeof(exten)); 06137 len = 0; 06138 } 06139 } else if (p->hidecallerid && !strcmp(exten, "*82")) { 06140 if (option_verbose > 2) 06141 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name); 06142 /* Enable Caller*ID if enabled */ 06143 p->hidecallerid = 0; 06144 if (chan->cid.cid_num) 06145 free(chan->cid.cid_num); 06146 chan->cid.cid_num = NULL; 06147 if (chan->cid.cid_name) 06148 free(chan->cid.cid_name); 06149 chan->cid.cid_name = NULL; 06150 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 06151 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06152 if (res) { 06153 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 06154 chan->name, strerror(errno)); 06155 } 06156 len = 0; 06157 memset(exten, 0, sizeof(exten)); 06158 timeout = firstdigittimeout; 06159 } else if (!strcmp(exten, "*0")) { 06160 struct ast_channel *nbridge = 06161 p->subs[SUB_THREEWAY].owner; 06162 struct dahdi_pvt *pbridge = NULL; 06163 /* set up the private struct of the bridged one, if any */ 06164 if (nbridge && ast_bridged_channel(nbridge)) 06165 pbridge = ast_bridged_channel(nbridge)->tech_pvt; 06166 if (nbridge && pbridge && 06167 (nbridge->tech == chan_tech) && 06168 (ast_bridged_channel(nbridge)->tech == chan_tech) && 06169 ISTRUNK(pbridge)) { 06170 int func = DAHDI_FLASH; 06171 /* Clear out the dial buffer */ 06172 p->dop.dialstr[0] = '\0'; 06173 /* flash hookswitch */ 06174 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 06175 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 06176 nbridge->name, strerror(errno)); 06177 } 06178 swap_subs(p, SUB_REAL, SUB_THREEWAY); 06179 unalloc_sub(p, SUB_THREEWAY); 06180 p->owner = p->subs[SUB_REAL].owner; 06181 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 06182 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 06183 ast_hangup(chan); 06184 goto quit; 06185 } else { 06186 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06187 dahdi_wait_event(p->subs[index].dfd); 06188 tone_zone_play_tone(p->subs[index].dfd, -1); 06189 swap_subs(p, SUB_REAL, SUB_THREEWAY); 06190 unalloc_sub(p, SUB_THREEWAY); 06191 p->owner = p->subs[SUB_REAL].owner; 06192 ast_hangup(chan); 06193 goto quit; 06194 } 06195 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) && 06196 ((exten[0] != '*') || (strlen(exten) > 2))) { 06197 if (option_debug) 06198 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); 06199 break; 06200 } 06201 if (!timeout) 06202 timeout = gendigittimeout; 06203 if (len && !ast_ignore_pattern(chan->context, exten)) 06204 tone_zone_play_tone(p->subs[index].dfd, -1); 06205 } 06206 break; 06207 case SIG_FXSLS: 06208 case SIG_FXSGS: 06209 case SIG_FXSKS: 06210 #ifdef HAVE_PRI 06211 if (p->pri) { 06212 /* This is a GR-303 trunk actually. Wait for the first ring... */ 06213 struct ast_frame *f; 06214 int res; 06215 time_t start; 06216 06217 time(&start); 06218 ast_setstate(chan, AST_STATE_RING); 06219 while (time(NULL) < start + 3) { 06220 res = ast_waitfor(chan, 1000); 06221 if (res) { 06222 f = ast_read(chan); 06223 if (!f) { 06224 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n"); 06225 ast_hangup(chan); 06226 goto quit; 06227 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) { 06228 res = 1; 06229 } else 06230 res = 0; 06231 ast_frfree(f); 06232 if (res) { 06233 ast_log(LOG_DEBUG, "Got ring!\n"); 06234 res = 0; 06235 break; 06236 } 06237 } 06238 } 06239 } 06240 #endif 06241 /* check for SMDI messages */ 06242 if (p->use_smdi && p->smdi_iface) { 06243 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); 06244 06245 if (smdi_msg != NULL) { 06246 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten)); 06247 06248 if (smdi_msg->type == 'B') 06249 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b"); 06250 else if (smdi_msg->type == 'N') 06251 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u"); 06252 06253 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name); 06254 } else { 06255 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n"); 06256 } 06257 } 06258 06259 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) { 06260 number = smdi_msg->calling_st; 06261 06262 /* If we want caller id, we're in a prering state due to a polarity reversal 06263 * and we're set to use a polarity reversal to trigger the start of caller id, 06264 * grab the caller id and wait for ringing to start... */ 06265 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) { 06266 /* If set to use DTMF CID signalling, listen for DTMF */ 06267 if (p->cid_signalling == CID_SIG_DTMF) { 06268 int i = 0; 06269 cs = NULL; 06270 ast_log(LOG_DEBUG, "Receiving DTMF cid on " 06271 "channel %s\n", chan->name); 06272 dahdi_setlinear(p->subs[index].dfd, 0); 06273 res = 2000; 06274 for (;;) { 06275 struct ast_frame *f; 06276 res = ast_waitfor(chan, res); 06277 if (res <= 0) { 06278 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 06279 "Exiting simple switch\n"); 06280 ast_hangup(chan); 06281 goto quit; 06282 } 06283 f = ast_read(chan); 06284 if (!f) 06285 break; 06286 if (f->frametype == AST_FRAME_DTMF) { 06287 dtmfbuf[i++] = f->subclass; 06288 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass); 06289 res = 2000; 06290 } 06291 ast_frfree(f); 06292 if (chan->_state == AST_STATE_RING || 06293 chan->_state == AST_STATE_RINGING) 06294 break; /* Got ring */ 06295 } 06296 dtmfbuf[i] = '\0'; 06297 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06298 /* Got cid and ring. */ 06299 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf); 06300 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 06301 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 06302 dtmfcid, flags); 06303 /* If first byte is NULL, we have no cid */ 06304 if (!ast_strlen_zero(dtmfcid)) 06305 number = dtmfcid; 06306 else 06307 number = NULL; 06308 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 06309 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { 06310 cs = callerid_new(p->cid_signalling); 06311 if (cs) { 06312 samples = 0; 06313 #if 1 06314 bump_gains(p); 06315 #endif 06316 /* Take out of linear mode for Caller*ID processing */ 06317 dahdi_setlinear(p->subs[index].dfd, 0); 06318 06319 /* First we wait and listen for the Caller*ID */ 06320 for (;;) { 06321 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 06322 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 06323 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 06324 callerid_free(cs); 06325 ast_hangup(chan); 06326 goto quit; 06327 } 06328 if (i & DAHDI_IOMUX_SIGEVENT) { 06329 res = dahdi_get_event(p->subs[index].dfd); 06330 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 06331 06332 if (p->cid_signalling == CID_SIG_V23_JP) { 06333 #ifdef DAHDI_EVENT_RINGBEGIN 06334 if (res == DAHDI_EVENT_RINGBEGIN) { 06335 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06336 usleep(1); 06337 } 06338 #endif 06339 } else { 06340 res = 0; 06341 break; 06342 } 06343 } else if (i & DAHDI_IOMUX_READ) { 06344 res = read(p->subs[index].dfd, buf, sizeof(buf)); 06345 if (res < 0) { 06346 if (errno != ELAST) { 06347 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 06348 callerid_free(cs); 06349 ast_hangup(chan); 06350 goto quit; 06351 } 06352 break; 06353 } 06354 samples += res; 06355 06356 if (p->cid_signalling == CID_SIG_V23_JP) { 06357 res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); 06358 } else { 06359 res = callerid_feed(cs, buf, res, AST_LAW(p)); 06360 } 06361 06362 if (res < 0) { 06363 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name); 06364 break; 06365 } else if (res) 06366 break; 06367 else if (samples > (8000 * 10)) 06368 break; 06369 } 06370 } 06371 if (res == 1) { 06372 callerid_get(cs, &name, &number, &flags); 06373 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 06374 } 06375 06376 if (p->cid_signalling == CID_SIG_V23_JP) { 06377 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 06378 usleep(1); 06379 res = 4000; 06380 } else { 06381 06382 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 06383 res = 2000; 06384 } 06385 06386 for (;;) { 06387 struct ast_frame *f; 06388 res = ast_waitfor(chan, res); 06389 if (res <= 0) { 06390 ast_log(LOG_WARNING, "CID timed out waiting for ring. " 06391 "Exiting simple switch\n"); 06392 ast_hangup(chan); 06393 goto quit; 06394 } 06395 if (!(f = ast_read(chan))) { 06396 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); 06397 ast_hangup(chan); 06398 goto quit; 06399 } 06400 ast_frfree(f); 06401 if (chan->_state == AST_STATE_RING || 06402 chan->_state == AST_STATE_RINGING) 06403 break; /* Got ring */ 06404 } 06405 06406 /* We must have a ring by now, so, if configured, lets try to listen for 06407 * distinctive ringing */ 06408 if (p->usedistinctiveringdetection == 1) { 06409 len = 0; 06410 distMatches = 0; 06411 /* Clear the current ring data array so we dont have old data in it. */ 06412 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++) 06413 curRingData[receivedRingT] = 0; 06414 receivedRingT = 0; 06415 counter = 0; 06416 counter1 = 0; 06417 /* Check to see if context is what it should be, if not set to be. */ 06418 if (strcmp(p->context,p->defcontext) != 0) { 06419 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 06420 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 06421 } 06422 06423 for (;;) { 06424 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 06425 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 06426 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 06427 callerid_free(cs); 06428 ast_hangup(chan); 06429 goto quit; 06430 } 06431 if (i & DAHDI_IOMUX_SIGEVENT) { 06432 res = dahdi_get_event(p->subs[index].dfd); 06433 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 06434 res = 0; 06435 /* Let us detect distinctive ring */ 06436 06437 curRingData[receivedRingT] = p->ringt; 06438 06439 if (p->ringt < p->ringt_base/2) 06440 break; 06441 /* Increment the ringT counter so we can match it against 06442 values in chan_dahdi.conf for distinctive ring */ 06443 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 06444 break; 06445 } else if (i & DAHDI_IOMUX_READ) { 06446 res = read(p->subs[index].dfd, buf, sizeof(buf)); 06447 if (res < 0) { 06448 if (errno != ELAST) { 06449 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 06450 callerid_free(cs); 06451 ast_hangup(chan); 06452 goto quit; 06453 } 06454 break; 06455 } 06456 if (p->ringt) 06457 p->ringt--; 06458 if (p->ringt == 1) { 06459 res = -1; 06460 break; 06461 } 06462 } 06463 } 06464 if (option_verbose > 2) 06465 /* this only shows up if you have n of the dring patterns filled in */ 06466 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 06467 06468 for (counter = 0; counter < 3; counter++) { 06469 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 06470 channel */ 06471 distMatches = 0; 06472 for (counter1 = 0; counter1 < 3; counter1++) { 06473 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >= 06474 (p->drings.ringnum[counter].ring[counter1]-10)) { 06475 distMatches++; 06476 } 06477 } 06478 if (distMatches == 3) { 06479 /* The ring matches, set the context to whatever is for distinctive ring.. */ 06480 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 06481 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 06482 if (option_verbose > 2) 06483 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context); 06484 break; 06485 } 06486 } 06487 } 06488 /* Restore linear mode (if appropriate) for Caller*ID processing */ 06489 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06490 #if 1 06491 restore_gains(p); 06492 #endif 06493 } else 06494 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 06495 } else { 06496 ast_log(LOG_WARNING, "Channel %s in prering " 06497 "state, but I have nothing to do. " 06498 "Terminating simple switch, should be " 06499 "restarted by the actual ring.\n", 06500 chan->name); 06501 ast_hangup(chan); 06502 goto quit; 06503 } 06504 } else if (p->use_callerid && p->cid_start == CID_START_RING) { 06505 /* FSK Bell202 callerID */ 06506 cs = callerid_new(p->cid_signalling); 06507 if (cs) { 06508 #if 1 06509 bump_gains(p); 06510 #endif 06511 samples = 0; 06512 len = 0; 06513 distMatches = 0; 06514 /* Clear the current ring data array so we dont have old data in it. */ 06515 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++) 06516 curRingData[receivedRingT] = 0; 06517 receivedRingT = 0; 06518 counter = 0; 06519 counter1 = 0; 06520 /* Check to see if context is what it should be, if not set to be. */ 06521 if (strcmp(p->context,p->defcontext) != 0) { 06522 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 06523 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 06524 } 06525 06526 /* Take out of linear mode for Caller*ID processing */ 06527 dahdi_setlinear(p->subs[index].dfd, 0); 06528 for (;;) { 06529 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 06530 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 06531 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 06532 callerid_free(cs); 06533 ast_hangup(chan); 06534 goto quit; 06535 } 06536 if (i & DAHDI_IOMUX_SIGEVENT) { 06537 res = dahdi_get_event(p->subs[index].dfd); 06538 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 06539 /* If we get a PR event, they hung up while processing calerid */ 06540 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { 06541 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); 06542 p->polarity = POLARITY_IDLE; 06543 callerid_free(cs); 06544 ast_hangup(chan); 06545 goto quit; 06546 } 06547 res = 0; 06548 /* Let us detect callerid when the telco uses distinctive ring */ 06549 06550 curRingData[receivedRingT] = p->ringt; 06551 06552 if (p->ringt < p->ringt_base/2) 06553 break; 06554 /* Increment the ringT counter so we can match it against 06555 values in chan_dahdi.conf for distinctive ring */ 06556 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 06557 break; 06558 } else if (i & DAHDI_IOMUX_READ) { 06559 res = read(p->subs[index].dfd, buf, sizeof(buf)); 06560 if (res < 0) { 06561 if (errno != ELAST) { 06562 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 06563 callerid_free(cs); 06564 ast_hangup(chan); 06565 goto quit; 06566 } 06567 break; 06568 } 06569 if (p->ringt) 06570 p->ringt--; 06571 if (p->ringt == 1) { 06572 res = -1; 06573 break; 06574 } 06575 samples += res; 06576 res = callerid_feed(cs, buf, res, AST_LAW(p)); 06577 if (res < 0) { 06578 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno)); 06579 break; 06580 } else if (res) 06581 break; 06582 else if (samples > (8000 * 10)) 06583 break; 06584 } 06585 } 06586 if (res == 1) { 06587 callerid_get(cs, &name, &number, &flags); 06588 if (option_debug) 06589 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 06590 } 06591 if (distinctiveringaftercid == 1) { 06592 /* Clear the current ring data array so we dont have old data in it. */ 06593 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) { 06594 curRingData[receivedRingT] = 0; 06595 } 06596 receivedRingT = 0; 06597 if (option_verbose > 2) 06598 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n"); 06599 for (;;) { 06600 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 06601 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 06602 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 06603 callerid_free(cs); 06604 ast_hangup(chan); 06605 goto quit; 06606 } 06607 if (i & DAHDI_IOMUX_SIGEVENT) { 06608 res = dahdi_get_event(p->subs[index].dfd); 06609 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 06610 res = 0; 06611 /* Let us detect callerid when the telco uses distinctive ring */ 06612 06613 curRingData[receivedRingT] = p->ringt; 06614 06615 if (p->ringt < p->ringt_base/2) 06616 break; 06617 /* Increment the ringT counter so we can match it against 06618 values in chan_dahdi.conf for distinctive ring */ 06619 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 06620 break; 06621 } else if (i & DAHDI_IOMUX_READ) { 06622 res = read(p->subs[index].dfd, buf, sizeof(buf)); 06623 if (res < 0) { 06624 if (errno != ELAST) { 06625 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 06626 callerid_free(cs); 06627 ast_hangup(chan); 06628 goto quit; 06629 } 06630 break; 06631 } 06632 if (p->ringt) 06633 p->ringt--; 06634 if (p->ringt == 1) { 06635 res = -1; 06636 break; 06637 } 06638 } 06639 } 06640 } 06641 if (p->usedistinctiveringdetection == 1) { 06642 if (option_verbose > 2) 06643 /* this only shows up if you have n of the dring patterns filled in */ 06644 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 06645 06646 for (counter = 0; counter < 3; counter++) { 06647 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 06648 channel */ 06649 if (option_verbose > 2) 06650 /* this only shows up if you have n of the dring patterns filled in */ 06651 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n", 06652 p->drings.ringnum[counter].ring[0], 06653 p->drings.ringnum[counter].ring[1], 06654 p->drings.ringnum[counter].ring[2]); 06655 distMatches = 0; 06656 for (counter1 = 0; counter1 < 3; counter1++) { 06657 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >= 06658 (p->drings.ringnum[counter].ring[counter1]-10)) { 06659 distMatches++; 06660 } 06661 } 06662 if (distMatches == 3) { 06663 /* The ring matches, set the context to whatever is for distinctive ring.. */ 06664 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 06665 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 06666 if (option_verbose > 2) 06667 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context); 06668 break; 06669 } 06670 } 06671 } 06672 /* Restore linear mode (if appropriate) for Caller*ID processing */ 06673 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06674 #if 1 06675 restore_gains(p); 06676 #endif 06677 if (res < 0) { 06678 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); 06679 } 06680 } else 06681 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 06682 } 06683 else 06684 cs = NULL; 06685 06686 if (number) 06687 ast_shrink_phone_number(number); 06688 ast_set_callerid(chan, number, name, number); 06689 06690 if (smdi_msg) 06691 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy); 06692 06693 if (cs) 06694 callerid_free(cs); 06695 06696 ast_setstate(chan, AST_STATE_RING); 06697 chan->rings = 1; 06698 p->ringt = p->ringt_base; 06699 res = ast_pbx_run(chan); 06700 if (res) { 06701 ast_hangup(chan); 06702 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 06703 } 06704 goto quit; 06705 default: 06706 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel); 06707 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06708 if (res < 0) 06709 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 06710 } 06711 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06712 if (res < 0) 06713 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 06714 ast_hangup(chan); 06715 quit: 06716 ast_mutex_lock(&ss_thread_lock); 06717 ss_thread_count--; 06718 ast_cond_signal(&ss_thread_complete); 06719 ast_mutex_unlock(&ss_thread_lock); 06720 return NULL; 06721 }
static int start_pri | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 9641 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().
09642 { 09643 int res, x; 09644 struct dahdi_params p; 09645 struct dahdi_bufferinfo bi; 09646 struct dahdi_spaninfo si; 09647 int i; 09648 09649 for (i = 0; i < NUM_DCHANS; i++) { 09650 if (!pri->dchannels[i]) 09651 break; 09652 pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600); 09653 x = pri->dchannels[i]; 09654 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) { 09655 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno)); 09656 return -1; 09657 } 09658 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p); 09659 if (res) { 09660 dahdi_close_pri_fd(pri, i); 09661 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno)); 09662 return -1; 09663 } 09664 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) { 09665 dahdi_close_pri_fd(pri, i); 09666 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/dahdi/system.conf\n", x); 09667 return -1; 09668 } 09669 memset(&si, 0, sizeof(si)); 09670 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si); 09671 if (res) { 09672 dahdi_close_pri_fd(pri, i); 09673 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno)); 09674 } 09675 if (!si.alarms) 09676 pri->dchanavail[i] |= DCHAN_NOTINALARM; 09677 else 09678 pri->dchanavail[i] &= ~DCHAN_NOTINALARM; 09679 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 09680 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 09681 bi.numbufs = 32; 09682 bi.bufsize = 1024; 09683 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) { 09684 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno)); 09685 dahdi_close_pri_fd(pri, i); 09686 return -1; 09687 } 09688 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype); 09689 /* Force overlap dial if we're doing GR-303! */ 09690 if (pri->switchtype == PRI_SWITCH_GR303_TMC) 09691 pri->overlapdial = 1; 09692 pri_set_overlapdial(pri->dchans[i],pri->overlapdial); 09693 #ifdef HAVE_PRI_INBANDDISCONNECT 09694 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect); 09695 #endif 09696 /* Enslave to master if appropriate */ 09697 if (i) 09698 pri_enslave(pri->dchans[0], pri->dchans[i]); 09699 if (!pri->dchans[i]) { 09700 dahdi_close_pri_fd(pri, i); 09701 ast_log(LOG_ERROR, "Unable to create PRI structure\n"); 09702 return -1; 09703 } 09704 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG); 09705 pri_set_nsf(pri->dchans[i], pri->nsf); 09706 #ifdef PRI_GETSET_TIMERS 09707 for (x = 0; x < PRI_MAX_TIMERS; x++) { 09708 if (pritimers[x] != 0) 09709 pri_set_timer(pri->dchans[i], x, pritimers[x]); 09710 } 09711 #endif 09712 } 09713 /* Assume primary is the one we use */ 09714 pri->pri = pri->dchans[0]; 09715 pri->resetpos = -1; 09716 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) { 09717 for (i = 0; i < NUM_DCHANS; i++) { 09718 if (!pri->dchannels[i]) 09719 break; 09720 dahdi_close_pri_fd(pri, i); 09721 } 09722 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno)); 09723 return -1; 09724 } 09725 return 0; 09726 }
static void swap_subs | ( | struct dahdi_pvt * | p, | |
int | a, | |||
int | b | |||
) | [static] |
Definition at line 878 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().
00879 { 00880 int tchan; 00881 int tinthreeway; 00882 struct ast_channel *towner; 00883 00884 ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b); 00885 00886 tchan = p->subs[a].chan; 00887 towner = p->subs[a].owner; 00888 tinthreeway = p->subs[a].inthreeway; 00889 00890 p->subs[a].chan = p->subs[b].chan; 00891 p->subs[a].owner = p->subs[b].owner; 00892 p->subs[a].inthreeway = p->subs[b].inthreeway; 00893 00894 p->subs[b].chan = tchan; 00895 p->subs[b].owner = towner; 00896 p->subs[b].inthreeway = tinthreeway; 00897 00898 if (p->subs[a].owner) 00899 p->subs[a].owner->fds[0] = p->subs[a].dfd; 00900 if (p->subs[b].owner) 00901 p->subs[b].owner->fds[0] = p->subs[b].dfd; 00902 wakeup_sub(p, a, NULL); 00903 wakeup_sub(p, b, NULL); 00904 }
static int unalloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 1017 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().
01018 { 01019 if (!x) { 01020 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel); 01021 return -1; 01022 } 01023 ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel); 01024 dahdi_close_sub(p, x); 01025 p->subs[x].linear = 0; 01026 p->subs[x].chan = 0; 01027 p->subs[x].owner = NULL; 01028 p->subs[x].inthreeway = 0; 01029 p->polarity = POLARITY_IDLE; 01030 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf)); 01031 return 0; 01032 }
static int unload_module | ( | void | ) | [static] |
Definition at line 10891 of file chan_dahdi.c.
References __unload_module(), ast_mutex_destroy(), lock, NUM_SPANS, and pris.
10892 { 10893 #ifdef HAVE_PRI 10894 int y; 10895 for (y = 0; y < NUM_SPANS; y++) 10896 ast_mutex_destroy(&pris[y].lock); 10897 #endif 10898 return __unload_module(); 10899 }
static int update_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1400 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().
01401 { 01402 int needconf = 0; 01403 int x; 01404 int useslavenative; 01405 struct dahdi_pvt *slave = NULL; 01406 01407 useslavenative = isslavenative(p, &slave); 01408 /* Start with the obvious, general stuff */ 01409 for (x = 0; x < 3; x++) { 01410 /* Look for three way calls */ 01411 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) { 01412 conf_add(p, &p->subs[x], x, 0); 01413 needconf++; 01414 } else { 01415 conf_del(p, &p->subs[x], x); 01416 } 01417 } 01418 /* If we have a slave, add him to our conference now. or DAX 01419 if this is slave native */ 01420 for (x = 0; x < MAX_SLAVES; x++) { 01421 if (p->slaves[x]) { 01422 if (useslavenative) 01423 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 01424 else { 01425 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 01426 needconf++; 01427 } 01428 } 01429 } 01430 /* If we're supposed to be in there, do so now */ 01431 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 01432 if (useslavenative) 01433 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 01434 else { 01435 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 01436 needconf++; 01437 } 01438 } 01439 /* If we have a master, add ourselves to his conference */ 01440 if (p->master) { 01441 if (isslavenative(p->master, NULL)) { 01442 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 01443 } else { 01444 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 01445 } 01446 } 01447 if (!needconf) { 01448 /* Nobody is left (or should be left) in our conference. 01449 Kill it. */ 01450 p->confno = -1; 01451 } 01452 if (option_debug) 01453 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf); 01454 return 0; 01455 }
Definition at line 820 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().
00824 { 00825 #ifdef HAVE_PRI 00826 if (pri) 00827 ast_mutex_unlock(&pri->lock); 00828 #endif 00829 for (;;) { 00830 if (p->subs[a].owner) { 00831 if (ast_mutex_trylock(&p->subs[a].owner->lock)) { 00832 DEADLOCK_AVOIDANCE(&p->lock); 00833 } else { 00834 ast_queue_frame(p->subs[a].owner, &ast_null_frame); 00835 ast_mutex_unlock(&p->subs[a].owner->lock); 00836 break; 00837 } 00838 } else 00839 break; 00840 } 00841 #ifdef HAVE_PRI 00842 if (pri) 00843 ast_mutex_lock(&pri->lock); 00844 #endif 00845 }
static int zap_action_dialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10737 of file chan_dahdi.c.
References __action_dialoffhook(), and s.
10738 { 10739 return __action_dialoffhook(s, m, 1); 10740 }
static int zap_action_dndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10637 of file chan_dahdi.c.
References __action_dnd(), and s.
10638 { 10639 return __action_dnd(s, m, 1, 0); 10640 }
static int zap_action_dndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10627 of file chan_dahdi.c.
References __action_dnd(), and s.
10628 { 10629 return __action_dnd(s, m, 1, 1); 10630 }
static int zap_action_restart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10816 of file chan_dahdi.c.
References __action_restart(), and s.
10817 { 10818 return __action_restart(s, m, 1); 10819 }
static int zap_action_showchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10792 of file chan_dahdi.c.
References __action_showchannels(), and s.
10793 { 10794 return __action_showchannels(s, m, 1); 10795 }
static int zap_action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10666 of file chan_dahdi.c.
References __action_transfer(), and s.
10667 { 10668 return __action_transfer(s, m, 1); 10669 }
static int zap_action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10694 of file chan_dahdi.c.
References __action_transferhangup(), and s.
10695 { 10696 return __action_transferhangup(s, m, 1); 10697 }
static int zap_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 2420 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and send_keypad_facility_exec().
Referenced by load_module().
02421 { 02422 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); 02423 return send_keypad_facility_exec(chan, data); 02424 }
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 12033 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 12033 of file chan_dahdi.c.
struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static] |
Definition at line 778 of file chan_dahdi.c.
struct ast_channel_tech* chan_tech [static] |
Definition at line 746 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 789 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 10533 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 10538 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 10518 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 10528 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 10523 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 10543 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 10511 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static] |
Definition at line 2362 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 2368 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static] |
Definition at line 2365 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 10404 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 10503 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 10507 of file chan_dahdi.c.
int distinctiveringaftercid = 0 [static] |
Definition at line 204 of file chan_dahdi.c.
struct dahdi_distRings drings [static] |
char* events[] [static] |
int firstdigittimeout = 16000 [static] |
Wait up to 16 seconds for first digit (FXO logic).
Definition at line 218 of file chan_dahdi.c.
Referenced by disa_exec(), mgcp_ss(), and skinny_ss().
int gendigittimeout = 8000 [static] |
How long to wait for following digits (FXO logic).
Definition at line 221 of file chan_dahdi.c.
Referenced by mgcp_ss(), and skinny_ss().
struct ast_jb_conf global_jbconf [static] |
Definition at line 117 of file chan_dahdi.c.
int ifcount = 0 [static] |
Definition at line 230 of file chan_dahdi.c.
Referenced by __action_showchannels(), __oh323_destroy(), __sip_destroy(), __sip_show_channels(), __unload_module(), chandup(), complete_sipch(), dahdi_destroy_channel_bynum(), dahdi_hangup(), dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), destroy_channel(), do_monitor(), find_call(), find_call_locked(), find_channel(), get_sip_pvt_byid_locked(), handle_request_subscribe(), load_module(), mkintf(), oh323_alloc(), phone_request(), sip_alloc(), sip_show_channel(), sip_show_history(), and unload_module().
ast_mutex_t iflock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
Protect the interface list (of dahdi_pvt's).
Definition at line 227 of file chan_dahdi.c.
Referenced by __action_showchannels(), __sip_show_channels(), __unload_module(), complete_sipch(), dahdi_hangup(), dahdi_request(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), do_monitor(), find_call(), find_call_locked(), get_sip_pvt_byid_locked(), handle_request_subscribe(), load_module(), oh323_alloc(), oh323_destroy(), phone_request(), restart_monitor(), setup_dahdi(), sip_alloc(), sip_destroy(), sip_show_channel(), sip_show_history(), and unload_module().
struct ast_channel inuse [static] |
Definition at line 209 of file chan_dahdi.c.
Referenced by ast_extension_state2(), ast_jb_do_usecheck(), chanavail_exec(), load_module(), pri_assign_bearer(), and update_call_counter().
int matchdigittimeout = 3000 [static] |
How long to wait for an extra digit, if there is an ambiguous match.
Definition at line 224 of file chan_dahdi.c.
Referenced by mgcp_ss(), and skinny_ss().
pthread_t monitor_thread = AST_PTHREADT_NULL [static] |
This is the thread for the monitor which checks for input on the channels which are not currently in use.
Definition at line 242 of file chan_dahdi.c.
Referenced by reload_config(), restart_monitor(), and unload_module().
ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
Definition at line 238 of file chan_dahdi.c.
Referenced by __unload_module(), dahdi_restart(), do_monitor(), restart_monitor(), and unload_module().
char* name |
Definition at line 1170 of file chan_dahdi.c.
int num_cadence = 4 [static] |
Definition at line 775 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 9991 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 9995 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 9999 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 10003 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 10007 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 344 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] |
Definition at line 290 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 10499 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 10495 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 776 of file chan_dahdi.c.
char* zap_send_keypad_facility_app = "ZapSendKeypadFacility" [static] |
Definition at line 2363 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 2371 of file chan_dahdi.c.
char* zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static] |
Definition at line 2366 of file chan_dahdi.c.
struct ast_channel_tech zap_tech [static] |