#include "asterisk.h"
#include <sys/signal.h>
#include <sys/ioctl.h>
#include <math.h>
#include <ctype.h>
#include <dahdi/user.h>
#include <dahdi/tonezone.h>
#include <libpri.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.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/event.h"
#include "asterisk/devicestate.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 | mwi_thread_data |
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 | CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING) |
#define | CALLPROGRESS_FAX_INCOMING 4 |
#define | CALLPROGRESS_FAX_OUTGOING 2 |
#define | CALLPROGRESS_PROGRESS 1 |
#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_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING) |
#define | DAHDI_OVERLAPDIAL_INCOMING 2 |
#define | DAHDI_OVERLAPDIAL_NONE 0 |
#define | DAHDI_OVERLAPDIAL_OUTGOING 1 |
#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 %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n" |
#define | FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" |
#define | FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n" |
#define | FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\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 | 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_BRI (0x2000000 | DAHDI_SIG_CLEAR) |
#define | SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR) |
#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 | SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR) |
#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 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 int | action_dahdidialoffhook (struct mansession *s, const struct message *m) |
static int | action_dahdidndoff (struct mansession *s, const struct message *m) |
static int | action_dahdidndon (struct mansession *s, const struct message *m) |
static int | action_dahdirestart (struct mansession *s, const struct message *m) |
static int | action_dahdishowchannels (struct mansession *s, const struct message *m) |
static int | action_transfer (struct mansession *s, const struct message *m) |
static int | action_transferhangup (struct mansession *s, const struct message *m) |
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 int | calc_energy (const unsigned char *buf, int len, int law) |
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_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 char * | dahdi_destroy_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
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_dnd (struct dahdi_pvt *dahdichan, int on) |
enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel | |
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, const 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, void *data) |
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 char * | dahdi_restart_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
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 char * | dahdi_set_dnd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | dahdi_set_hook (int fd, int hs) |
static char * | dahdi_set_hwgain (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | dahdi_set_swgain (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
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 char * | dahdi_show_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | dahdi_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | dahdi_show_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | dahdi_show_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
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 char * | handle_dahdi_show_cadences (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | handle_init_event (struct dahdi_pvt *i, int event) |
static char * | handle_pri_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_pri_no_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_pri_really_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_pri_set_debug_file (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_pri_show_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_pri_show_span (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_pri_show_spans (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_pri_unset_debug_file (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
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 void | mwi_event_cb (const struct ast_event *event, void *userdata) |
static void * | mwi_thread (void *data) |
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 void | notify_message (char *mailbox_full, int thereornot) |
Send MWI state change. | |
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, struct ast_variable *v, int reload, int skipchannels) |
static void | process_echocancel (struct dahdi_chan_conf *confp, const char *data, unsigned int line) |
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 | 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 int | sigtype_to_signalling (int sigtype) |
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) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "068e67f60f50dd9ee86464c05884a49d" , .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 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 const char | config [] = "chan_dahdi.conf" |
static struct ast_cli_entry | dahdi_cli [] |
static struct ast_cli_entry | dahdi_pri_cli [] |
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 struct ast_channel_tech | dahdi_tech |
static struct ast_jb_conf | default_jbconf |
static char | defaultcic [64] = "" |
static char | defaultozz [64] = "" |
static int | distinctiveringaftercid = 0 |
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_RECURSIVE_MUTEX_INITIALIZER_NP ) |
Protect the interface list (of dahdi_pvt's). | |
static struct ast_channel | inuse |
static const char * | lbostr [] |
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_RECURSIVE_MUTEX_INITIALIZER_NP ) |
Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical. | |
static int | mwilevel = 512 |
static char | mwimonitornotify [PATH_MAX] = "" |
static int | num_cadence = 4 |
static int | num_restart_pending = 0 |
static int | numbufs = 4 |
static int | pridebugfd = -1 |
static ast_mutex_t | pridebugfdlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
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_RECURSIVE_MUTEX_INITIALIZER_NP ) |
static int | ringt_base = DEFAULT_RINGT |
Configured ring timeout base. | |
dahdi_pvt * | round_robin [32] |
static ast_cond_t | ss_thread_complete |
static int | ss_thread_count = 0 |
static ast_mutex_t | ss_thread_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
static char * | subnames [] |
static const char | tdesc [] |
static int | usedistinctiveringdetection = 0 |
static int | user_has_defined_cadences = 0 |
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 153 of file chan_dahdi.c.
Referenced by dahdi_call(), dahdi_callwait(), dahdi_sendtext(), mwi_thread(), send_cwcidspill(), and ss_thread().
#define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING) |
Definition at line 224 of file chan_dahdi.c.
Referenced by dahdi_handle_dtmfup(), and process_dahdi().
#define CALLPROGRESS_FAX_INCOMING 4 |
#define CALLPROGRESS_FAX_OUTGOING 2 |
#define CALLPROGRESS_PROGRESS 1 |
Definition at line 221 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_new(), and process_dahdi().
#define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) |
#define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) |
300 ms
Definition at line 323 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 206 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 151 of file chan_dahdi.c.
#define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) |
#define CONF_USER_REAL (1 << 0) |
Definition at line 505 of file chan_dahdi.c.
#define CONF_USER_THIRDCALL (1 << 1) |
Definition at line 506 of file chan_dahdi.c.
#define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING) |
#define DAHDI_OVERLAPDIAL_INCOMING 2 |
Definition at line 217 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_read(), handle_pri_show_span(), and process_dahdi().
#define DAHDI_OVERLAPDIAL_NONE 0 |
#define DAHDI_OVERLAPDIAL_OUTGOING 1 |
Definition at line 216 of file chan_dahdi.c.
Referenced by dahdi_read(), process_dahdi(), and start_pri().
#define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP) |
#define DCHAN_NOTINALARM (1 << 1) |
#define DCHAN_PROVISIONED (1 << 0) |
Definition at line 208 of file chan_dahdi.c.
Referenced by build_status(), pri_create_trunkgroup(), and pri_resolve_span().
#define DCHAN_UP (1 << 2) |
Definition at line 210 of file chan_dahdi.c.
#define DEFAULT_CIDRINGS 1 |
Typically, how many rings before we should send Caller*ID.
Definition at line 149 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 327 of file chan_dahdi.c.
#define END_SILENCE_LEN 400 |
Referenced by dahdi_sendtext().
#define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n" |
#define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" |
#define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n" |
#define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" |
#define GET_CHANNEL | ( | p | ) | ((p)->bearer ? (p)->bearer->channel : p->channel) |
Definition at line 1220 of file chan_dahdi.c.
#define HANGUP 1 |
Definition at line 13103 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 1292 of file chan_dahdi.c.
Referenced by dahdi_indicate(), dahdi_show_channel(), and ss_thread().
#define MASK_AVAIL (1 << 0) |
Channel available for PRI use
Definition at line 320 of file chan_dahdi.c.
#define MASK_INUSE (1 << 1) |
Channel currently in use
Definition at line 321 of file chan_dahdi.c.
#define MAX_CHANLIST_LEN 80 |
The length of the parameters list of 'dahdichan'.
Definition at line 13942 of file chan_dahdi.c.
Referenced by process_dahdi().
#define MAX_CHANNELS 672 |
No more than a DS3 per trunk group
Definition at line 204 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 157 of file chan_dahdi.c.
Referenced by dahdi_new(), and ss_thread().
#define NUM_CADENCE_MAX 25 |
Definition at line 1270 of file chan_dahdi.c.
#define NUM_DCHANS 4 |
No more than 4 d-channels
Definition at line 203 of file chan_dahdi.c.
Referenced by mkintf(), pri_active_dchan_fd(), pri_create_trunkgroup(), pri_find_dchan(), and pri_is_up().
#define NUM_SPANS 32 |
Definition at line 201 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(), process_dahdi(), setup_dahdi(), and unload_module().
#define POLARITY_IDLE 0 |
Definition at line 464 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_hangup(), and unalloc_sub().
#define POLARITY_REV 1 |
Definition at line 465 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 384 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 318 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 1821 of file chan_dahdi.c.
Referenced by action_dahdishowchannels(), build_channels(), dahdi_handle_event(), dahdi_show_channel(), handle_init_event(), and mkintf().
#define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR) |
Definition at line 186 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_queue_frame(), dahdi_read(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), ss_thread(), and start_pri().
#define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR) |
Definition at line 187 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_queue_frame(), dahdi_read(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), ss_thread(), and start_pri().
#define SIG_E911 (0x1000000 | DAHDI_SIG_EM) |
Definition at line 175 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_EM DAHDI_SIG_EM |
Definition at line 170 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_EM_E1 DAHDI_SIG_EM_E1 |
Definition at line 194 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM) |
Definition at line 171 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FEATB (0x0800000 | DAHDI_SIG_EM) |
Definition at line 174 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FEATD (0x0200000 | DAHDI_SIG_EM) |
Definition at line 172 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM) |
Definition at line 173 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM) |
Definition at line 176 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM) |
Definition at line 177 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM) |
Definition at line 178 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FXOGS DAHDI_SIG_FXOGS |
Definition at line 183 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FXOKS DAHDI_SIG_FXOKS |
Definition at line 184 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
#define SIG_FXOLS DAHDI_SIG_FXOLS |
Definition at line 182 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FXSGS DAHDI_SIG_FXSGS |
Definition at line 180 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FXSKS DAHDI_SIG_FXSKS |
Definition at line 181 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_request(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
#define SIG_FXSLS DAHDI_SIG_FXSLS |
Definition at line 179 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS) |
Definition at line 195 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 196 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 185 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_queue_frame(), dahdi_read(), dahdi_sig2str(), dahdi_write(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
#define SIG_SF DAHDI_SIG_SF |
Definition at line 189 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF) |
Definition at line 193 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 191 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 192 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 190 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_SS7 (0x1000000 | DAHDI_SIG_CLEAR) |
Definition at line 188 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_queue_frame(), dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().
#define SMDI_MD_WAIT_TIMEOUT 1500 |
#define SUB_CALLWAIT 1 |
Call-Waiting call on hold
Definition at line 460 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 459 of file chan_dahdi.c.
Referenced by __dahdi_exception(), attempt_transfer(), available(), build_device(), bump_gains(), chandup(), check_for_conference(), close_call(), close_client(), 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(), find_subchannel_by_name(), get_alarms(), handle_init_event(), HandleCallIncoming(), HandleCallOutgoing(), key_call(), key_dial_page(), mkintf(), mwi_thread(), pri_assign_bearer(), pri_fixup_principle(), process_request(), rcv_mac_addr(), reset_conf(), restore_conference(), restore_gains(), save_conference(), send_callerid(), ss_thread(), TransferCallStep1(), unistim_do_senddigit(), unistim_hangup(), and unistim_senddigit_end().
#define SUB_THREEWAY 2 |
Three-way call
Definition at line 461 of file chan_dahdi.c.
Referenced by attempt_transfer(), available(), close_call(), dahdi_answer(), dahdi_bridge(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_show_channel(), features_hangup(), HandleCallOutgoing(), ss_thread(), TransferCallStep1(), unistim_answer(), and unistim_hangup().
#define tdesc "DAHDI Telephony w/PRI" |
Definition at line 15163 of file chan_dahdi.c.
#define TRAILER_MS 5 |
Referenced by dahdi_sendtext().
#define TRANSFER 0 |
Definition at line 13102 of file chan_dahdi.c.
Referenced by action_transfer(), and dahdi_fake_event().
static struct ast_frame* __dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5531 of file chan_dahdi.c.
References ast_bridged_channel(), AST_CONTROL_UNHOLD, ast_debug, AST_FRAME_NULL, ast_log(), ast_queue_control(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_tv(), ast_tvnow(), ast_verb, 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, ast_frame::mallocd, ast_channel::name, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, 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, and update_conf().
Referenced by dahdi_exception(), and dahdi_read().
05532 { 05533 struct dahdi_pvt *p = ast->tech_pvt; 05534 int res; 05535 int usedindex=-1; 05536 int index; 05537 struct ast_frame *f; 05538 05539 05540 index = dahdi_get_index(ast, p, 1); 05541 05542 p->subs[index].f.frametype = AST_FRAME_NULL; 05543 p->subs[index].f.datalen = 0; 05544 p->subs[index].f.samples = 0; 05545 p->subs[index].f.mallocd = 0; 05546 p->subs[index].f.offset = 0; 05547 p->subs[index].f.subclass = 0; 05548 p->subs[index].f.delivery = ast_tv(0,0); 05549 p->subs[index].f.src = "dahdi_exception"; 05550 p->subs[index].f.data = NULL; 05551 05552 05553 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) { 05554 /* If nobody owns us, absorb the event appropriately, otherwise 05555 we loop indefinitely. This occurs when, during call waiting, the 05556 other end hangs up our channel so that it no longer exists, but we 05557 have neither FLASH'd nor ONHOOK'd to signify our desire to 05558 change to the other channel. */ 05559 if (p->fake_event) { 05560 res = p->fake_event; 05561 p->fake_event = 0; 05562 } else 05563 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 05564 /* Switch to real if there is one and this isn't something really silly... */ 05565 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) && 05566 (res != DAHDI_EVENT_HOOKCOMPLETE)) { 05567 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res); 05568 p->owner = p->subs[SUB_REAL].owner; 05569 if (p->owner && ast_bridged_channel(p->owner)) 05570 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05571 p->subs[SUB_REAL].needunhold = 1; 05572 } 05573 switch (res) { 05574 case DAHDI_EVENT_ONHOOK: 05575 dahdi_disable_ec(p); 05576 if (p->owner) { 05577 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name); 05578 dahdi_ring_phone(p); 05579 p->callwaitingrepeat = 0; 05580 p->cidcwexpire = 0; 05581 } else 05582 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 05583 update_conf(p); 05584 break; 05585 case DAHDI_EVENT_RINGOFFHOOK: 05586 dahdi_enable_ec(p); 05587 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 05588 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) { 05589 p->subs[SUB_REAL].needanswer = 1; 05590 p->dialing = 0; 05591 } 05592 break; 05593 case DAHDI_EVENT_HOOKCOMPLETE: 05594 case DAHDI_EVENT_RINGERON: 05595 case DAHDI_EVENT_RINGEROFF: 05596 /* Do nothing */ 05597 break; 05598 case DAHDI_EVENT_WINKFLASH: 05599 p->flashtime = ast_tvnow(); 05600 if (p->owner) { 05601 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name); 05602 if (p->owner->_state != AST_STATE_UP) { 05603 /* Answer if necessary */ 05604 usedindex = dahdi_get_index(p->owner, p, 0); 05605 if (usedindex > -1) { 05606 p->subs[usedindex].needanswer = 1; 05607 } 05608 ast_setstate(p->owner, AST_STATE_UP); 05609 } 05610 p->callwaitingrepeat = 0; 05611 p->cidcwexpire = 0; 05612 if (ast_bridged_channel(p->owner)) 05613 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05614 p->subs[SUB_REAL].needunhold = 1; 05615 } else 05616 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 05617 update_conf(p); 05618 break; 05619 default: 05620 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res)); 05621 } 05622 f = &p->subs[index].f; 05623 return f; 05624 } 05625 if (!(p->radio || (p->oprmode < 0))) 05626 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel); 05627 /* If it's not us, return NULL immediately */ 05628 if (ast != p->owner) { 05629 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name); 05630 f = &p->subs[index].f; 05631 return f; 05632 } 05633 f = dahdi_handle_event(ast); 05634 return f; 05635 }
static void __reg_module | ( | void | ) | [static] |
Definition at line 15177 of file chan_dahdi.c.
static int __unload_module | ( | void | ) | [static] |
Definition at line 13760 of file chan_dahdi.c.
References ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_destroy(), ast_manager_unregister(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_unregister_application(), dahdi_cli, dahdi_close_pri_fd(), dahdi_pri_cli, dahdi_tech, destroy_all_channels(), iflist, iflock, monlock, dahdi_pvt::next, NUM_SPANS, dahdi_pvt::owner, and pris.
Referenced by load_module(), and unload_module().
13761 { 13762 struct dahdi_pvt *p; 13763 #if defined(HAVE_PRI) || defined(HAVE_SS7) 13764 int i, j; 13765 #endif 13766 13767 #ifdef HAVE_PRI 13768 for (i = 0; i < NUM_SPANS; i++) { 13769 if (pris[i].master != AST_PTHREADT_NULL) 13770 pthread_cancel(pris[i].master); 13771 } 13772 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 13773 ast_unregister_application(dahdi_send_keypad_facility_app); 13774 #endif 13775 #if defined(HAVE_SS7) 13776 for (i = 0; i < NUM_SPANS; i++) { 13777 if (linksets[i].master != AST_PTHREADT_NULL) 13778 pthread_cancel(linksets[i].master); 13779 } 13780 ast_cli_unregister_multiple(dahdi_ss7_cli, sizeof(dahdi_ss7_cli) / sizeof(struct ast_cli_entry)); 13781 #endif 13782 13783 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 13784 ast_manager_unregister( "DAHDIDialOffhook" ); 13785 ast_manager_unregister( "DAHDIHangup" ); 13786 ast_manager_unregister( "DAHDITransfer" ); 13787 ast_manager_unregister( "DAHDIDNDoff" ); 13788 ast_manager_unregister( "DAHDIDNDon" ); 13789 ast_manager_unregister("DAHDIShowChannels"); 13790 ast_manager_unregister("DAHDIRestart"); 13791 ast_channel_unregister(&dahdi_tech); 13792 ast_mutex_lock(&iflock); 13793 /* Hangup all interfaces if they have an owner */ 13794 p = iflist; 13795 while (p) { 13796 if (p->owner) 13797 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 13798 p = p->next; 13799 } 13800 ast_mutex_unlock(&iflock); 13801 ast_mutex_lock(&monlock); 13802 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 13803 pthread_cancel(monitor_thread); 13804 pthread_kill(monitor_thread, SIGURG); 13805 pthread_join(monitor_thread, NULL); 13806 } 13807 monitor_thread = AST_PTHREADT_STOP; 13808 ast_mutex_unlock(&monlock); 13809 13810 destroy_all_channels(); 13811 13812 #if defined(HAVE_PRI) 13813 for (i = 0; i < NUM_SPANS; i++) { 13814 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) 13815 pthread_join(pris[i].master, NULL); 13816 for (j = 0; j < NUM_DCHANS; j++) { 13817 dahdi_close_pri_fd(&(pris[i]), j); 13818 } 13819 } 13820 #endif 13821 13822 #if defined(HAVE_SS7) 13823 for (i = 0; i < NUM_SPANS; i++) { 13824 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) 13825 pthread_join(linksets[i].master, NULL); 13826 for (j = 0; j < NUM_DCHANS; j++) { 13827 dahdi_close_ss7_fd(&(linksets[i]), j); 13828 } 13829 } 13830 #endif 13831 13832 ast_cond_destroy(&ss_thread_complete); 13833 return 0; 13834 }
static void __unreg_module | ( | void | ) | [static] |
Definition at line 15177 of file chan_dahdi.c.
static int action_dahdidialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13209 of file chan_dahdi.c.
References AST_FRAME_DTMF, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_queue_frame(), f, find_channel(), dahdi_pvt::owner, and s.
Referenced by load_module().
13210 { 13211 struct dahdi_pvt *p = NULL; 13212 const char *channel = astman_get_header(m, "DAHDIChannel"); 13213 const char *number = astman_get_header(m, "Number"); 13214 int i; 13215 13216 if (ast_strlen_zero(channel)) { 13217 astman_send_error(s, m, "No channel specified"); 13218 return 0; 13219 } 13220 if (ast_strlen_zero(number)) { 13221 astman_send_error(s, m, "No number specified"); 13222 return 0; 13223 } 13224 p = find_channel(atoi(channel)); 13225 if (!p) { 13226 astman_send_error(s, m, "No such channel"); 13227 return 0; 13228 } 13229 if (!p->owner) { 13230 astman_send_error(s, m, "Channel does not have it's owner"); 13231 return 0; 13232 } 13233 for (i = 0; i < strlen(number); i++) { 13234 struct ast_frame f = { AST_FRAME_DTMF, number[i] }; 13235 dahdi_queue_frame(p, &f, NULL); 13236 } 13237 astman_send_ack(s, m, "DAHDIDialOffhook"); 13238 return 0; 13239 }
static int action_dahdidndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13152 of file chan_dahdi.c.
References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_pvt::dnd, find_channel(), and s.
Referenced by load_module().
13153 { 13154 struct dahdi_pvt *p = NULL; 13155 const char *channel = astman_get_header(m, "DAHDIChannel"); 13156 13157 if (ast_strlen_zero(channel)) { 13158 astman_send_error(s, m, "No channel specified"); 13159 return 0; 13160 } 13161 p = find_channel(atoi(channel)); 13162 if (!p) { 13163 astman_send_error(s, m, "No such channel"); 13164 return 0; 13165 } 13166 p->dnd = 0; 13167 astman_send_ack(s, m, "DND Disabled"); 13168 return 0; 13169 }
static int action_dahdidndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13133 of file chan_dahdi.c.
References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_pvt::dnd, find_channel(), and s.
Referenced by load_module().
13134 { 13135 struct dahdi_pvt *p = NULL; 13136 const char *channel = astman_get_header(m, "DAHDIChannel"); 13137 13138 if (ast_strlen_zero(channel)) { 13139 astman_send_error(s, m, "No channel specified"); 13140 return 0; 13141 } 13142 p = find_channel(atoi(channel)); 13143 if (!p) { 13144 astman_send_error(s, m, "No such channel"); 13145 return 0; 13146 } 13147 p->dnd = 1; 13148 astman_send_ack(s, m, "DND Enabled"); 13149 return 0; 13150 }
static int action_dahdirestart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12408 of file chan_dahdi.c.
References astman_send_ack(), astman_send_error(), dahdi_restart(), and s.
Referenced by load_module().
12409 { 12410 if (dahdi_restart() != 0) { 12411 astman_send_error(s, m, "Failed rereading DAHDI configuration"); 12412 return 1; 12413 } 12414 astman_send_ack(s, m, "DAHDIRestart: Success"); 12415 return 0; 12416 }
static int action_dahdishowchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13241 of file chan_dahdi.c.
References ast_channel::accountcode, alarm, alarm2str(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_ack(), dahdi_pvt::channel, dahdi_pvt::context, dahdi_pvt::dnd, get_alarms(), iflist, iflock, ast_channel::name, dahdi_pvt::next, dahdi_pvt::owner, s, dahdi_pvt::sig, sig2str, and ast_channel::uniqueid.
Referenced by load_module().
13242 { 13243 struct dahdi_pvt *tmp = NULL; 13244 const char *id = astman_get_header(m, "ActionID"); 13245 const char *dahdichannel = astman_get_header(m, "DAHDIChannel"); 13246 char idText[256] = ""; 13247 int channels = 0; 13248 int dahdichanquery = -1; 13249 if (!ast_strlen_zero(dahdichannel)) { 13250 dahdichanquery = atoi(dahdichannel); 13251 } 13252 13253 astman_send_ack(s, m, "DAHDI channel status will follow"); 13254 if (!ast_strlen_zero(id)) 13255 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 13256 13257 ast_mutex_lock(&iflock); 13258 13259 tmp = iflist; 13260 while (tmp) { 13261 if (tmp->channel > 0) { 13262 int alarm = get_alarms(tmp); 13263 13264 /* If a specific channel is queried for, only deliver status for that channel */ 13265 if (dahdichanquery > 0 && tmp->channel != dahdichanquery) 13266 continue; 13267 13268 channels++; 13269 if (tmp->owner) { 13270 /* Add data if we have a current call */ 13271 astman_append(s, 13272 "Event: DAHDIShowChannels\r\n" 13273 "DAHDIChannel: %d\r\n" 13274 "Channel: %s\r\n" 13275 "Uniqueid: %s\r\n" 13276 "AccountCode: %s\r\n" 13277 "Signalling: %s\r\n" 13278 "SignallingCode: %d\r\n" 13279 "Context: %s\r\n" 13280 "DND: %s\r\n" 13281 "Alarm: %s\r\n" 13282 "%s" 13283 "\r\n", 13284 tmp->channel, 13285 tmp->owner->name, 13286 tmp->owner->uniqueid, 13287 tmp->owner->accountcode, 13288 sig2str(tmp->sig), 13289 tmp->sig, 13290 tmp->context, 13291 tmp->dnd ? "Enabled" : "Disabled", 13292 alarm2str(alarm), idText); 13293 } else { 13294 astman_append(s, 13295 "Event: DAHDIShowChannels\r\n" 13296 "DAHDIChannel: %d\r\n" 13297 "Signalling: %s\r\n" 13298 "SignallingCode: %d\r\n" 13299 "Context: %s\r\n" 13300 "DND: %s\r\n" 13301 "Alarm: %s\r\n" 13302 "%s" 13303 "\r\n", 13304 tmp->channel, sig2str(tmp->sig), tmp->sig, 13305 tmp->context, 13306 tmp->dnd ? "Enabled" : "Disabled", 13307 alarm2str(alarm), idText); 13308 } 13309 } 13310 13311 tmp = tmp->next; 13312 } 13313 13314 ast_mutex_unlock(&iflock); 13315 13316 astman_append(s, 13317 "Event: DAHDIShowChannelsComplete\r\n" 13318 "%s" 13319 "Items: %d\r\n" 13320 "\r\n", 13321 idText, 13322 channels); 13323 return 0; 13324 }
static int action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13171 of file chan_dahdi.c.
References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_fake_event(), find_channel(), s, and TRANSFER.
Referenced by load_module().
13172 { 13173 struct dahdi_pvt *p = NULL; 13174 const char *channel = astman_get_header(m, "DAHDIChannel"); 13175 13176 if (ast_strlen_zero(channel)) { 13177 astman_send_error(s, m, "No channel specified"); 13178 return 0; 13179 } 13180 p = find_channel(atoi(channel)); 13181 if (!p) { 13182 astman_send_error(s, m, "No such channel"); 13183 return 0; 13184 } 13185 dahdi_fake_event(p,TRANSFER); 13186 astman_send_ack(s, m, "DAHDITransfer"); 13187 return 0; 13188 }
static int action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13190 of file chan_dahdi.c.
References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_fake_event(), find_channel(), HANGUP, and s.
Referenced by load_module().
13191 { 13192 struct dahdi_pvt *p = NULL; 13193 const char *channel = astman_get_header(m, "DAHDIChannel"); 13194 13195 if (ast_strlen_zero(channel)) { 13196 astman_send_error(s, m, "No channel specified"); 13197 return 0; 13198 } 13199 p = find_channel(atoi(channel)); 13200 if (!p) { 13201 astman_send_error(s, m, "No such channel"); 13202 return 0; 13203 } 13204 dahdi_fake_event(p,HANGUP); 13205 astman_send_ack(s, m, "DAHDIHangup"); 13206 return 0; 13207 }
static char* alarm2str | ( | int | alarm | ) | [static] |
Definition at line 1726 of file chan_dahdi.c.
References alarms, and ARRAY_LEN.
Referenced by action_dahdishowchannels(), and handle_alarms().
01727 { 01728 int x; 01729 for (x = 0; x < ARRAY_LEN(alarms); x++) { 01730 if (alarms[x].alarm & alarm) 01731 return alarms[x].name; 01732 } 01733 return alarm ? "Unknown Alarm" : "No Alarm"; 01734 }
static int alloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 1522 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_subchannel::chan, dahdi_pvt::channel, dahdi_close_sub(), dahdi_open(), dahdi_subchannel::dfd, errno, LOG_WARNING, and dahdi_pvt::subs.
Referenced by build_device(), dahdi_handle_event(), dahdi_request(), HandleCallOutgoing(), rcv_mac_addr(), and ss_thread().
01523 { 01524 struct dahdi_bufferinfo bi; 01525 int res; 01526 if (p->subs[x].dfd >= 0) { 01527 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel); 01528 return -1; 01529 } 01530 01531 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo"); 01532 if (p->subs[x].dfd <= -1) { 01533 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 01534 return -1; 01535 } 01536 01537 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi); 01538 if (!res) { 01539 bi.txbufpolicy = p->buf_policy; 01540 bi.rxbufpolicy = p->buf_policy; 01541 bi.numbufs = p->buf_no; 01542 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi); 01543 if (res < 0) { 01544 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno)); 01545 } 01546 } else 01547 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno)); 01548 01549 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) { 01550 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno)); 01551 dahdi_close_sub(p, x); 01552 p->subs[x].dfd = -1; 01553 return -1; 01554 } 01555 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan); 01556 return 0; 01557 }
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 10634 of file chan_dahdi.c.
References ast_strlen_zero(), dahdi_pri::dialplan, dahdi_pri::internationalprefix, dahdi_pri::localprefix, dahdi_pri::nationalprefix, dahdi_pri::privateprefix, and dahdi_pri::unknownprefix.
10635 { 10636 if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */ 10637 snprintf(buf, size, "%s", number); 10638 return; 10639 } 10640 if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */ 10641 if (size) { 10642 *buf = '\0'; 10643 } 10644 return; 10645 } 10646 switch (plan) { 10647 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */ 10648 snprintf(buf, size, "%s%s", pri->internationalprefix, number); 10649 break; 10650 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */ 10651 snprintf(buf, size, "%s%s", pri->nationalprefix, number); 10652 break; 10653 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */ 10654 snprintf(buf, size, "%s%s", pri->localprefix, number); 10655 break; 10656 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */ 10657 snprintf(buf, size, "%s%s", pri->privateprefix, number); 10658 break; 10659 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */ 10660 snprintf(buf, size, "%s%s", pri->unknownprefix, number); 10661 break; 10662 default: /* other Q.931 dialplan => don't twiddle with callingnum */ 10663 snprintf(buf, size, "%s", number); 10664 break; 10665 } 10666 }
static int attempt_transfer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4497 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, ast_bridged_channel(), ast_channel_masquerade(), ast_channel_unlock, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_debug, ast_indicate(), ast_log(), ast_queue_control(), AST_SOFTHANGUP_DEV, AST_STATE_RING, AST_STATE_RINGING, dahdi_subchannel::dfd, ast_channel::name, dahdi_subchannel::owner, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and unalloc_sub().
Referenced by close_call(), dahdi_handle_event(), handle_onhook_message(), handle_request(), handle_soft_key_event_message(), and local_attended_transfer().
04498 { 04499 /* In order to transfer, we need at least one of the channels to 04500 actually be in a call bridge. We can't conference two applications 04501 together (but then, why would we want to?) */ 04502 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 04503 /* The three-way person we're about to transfer to could still be in MOH, so 04504 stop if now if appropriate */ 04505 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) 04506 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD); 04507 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) { 04508 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING); 04509 } 04510 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) { 04511 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 04512 } 04513 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { 04514 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 04515 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name); 04516 return -1; 04517 } 04518 /* Orphan the channel after releasing the lock */ 04519 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04520 unalloc_sub(p, SUB_THREEWAY); 04521 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 04522 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 04523 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) { 04524 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING); 04525 } 04526 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) { 04527 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04528 } 04529 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { 04530 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 04531 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); 04532 return -1; 04533 } 04534 /* Three-way is now the REAL */ 04535 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04536 ast_channel_unlock(p->subs[SUB_REAL].owner); 04537 unalloc_sub(p, SUB_THREEWAY); 04538 /* Tell the caller not to hangup */ 04539 return 1; 04540 } else { 04541 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n", 04542 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name); 04543 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04544 return -1; 04545 } 04546 return 0; 04547 }
static int available | ( | struct dahdi_pvt * | p, | |
int | channelmatch, | |||
ast_group_t | groupmatch, | |||
int * | busy, | |||
int * | channelmatched, | |||
int * | groupmatched | |||
) | [inline, static] |
Definition at line 9066 of file chan_dahdi.c.
References ast_channel::_state, ast_debug, 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, dahdi_pvt::locallyblocked, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::radio, dahdi_pvt::remotelyblocked, dahdi_pvt::resetting, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, and dahdi_pvt::subs.
Referenced by __ast_string_field_ptr_build_va(), and dahdi_request().
09067 { 09068 int res; 09069 struct dahdi_params par; 09070 09071 /* First, check group matching */ 09072 if (groupmatch) { 09073 if ((p->group & groupmatch) != groupmatch) 09074 return 0; 09075 *groupmatched = 1; 09076 } 09077 /* Check to see if we have a channel match */ 09078 if (channelmatch != -1) { 09079 if (p->channel != channelmatch) 09080 return 0; 09081 *channelmatched = 1; 09082 } 09083 /* We're at least busy at this point */ 09084 if (busy) { 09085 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS)) 09086 *busy = 1; 09087 } 09088 /* If do not disturb, definitely not */ 09089 if (p->dnd) 09090 return 0; 09091 /* If guard time, definitely not */ 09092 if (p->guardtime && (time(NULL) < p->guardtime)) 09093 return 0; 09094 09095 if (p->locallyblocked || p->remotelyblocked) 09096 return 0; 09097 09098 /* If no owner definitely available */ 09099 if (!p->owner) { 09100 #ifdef HAVE_PRI 09101 /* Trust PRI */ 09102 if (p->pri) { 09103 if (p->resetting || p->call) 09104 return 0; 09105 else 09106 return 1; 09107 } 09108 #endif 09109 #ifdef HAVE_SS7 09110 /* Trust SS7 */ 09111 if (p->ss7) { 09112 if (p->ss7call) 09113 return 0; 09114 else 09115 return 1; 09116 } 09117 #endif 09118 if (!(p->radio || (p->oprmode < 0))) 09119 { 09120 if (!p->sig || (p->sig == SIG_FXSLS)) 09121 return 1; 09122 /* Check hook state */ 09123 if (p->subs[SUB_REAL].dfd > -1) { 09124 memset(&par, 0, sizeof(par)); 09125 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 09126 } else { 09127 /* Assume not off hook on CVRS */ 09128 res = 0; 09129 par.rxisoffhook = 0; 09130 } 09131 if (res) { 09132 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno)); 09133 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) { 09134 /* When "onhook" that means no battery on the line, and thus 09135 it is out of service..., if it's on a TDM card... If it's a channel 09136 bank, there is no telling... */ 09137 if (par.rxbits > -1) 09138 return 1; 09139 if (par.rxisoffhook) 09140 return 1; 09141 else 09142 return 0; 09143 } else if (par.rxisoffhook) { 09144 ast_debug(1, "Channel %d off hook, can't use\n", p->channel); 09145 /* Not available when the other end is off hook */ 09146 #ifdef DAHDI_CHECK_HOOKSTATE 09147 return 0; 09148 #else 09149 return 1; 09150 #endif 09151 } 09152 } 09153 return 1; 09154 } 09155 09156 /* If it's not an FXO, forget about call wait */ 09157 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 09158 return 0; 09159 09160 if (!p->callwaiting) { 09161 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */ 09162 return 0; 09163 } 09164 09165 if (p->subs[SUB_CALLWAIT].dfd > -1) { 09166 /* If there is already a call waiting call, then we can't take a second one */ 09167 return 0; 09168 } 09169 09170 if ((p->owner->_state != AST_STATE_UP) && 09171 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) { 09172 /* If the current call is not up, then don't allow the call */ 09173 return 0; 09174 } 09175 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) { 09176 /* Can't take a call wait when the three way calling hasn't been merged yet. */ 09177 return 0; 09178 } 09179 /* We're cool */ 09180 return 1; 09181 }
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 13852 of file chan_dahdi.c.
References ast_log(), ast_strdupa, ast_verb, dahdi_chan_conf::chan, chan, CHAN_PSEUDO, HAVE_PRI, dahdi_chan_conf::is_sig_auto, LOG_ERROR, mkintf(), NUM_SPANS, dahdi_pri::pri, pris, dahdi_pvt::sig, sig2str, strsep(), and dahdi_pri::trunkgroup.
Referenced by process_dahdi().
13853 { 13854 char *c, *chan; 13855 int x, start, finish; 13856 struct dahdi_pvt *tmp; 13857 #ifdef HAVE_PRI 13858 struct dahdi_pri *pri; 13859 int trunkgroup, y; 13860 #endif 13861 13862 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) { 13863 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); 13864 return -1; 13865 } 13866 13867 c = ast_strdupa(value); 13868 13869 #ifdef HAVE_PRI 13870 pri = NULL; 13871 if (iscrv) { 13872 if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) { 13873 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno); 13874 return -1; 13875 } 13876 if (trunkgroup < 1) { 13877 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno); 13878 return -1; 13879 } 13880 c += y; 13881 for (y = 0; y < NUM_SPANS; y++) { 13882 if (pris[y].trunkgroup == trunkgroup) { 13883 pri = pris + y; 13884 break; 13885 } 13886 } 13887 if (!pri) { 13888 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno); 13889 return -1; 13890 } 13891 } 13892 #endif 13893 13894 while ((chan = strsep(&c, ","))) { 13895 if (sscanf(chan, "%d-%d", &start, &finish) == 2) { 13896 /* Range */ 13897 } else if (sscanf(chan, "%d", &start)) { 13898 /* Just one */ 13899 finish = start; 13900 } else if (!strcasecmp(chan, "pseudo")) { 13901 finish = start = CHAN_PSEUDO; 13902 if (found_pseudo) 13903 *found_pseudo = 1; 13904 } else { 13905 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan); 13906 return -1; 13907 } 13908 if (finish < start) { 13909 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); 13910 x = finish; 13911 finish = start; 13912 start = x; 13913 } 13914 13915 for (x = start; x <= finish; x++) { 13916 #ifdef HAVE_PRI 13917 tmp = mkintf(x, conf, pri, reload); 13918 #else 13919 tmp = mkintf(x, conf, NULL, reload); 13920 #endif 13921 13922 if (tmp) { 13923 #ifdef HAVE_PRI 13924 if (pri) 13925 ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig)); 13926 else 13927 #endif 13928 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig)); 13929 } else { 13930 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n", 13931 (reload == 1) ? "reconfigure" : "register", value); 13932 return -1; 13933 } 13934 } 13935 } 13936 13937 return 0; 13938 }
static void build_status | ( | char * | s, | |
size_t | len, | |||
int | status, | |||
int | active | |||
) | [static] |
Definition at line 12067 of file chan_dahdi.c.
References DCHAN_NOTINALARM, and DCHAN_PROVISIONED.
Referenced by handle_pri_show_span(), and handle_pri_show_spans().
12068 { 12069 if (!s || len < 1) { 12070 return; 12071 } 12072 s[0] = '\0'; 12073 if (status & DCHAN_PROVISIONED) 12074 strncat(s, "Provisioned, ", len - strlen(s) - 1); 12075 if (!(status & DCHAN_NOTINALARM)) 12076 strncat(s, "In Alarm, ", len - strlen(s) - 1); 12077 if (status & DCHAN_UP) 12078 strncat(s, "Up", len - strlen(s) - 1); 12079 else 12080 strncat(s, "Down", len - strlen(s) - 1); 12081 if (active) 12082 strncat(s, ", Active", len - strlen(s) - 1); 12083 else 12084 strncat(s, ", Standby", len - strlen(s) - 1); 12085 s[len - 1] = '\0'; 12086 }
static int bump_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2181 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::cid_rxgain, errno, dahdi_pvt::law, LOG_WARNING, dahdi_pvt::rxgain, set_actual_gain(), SUB_REAL, dahdi_pvt::subs, and dahdi_pvt::txgain.
Referenced by mwi_thread(), and ss_thread().
02182 { 02183 int res; 02184 02185 /* Bump receive gain by value stored in cid_rxgain */ 02186 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law); 02187 if (res) { 02188 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno)); 02189 return -1; 02190 } 02191 02192 return 0; 02193 }
static int calc_energy | ( | const unsigned char * | buf, | |
int | len, | |||
int | law | |||
) | [static] |
Definition at line 7717 of file chan_dahdi.c.
References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.
Referenced by mwi_thread().
07718 { 07719 int x; 07720 int sum = 0; 07721 07722 if (!len) 07723 return 0; 07724 07725 for (x = 0; x < len; x++) 07726 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x])); 07727 07728 return sum / len; 07729 }
Definition at line 9183 of file chan_dahdi.c.
References ast_log(), ast_malloc, ast_mutex_init(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_open(), destroy_dahdi_pvt(), errno, iflist, LOG_ERROR, dahdi_pvt::next, dahdi_pvt::prev, and SUB_REAL.
Referenced by dahdi_request().
09184 { 09185 struct dahdi_pvt *p; 09186 struct dahdi_bufferinfo bi; 09187 int res; 09188 09189 if ((p = ast_malloc(sizeof(*p)))) { 09190 memcpy(p, src, sizeof(struct dahdi_pvt)); 09191 ast_mutex_init(&p->lock); 09192 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo"); 09193 /* Allocate a dahdi structure */ 09194 if (p->subs[SUB_REAL].dfd < 0) { 09195 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno)); 09196 destroy_dahdi_pvt(&p); 09197 return NULL; 09198 } 09199 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 09200 if (!res) { 09201 bi.txbufpolicy = src->buf_policy; 09202 bi.rxbufpolicy = src->buf_policy; 09203 bi.numbufs = src->buf_no; 09204 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 09205 if (res < 0) { 09206 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno)); 09207 } 09208 } else 09209 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno)); 09210 } 09211 p->destroy = 1; 09212 p->next = iflist; 09213 p->prev = NULL; 09214 iflist = p; 09215 if (iflist->next) 09216 iflist->next->prev = p; 09217 return p; 09218 }
static int check_for_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4549 of file chan_dahdi.c.
References ast_log(), ast_verb, dahdi_pvt::channel, dahdi_pvt::confno, errno, dahdi_pvt::master, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_handle_event().
04550 { 04551 struct dahdi_confinfo ci; 04552 /* Fine if we already have a master, etc */ 04553 if (p->master || (p->confno > -1)) 04554 return 0; 04555 memset(&ci, 0, sizeof(ci)); 04556 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 04557 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno)); 04558 return 0; 04559 } 04560 /* If we have no master and don't have a confno, then 04561 if we're in a conference, it's probably a MeetMe room or 04562 some such, so don't let us 3-way out! */ 04563 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) { 04564 ast_verb(3, "Avoiding 3-way call when in an external conference\n"); 04565 return 1; 04566 } 04567 return 0; 04568 }
static char* complete_span_4 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 11892 of file chan_dahdi.c.
References complete_span_helper().
Referenced by handle_pri_debug(), and handle_pri_show_span().
11893 { 11894 return complete_span_helper(line,word,pos,state,3); 11895 }
static char* complete_span_5 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 11897 of file chan_dahdi.c.
References complete_span_helper().
Referenced by handle_pri_no_debug(), and handle_pri_really_debug().
11898 { 11899 return complete_span_helper(line,word,pos,state,4); 11900 }
static char* complete_span_helper | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state, | |||
int | rpos | |||
) | [static] |
Definition at line 11873 of file chan_dahdi.c.
References asprintf, ast_log(), errno, NUM_SPANS, and pris.
Referenced by complete_span_4(), and complete_span_5().
11874 { 11875 int which, span; 11876 char *ret = NULL; 11877 11878 if (pos != rpos) 11879 return ret; 11880 11881 for (which = span = 0; span < NUM_SPANS; span++) { 11882 if (pris[span].pri && ++which > state) { 11883 if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */ 11884 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 11885 } 11886 break; 11887 } 11888 } 11889 return ret; 11890 }
static int conf_add | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index, | |||
int | slavechannel | |||
) | [static] |
Definition at line 1823 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::confno, dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, and LOG_WARNING.
Referenced by update_conf().
01824 { 01825 /* If the conference already exists, and we're already in it 01826 don't bother doing anything */ 01827 struct dahdi_confinfo zi; 01828 01829 memset(&zi, 0, sizeof(zi)); 01830 zi.chan = 0; 01831 01832 if (slavechannel > 0) { 01833 /* If we have only one slave, do a digital mon */ 01834 zi.confmode = DAHDI_CONF_DIGITALMON; 01835 zi.confno = slavechannel; 01836 } else { 01837 if (!index) { 01838 /* Real-side and pseudo-side both participate in conference */ 01839 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER | 01840 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 01841 } else 01842 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 01843 zi.confno = p->confno; 01844 } 01845 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode)) 01846 return 0; 01847 if (c->dfd < 0) 01848 return 0; 01849 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 01850 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno)); 01851 return -1; 01852 } 01853 if (slavechannel < 1) { 01854 p->confno = zi.confno; 01855 } 01856 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 01857 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 01858 return 0; 01859 }
static int conf_del | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index | |||
) | [static] |
Definition at line 1872 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, isourconf(), and LOG_WARNING.
Referenced by dahdi_unlink(), and update_conf().
01873 { 01874 struct dahdi_confinfo zi; 01875 if (/* Can't delete if there's no dfd */ 01876 (c->dfd < 0) || 01877 /* Don't delete from the conference if it's not our conference */ 01878 !isourconf(p, c) 01879 /* Don't delete if we don't think it's conferenced at all (implied) */ 01880 ) return 0; 01881 memset(&zi, 0, sizeof(zi)); 01882 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 01883 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno)); 01884 return -1; 01885 } 01886 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 01887 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 01888 return 0; 01889 }
static int dahdi_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3733 of file chan_dahdi.c.
References ast_channel::_state, ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_tvnow(), 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_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_BRI, SIG_BRI_PTMP, 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, SIG_SS7, dahdi_pvt::span, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and ast_channel::tech_pvt.
03734 { 03735 struct dahdi_pvt *p = ast->tech_pvt; 03736 int res = 0; 03737 int index; 03738 int oldstate = ast->_state; 03739 ast_setstate(ast, AST_STATE_UP); 03740 ast_mutex_lock(&p->lock); 03741 index = dahdi_get_index(ast, p, 0); 03742 if (index < 0) 03743 index = SUB_REAL; 03744 /* nothing to do if a radio channel */ 03745 if ((p->radio || (p->oprmode < 0))) { 03746 ast_mutex_unlock(&p->lock); 03747 return 0; 03748 } 03749 switch (p->sig) { 03750 case SIG_FXSLS: 03751 case SIG_FXSGS: 03752 case SIG_FXSKS: 03753 p->ringt = 0; 03754 /* Fall through */ 03755 case SIG_EM: 03756 case SIG_EM_E1: 03757 case SIG_EMWINK: 03758 case SIG_FEATD: 03759 case SIG_FEATDMF: 03760 case SIG_FEATDMF_TA: 03761 case SIG_E911: 03762 case SIG_FGC_CAMA: 03763 case SIG_FGC_CAMAMF: 03764 case SIG_FEATB: 03765 case SIG_SF: 03766 case SIG_SFWINK: 03767 case SIG_SF_FEATD: 03768 case SIG_SF_FEATDMF: 03769 case SIG_SF_FEATB: 03770 case SIG_FXOLS: 03771 case SIG_FXOGS: 03772 case SIG_FXOKS: 03773 /* Pick up the line */ 03774 ast_debug(1, "Took %s off hook\n", ast->name); 03775 if (p->hanguponpolarityswitch) { 03776 p->polaritydelaytv = ast_tvnow(); 03777 } 03778 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 03779 tone_zone_play_tone(p->subs[index].dfd, -1); 03780 p->dialing = 0; 03781 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) { 03782 if (oldstate == AST_STATE_RINGING) { 03783 ast_debug(1, "Finally swapping real and threeway\n"); 03784 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1); 03785 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03786 p->owner = p->subs[SUB_REAL].owner; 03787 } 03788 } 03789 if (p->sig & __DAHDI_SIG_FXS) { 03790 dahdi_enable_ec(p); 03791 dahdi_train_ec(p); 03792 } 03793 break; 03794 #ifdef HAVE_PRI 03795 case SIG_BRI: 03796 case SIG_BRI_PTMP: 03797 case SIG_PRI: 03798 /* Send a pri acknowledge */ 03799 if (!pri_grab(p, p->pri)) { 03800 p->proceeding = 1; 03801 p->dialing = 0; 03802 res = pri_answer(p->pri->pri, p->call, 0, !p->digital); 03803 pri_rel(p->pri); 03804 } else { 03805 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 03806 res = -1; 03807 } 03808 break; 03809 #endif 03810 #ifdef HAVE_SS7 03811 case SIG_SS7: 03812 if (!ss7_grab(p, p->ss7)) { 03813 p->proceeding = 1; 03814 res = isup_anm(p->ss7->ss7, p->ss7call); 03815 ss7_rel(p->ss7); 03816 } else { 03817 ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span); 03818 res = -1; 03819 } 03820 break; 03821 #endif 03822 case 0: 03823 ast_mutex_unlock(&p->lock); 03824 return 0; 03825 default: 03826 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel); 03827 res = -1; 03828 } 03829 ast_mutex_unlock(&p->lock); 03830 return res; 03831 }
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 4145 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_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_read(), AST_STATE_RINGING, ast_verb, ast_waitfor_n(), ast_write(), dahdi_pvt::call, dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_link(), dahdi_unlink(), dahdi_subchannel::dfd, disable_dtmf_detect(), dahdi_pvt::echocanbridged, enable_dtmf_detect(), f, ast_channel::fds, dahdi_subchannel::inthreeway, dahdi_pvt::lock, LOG_NOTICE, master, ast_channel::name, 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, and update_conf().
04146 { 04147 struct ast_channel *who; 04148 struct dahdi_pvt *p0, *p1, *op0, *op1; 04149 struct dahdi_pvt *master = NULL, *slave = NULL; 04150 struct ast_frame *f; 04151 int inconf = 0; 04152 int nothingok = 1; 04153 int ofd0, ofd1; 04154 int oi0, oi1, i0 = -1, i1 = -1, t0, t1; 04155 int os0 = -1, os1 = -1; 04156 int priority = 0; 04157 struct ast_channel *oc0, *oc1; 04158 enum ast_bridge_result res; 04159 04160 #ifdef PRI_2BCT 04161 int triedtopribridge = 0; 04162 q931_call *q931c0 = NULL, *q931c1 = NULL; 04163 #endif 04164 04165 /* For now, don't attempt to native bridge if either channel needs DTMF detection. 04166 There is code below to handle it properly until DTMF is actually seen, 04167 but due to currently unresolved issues it's ignored... 04168 */ 04169 04170 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 04171 return AST_BRIDGE_FAILED_NOWARN; 04172 04173 ast_channel_lock(c0); 04174 while (ast_channel_trylock(c1)) { 04175 ast_channel_unlock(c0); 04176 usleep(1); 04177 ast_channel_lock(c0); 04178 } 04179 04180 p0 = c0->tech_pvt; 04181 p1 = c1->tech_pvt; 04182 /* cant do pseudo-channels here */ 04183 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) { 04184 ast_channel_unlock(c0); 04185 ast_channel_unlock(c1); 04186 return AST_BRIDGE_FAILED_NOWARN; 04187 } 04188 04189 oi0 = dahdi_get_index(c0, p0, 0); 04190 oi1 = dahdi_get_index(c1, p1, 0); 04191 if ((oi0 < 0) || (oi1 < 0)) { 04192 ast_channel_unlock(c0); 04193 ast_channel_unlock(c1); 04194 return AST_BRIDGE_FAILED; 04195 } 04196 04197 op0 = p0 = c0->tech_pvt; 04198 op1 = p1 = c1->tech_pvt; 04199 ofd0 = c0->fds[0]; 04200 ofd1 = c1->fds[0]; 04201 oc0 = p0->owner; 04202 oc1 = p1->owner; 04203 04204 if (ast_mutex_trylock(&p0->lock)) { 04205 /* Don't block, due to potential for deadlock */ 04206 ast_channel_unlock(c0); 04207 ast_channel_unlock(c1); 04208 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 04209 return AST_BRIDGE_RETRY; 04210 } 04211 if (ast_mutex_trylock(&p1->lock)) { 04212 /* Don't block, due to potential for deadlock */ 04213 ast_mutex_unlock(&p0->lock); 04214 ast_channel_unlock(c0); 04215 ast_channel_unlock(c1); 04216 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 04217 return AST_BRIDGE_RETRY; 04218 } 04219 04220 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 04221 if (p0->owner && p1->owner) { 04222 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */ 04223 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) { 04224 master = p0; 04225 slave = p1; 04226 inconf = 1; 04227 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) { 04228 master = p1; 04229 slave = p0; 04230 inconf = 1; 04231 } else { 04232 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n"); 04233 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n", 04234 p0->channel, 04235 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 04236 p0->subs[SUB_REAL].inthreeway, p0->channel, 04237 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 04238 p1->subs[SUB_REAL].inthreeway); 04239 } 04240 nothingok = 0; 04241 } 04242 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) { 04243 if (p1->subs[SUB_THREEWAY].inthreeway) { 04244 master = p1; 04245 slave = p0; 04246 nothingok = 0; 04247 } 04248 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) { 04249 if (p0->subs[SUB_THREEWAY].inthreeway) { 04250 master = p0; 04251 slave = p1; 04252 nothingok = 0; 04253 } 04254 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) { 04255 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise, 04256 don't put us in anything */ 04257 if (p1->subs[SUB_CALLWAIT].inthreeway) { 04258 master = p1; 04259 slave = p0; 04260 nothingok = 0; 04261 } 04262 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) { 04263 /* Same as previous */ 04264 if (p0->subs[SUB_CALLWAIT].inthreeway) { 04265 master = p0; 04266 slave = p1; 04267 nothingok = 0; 04268 } 04269 } 04270 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n", 04271 master ? master->channel : 0, slave ? slave->channel : 0, nothingok); 04272 if (master && slave) { 04273 /* Stop any tones, or play ringtone as appropriate. If they're bridged 04274 in an active threeway call with a channel that is ringing, we should 04275 indicate ringing. */ 04276 if ((oi1 == SUB_THREEWAY) && 04277 p1->subs[SUB_THREEWAY].inthreeway && 04278 p1->subs[SUB_REAL].owner && 04279 p1->subs[SUB_REAL].inthreeway && 04280 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 04281 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name); 04282 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE); 04283 os1 = p1->subs[SUB_REAL].owner->_state; 04284 } else { 04285 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1); 04286 tone_zone_play_tone(p0->subs[oi0].dfd, -1); 04287 } 04288 if ((oi0 == SUB_THREEWAY) && 04289 p0->subs[SUB_THREEWAY].inthreeway && 04290 p0->subs[SUB_REAL].owner && 04291 p0->subs[SUB_REAL].inthreeway && 04292 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 04293 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name); 04294 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE); 04295 os0 = p0->subs[SUB_REAL].owner->_state; 04296 } else { 04297 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0); 04298 tone_zone_play_tone(p1->subs[oi0].dfd, -1); 04299 } 04300 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 04301 if (!p0->echocanbridged || !p1->echocanbridged) { 04302 /* Disable echo cancellation if appropriate */ 04303 dahdi_disable_ec(p0); 04304 dahdi_disable_ec(p1); 04305 } 04306 } 04307 dahdi_link(slave, master); 04308 master->inconference = inconf; 04309 } else if (!nothingok) 04310 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]); 04311 04312 update_conf(p0); 04313 update_conf(p1); 04314 t0 = p0->subs[SUB_REAL].inthreeway; 04315 t1 = p1->subs[SUB_REAL].inthreeway; 04316 04317 ast_mutex_unlock(&p0->lock); 04318 ast_mutex_unlock(&p1->lock); 04319 04320 ast_channel_unlock(c0); 04321 ast_channel_unlock(c1); 04322 04323 /* Native bridge failed */ 04324 if ((!master || !slave) && !nothingok) { 04325 dahdi_enable_ec(p0); 04326 dahdi_enable_ec(p1); 04327 return AST_BRIDGE_FAILED; 04328 } 04329 04330 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name); 04331 04332 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 04333 disable_dtmf_detect(op0); 04334 04335 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 04336 disable_dtmf_detect(op1); 04337 04338 for (;;) { 04339 struct ast_channel *c0_priority[2] = {c0, c1}; 04340 struct ast_channel *c1_priority[2] = {c1, c0}; 04341 04342 /* Here's our main loop... Start by locking things, looking for private parts, 04343 and then balking if anything is wrong */ 04344 04345 ast_channel_lock(c0); 04346 while (ast_channel_trylock(c1)) { 04347 ast_channel_unlock(c0); 04348 usleep(1); 04349 ast_channel_lock(c0); 04350 } 04351 04352 p0 = c0->tech_pvt; 04353 p1 = c1->tech_pvt; 04354 04355 if (op0 == p0) 04356 i0 = dahdi_get_index(c0, p0, 1); 04357 if (op1 == p1) 04358 i1 = dahdi_get_index(c1, p1, 1); 04359 04360 ast_channel_unlock(c0); 04361 ast_channel_unlock(c1); 04362 04363 if (!timeoutms || 04364 (op0 != p0) || 04365 (op1 != p1) || 04366 (ofd0 != c0->fds[0]) || 04367 (ofd1 != c1->fds[0]) || 04368 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 04369 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 04370 (oc0 != p0->owner) || 04371 (oc1 != p1->owner) || 04372 (t0 != p0->subs[SUB_REAL].inthreeway) || 04373 (t1 != p1->subs[SUB_REAL].inthreeway) || 04374 (oi0 != i0) || 04375 (oi1 != i1)) { 04376 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n", 04377 op0->channel, oi0, op1->channel, oi1); 04378 res = AST_BRIDGE_RETRY; 04379 goto return_from_bridge; 04380 } 04381 04382 #ifdef PRI_2BCT 04383 q931c0 = p0->call; 04384 q931c1 = p1->call; 04385 if (p0->transfer && p1->transfer 04386 && q931c0 && q931c1 04387 && !triedtopribridge) { 04388 pri_channel_bridge(q931c0, q931c1); 04389 triedtopribridge = 1; 04390 } 04391 #endif 04392 04393 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms); 04394 if (!who) { 04395 ast_debug(1, "Ooh, empty read...\n"); 04396 continue; 04397 } 04398 f = ast_read(who); 04399 if (!f || (f->frametype == AST_FRAME_CONTROL)) { 04400 *fo = f; 04401 *rc = who; 04402 res = AST_BRIDGE_COMPLETE; 04403 goto return_from_bridge; 04404 } 04405 if (f->frametype == AST_FRAME_DTMF) { 04406 if ((who == c0) && p0->pulsedial) { 04407 ast_write(c1, f); 04408 } else if ((who == c1) && p1->pulsedial) { 04409 ast_write(c0, f); 04410 } else { 04411 *fo = f; 04412 *rc = who; 04413 res = AST_BRIDGE_COMPLETE; 04414 goto return_from_bridge; 04415 } 04416 } 04417 ast_frfree(f); 04418 04419 /* Swap who gets priority */ 04420 priority = !priority; 04421 } 04422 04423 return_from_bridge: 04424 if (op0 == p0) 04425 dahdi_enable_ec(p0); 04426 04427 if (op1 == p1) 04428 dahdi_enable_ec(p1); 04429 04430 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 04431 enable_dtmf_detect(op0); 04432 04433 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 04434 enable_dtmf_detect(op1); 04435 04436 dahdi_unlink(slave, master, 1); 04437 04438 return res; 04439 }
static int dahdi_call | ( | struct ast_channel * | ast, | |
char * | rdest, | |||
int | timeout | |||
) | [static] |
Definition at line 2448 of file chan_dahdi.c.
References ast_channel::_state, ast_callerid_generate(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_debug, ast_free, 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_verb, 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_ani2, 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, 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_ERROR, 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, 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_BRI, SIG_BRI_PTMP, 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, SIG_SS7, 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, and dahdi_pvt::whichwink.
02449 { 02450 struct dahdi_pvt *p = ast->tech_pvt; 02451 int x, res, index,mysig; 02452 char *c, *n, *l; 02453 #ifdef HAVE_PRI 02454 char *s = NULL; 02455 #endif 02456 char dest[256]; /* must be same length as p->dialdest */ 02457 ast_mutex_lock(&p->lock); 02458 ast_copy_string(dest, rdest, sizeof(dest)); 02459 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest)); 02460 if ((ast->_state == AST_STATE_BUSY)) { 02461 p->subs[SUB_REAL].needbusy = 1; 02462 ast_mutex_unlock(&p->lock); 02463 return 0; 02464 } 02465 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 02466 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name); 02467 ast_mutex_unlock(&p->lock); 02468 return -1; 02469 } 02470 p->dialednone = 0; 02471 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ 02472 { 02473 /* Special pseudo -- automatically up */ 02474 ast_setstate(ast, AST_STATE_UP); 02475 ast_mutex_unlock(&p->lock); 02476 return 0; 02477 } 02478 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE; 02479 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 02480 if (res) 02481 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno)); 02482 p->outgoing = 1; 02483 02484 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02485 02486 mysig = p->sig; 02487 if (p->outsigmod > -1) 02488 mysig = p->outsigmod; 02489 02490 switch (mysig) { 02491 case SIG_FXOLS: 02492 case SIG_FXOGS: 02493 case SIG_FXOKS: 02494 if (p->owner == ast) { 02495 /* Normal ring, on hook */ 02496 02497 /* Don't send audio while on hook, until the call is answered */ 02498 p->dialing = 1; 02499 if (p->use_callerid) { 02500 /* Generate the Caller-ID spill if desired */ 02501 if (p->cidspill) { 02502 ast_log(LOG_WARNING, "cidspill already exists??\n"); 02503 ast_free(p->cidspill); 02504 } 02505 p->callwaitcas = 0; 02506 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) { 02507 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p)); 02508 p->cidpos = 0; 02509 send_callerid(p); 02510 } 02511 } 02512 /* Choose proper cadence */ 02513 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { 02514 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) 02515 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); 02516 p->cidrings = cidrings[p->distinctivering - 1]; 02517 } else { 02518 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) 02519 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); 02520 p->cidrings = p->sendcalleridafter; 02521 } 02522 02523 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */ 02524 c = strchr(dest, '/'); 02525 if (c) 02526 c++; 02527 if (c && (strlen(c) < p->stripmsd)) { 02528 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02529 c = NULL; 02530 } 02531 if (c) { 02532 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02533 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c); 02534 ast_debug(1, "FXO: setup deferred dialstring: %s\n", c); 02535 } else { 02536 p->dop.dialstr[0] = '\0'; 02537 } 02538 x = DAHDI_RING; 02539 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) { 02540 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno)); 02541 ast_mutex_unlock(&p->lock); 02542 return -1; 02543 } 02544 p->dialing = 1; 02545 } else { 02546 /* Call waiting call */ 02547 p->callwaitrings = 0; 02548 if (ast->cid.cid_num) 02549 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num)); 02550 else 02551 p->callwait_num[0] = '\0'; 02552 if (ast->cid.cid_name) 02553 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name)); 02554 else 02555 p->callwait_name[0] = '\0'; 02556 /* Call waiting tone instead */ 02557 if (dahdi_callwait(ast)) { 02558 ast_mutex_unlock(&p->lock); 02559 return -1; 02560 } 02561 /* Make ring-back */ 02562 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE)) 02563 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name); 02564 02565 } 02566 n = ast->cid.cid_name; 02567 l = ast->cid.cid_num; 02568 if (l) 02569 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num)); 02570 else 02571 p->lastcid_num[0] = '\0'; 02572 if (n) 02573 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name)); 02574 else 02575 p->lastcid_name[0] = '\0'; 02576 ast_setstate(ast, AST_STATE_RINGING); 02577 index = dahdi_get_index(ast, p, 0); 02578 if (index > -1) { 02579 p->subs[index].needringing = 1; 02580 } 02581 break; 02582 case SIG_FXSLS: 02583 case SIG_FXSGS: 02584 case SIG_FXSKS: 02585 case SIG_EMWINK: 02586 case SIG_EM: 02587 case SIG_EM_E1: 02588 case SIG_FEATD: 02589 case SIG_FEATDMF: 02590 case SIG_E911: 02591 case SIG_FGC_CAMA: 02592 case SIG_FGC_CAMAMF: 02593 case SIG_FEATB: 02594 case SIG_SFWINK: 02595 case SIG_SF: 02596 case SIG_SF_FEATD: 02597 case SIG_SF_FEATDMF: 02598 case SIG_FEATDMF_TA: 02599 case SIG_SF_FEATB: 02600 c = strchr(dest, '/'); 02601 if (c) 02602 c++; 02603 else 02604 c = ""; 02605 if (strlen(c) < p->stripmsd) { 02606 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02607 ast_mutex_unlock(&p->lock); 02608 return -1; 02609 } 02610 #ifdef HAVE_PRI 02611 /* Start the trunk, if not GR-303 */ 02612 if (!p->pri) { 02613 #endif 02614 x = DAHDI_START; 02615 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02616 if (res < 0) { 02617 if (errno != EINPROGRESS) { 02618 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 02619 ast_mutex_unlock(&p->lock); 02620 return -1; 02621 } 02622 } 02623 #ifdef HAVE_PRI 02624 } 02625 #endif 02626 ast_debug(1, "Dialing '%s'\n", c); 02627 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02628 02629 c += p->stripmsd; 02630 02631 switch (mysig) { 02632 case SIG_FEATD: 02633 l = ast->cid.cid_num; 02634 if (l) 02635 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c); 02636 else 02637 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c); 02638 break; 02639 case SIG_FEATDMF: 02640 l = ast->cid.cid_num; 02641 if (l) 02642 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c); 02643 else 02644 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c); 02645 break; 02646 case SIG_FEATDMF_TA: 02647 { 02648 const char *cic, *ozz; 02649 02650 /* If you have to go through a Tandem Access point you need to use this */ 02651 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ"); 02652 if (!ozz) 02653 ozz = defaultozz; 02654 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC"); 02655 if (!cic) 02656 cic = defaultcic; 02657 if (!ozz || !cic) { 02658 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n"); 02659 ast_mutex_unlock(&p->lock); 02660 return -1; 02661 } 02662 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic); 02663 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c); 02664 p->whichwink = 0; 02665 } 02666 break; 02667 case SIG_E911: 02668 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr)); 02669 break; 02670 case SIG_FGC_CAMA: 02671 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c); 02672 break; 02673 case SIG_FGC_CAMAMF: 02674 case SIG_FEATB: 02675 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c); 02676 break; 02677 default: 02678 if (p->pulse) 02679 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c); 02680 else 02681 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c); 02682 break; 02683 } 02684 02685 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) { 02686 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 02687 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 02688 p->echorest[sizeof(p->echorest) - 1] = '\0'; 02689 p->echobreak = 1; 02690 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 02691 } else 02692 p->echobreak = 0; 02693 if (!res) { 02694 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 02695 int saveerr = errno; 02696 02697 x = DAHDI_ONHOOK; 02698 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02699 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 02700 ast_mutex_unlock(&p->lock); 02701 return -1; 02702 } 02703 } else 02704 ast_debug(1, "Deferring dialing...\n"); 02705 02706 p->dialing = 1; 02707 if (ast_strlen_zero(c)) 02708 p->dialednone = 1; 02709 ast_setstate(ast, AST_STATE_DIALING); 02710 break; 02711 case 0: 02712 /* Special pseudo -- automatically up*/ 02713 ast_setstate(ast, AST_STATE_UP); 02714 break; 02715 case SIG_PRI: 02716 case SIG_BRI: 02717 case SIG_BRI_PTMP: 02718 case SIG_SS7: 02719 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */ 02720 p->dialdest[0] = '\0'; 02721 p->dialing = 1; 02722 break; 02723 default: 02724 ast_debug(1, "not yet implemented\n"); 02725 ast_mutex_unlock(&p->lock); 02726 return -1; 02727 } 02728 #ifdef HAVE_SS7 02729 if (p->ss7) { 02730 char ss7_called_nai; 02731 int called_nai_strip; 02732 char ss7_calling_nai; 02733 int calling_nai_strip; 02734 const char *charge_str = NULL; 02735 const char *gen_address = NULL; 02736 const char *gen_digits = NULL; 02737 const char *gen_dig_type = NULL; 02738 const char *gen_dig_scheme = NULL; 02739 const char *gen_name = NULL; 02740 const char *jip_digits = NULL; 02741 const char *lspi_ident = NULL; 02742 const char *rlt_flag = NULL; 02743 const char *call_ref_id = NULL; 02744 const char *call_ref_pc = NULL; 02745 const char *send_far = NULL; 02746 02747 c = strchr(dest, '/'); 02748 if (c) { 02749 c++; 02750 } else { 02751 c = ""; 02752 } 02753 if (strlen(c) < p->stripmsd) { 02754 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02755 ast_mutex_unlock(&p->lock); 02756 return -1; 02757 } 02758 02759 if (!p->hidecallerid) { 02760 l = ast->cid.cid_num; 02761 } else { 02762 l = NULL; 02763 } 02764 02765 if (ss7_grab(p, p->ss7)) { 02766 ast_log(LOG_WARNING, "Failed to grab SS7!\n"); 02767 ast_mutex_unlock(&p->lock); 02768 return -1; 02769 } 02770 p->digital = IS_DIGITAL(ast->transfercapability); 02771 p->ss7call = isup_new_call(p->ss7->ss7); 02772 02773 if (!p->ss7call) { 02774 ss7_rel(p->ss7); 02775 ast_mutex_unlock(&p->lock); 02776 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n"); 02777 return -1; 02778 } 02779 02780 called_nai_strip = 0; 02781 ss7_called_nai = p->ss7->called_nai; 02782 if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */ 02783 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) { 02784 called_nai_strip = strlen(p->ss7->internationalprefix); 02785 ss7_called_nai = SS7_NAI_INTERNATIONAL; 02786 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) { 02787 called_nai_strip = strlen(p->ss7->nationalprefix); 02788 ss7_called_nai = SS7_NAI_NATIONAL; 02789 } else { 02790 ss7_called_nai = SS7_NAI_SUBSCRIBER; 02791 } 02792 } 02793 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7); 02794 02795 calling_nai_strip = 0; 02796 ss7_calling_nai = p->ss7->calling_nai; 02797 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */ 02798 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) { 02799 calling_nai_strip = strlen(p->ss7->internationalprefix); 02800 ss7_calling_nai = SS7_NAI_INTERNATIONAL; 02801 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) { 02802 calling_nai_strip = strlen(p->ss7->nationalprefix); 02803 ss7_calling_nai = SS7_NAI_NATIONAL; 02804 } else { 02805 ss7_calling_nai = SS7_NAI_SUBSCRIBER; 02806 } 02807 } 02808 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai, 02809 p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED), 02810 p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED ); 02811 02812 isup_set_oli(p->ss7call, ast->cid.cid_ani2); 02813 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc); 02814 02815 ast_channel_lock(ast); 02816 /* Set the charge number if it is set */ 02817 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER"); 02818 if (charge_str) 02819 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10); 02820 02821 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS"); 02822 if (gen_address) 02823 isup_set_gen_address(p->ss7call, gen_address, p->gen_add_nai,p->gen_add_pres_ind, p->gen_add_num_plan,p->gen_add_type); /* need to add some types here for NAI,PRES,TYPE */ 02824 02825 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS"); 02826 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE"); 02827 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME"); 02828 if (gen_digits) 02829 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme)); 02830 02831 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME"); 02832 if (gen_name) 02833 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED); 02834 02835 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP"); 02836 if (jip_digits) 02837 isup_set_jip_digits(p->ss7call, jip_digits); 02838 02839 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT"); 02840 if (lspi_ident) 02841 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00); 02842 02843 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON"); 02844 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) { 02845 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */ 02846 } 02847 02848 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT"); 02849 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC"); 02850 if (call_ref_id && call_ref_pc) { 02851 isup_set_callref(p->ss7call, atoi(call_ref_id), 02852 call_ref_pc ? atoi(call_ref_pc) : 0); 02853 } 02854 02855 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR"); 02856 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 )) 02857 (isup_far(p->ss7->ss7, p->ss7call)); 02858 02859 ast_channel_unlock(ast); 02860 02861 isup_iam(p->ss7->ss7, p->ss7call); 02862 ast_setstate(ast, AST_STATE_DIALING); 02863 ss7_rel(p->ss7); 02864 } 02865 #endif /* HAVE_SS7 */ 02866 #ifdef HAVE_PRI 02867 if (p->pri) { 02868 struct pri_sr *sr; 02869 #ifdef SUPPORT_USERUSER 02870 const char *useruser; 02871 #endif 02872 int pridialplan; 02873 int dp_strip; 02874 int prilocaldialplan; 02875 int ldp_strip; 02876 int exclusive; 02877 const char *rr_str; 02878 int redirect_reason; 02879 02880 c = strchr(dest, '/'); 02881 if (c) { 02882 c++; 02883 } else { 02884 c = ""; 02885 } 02886 02887 l = NULL; 02888 n = NULL; 02889 if (!p->hidecallerid) { 02890 l = ast->cid.cid_num; 02891 if (!p->hidecalleridname) { 02892 n = ast->cid.cid_name; 02893 } 02894 } 02895 02896 if (strlen(c) < p->stripmsd) { 02897 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02898 ast_mutex_unlock(&p->lock); 02899 return -1; 02900 } 02901 if (mysig != SIG_FXSKS) { 02902 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02903 s = strchr(c + p->stripmsd, 'w'); 02904 if (s) { 02905 if (strlen(s) > 1) 02906 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s); 02907 else 02908 p->dop.dialstr[0] = '\0'; 02909 *s = '\0'; 02910 } else { 02911 p->dop.dialstr[0] = '\0'; 02912 } 02913 } 02914 if (pri_grab(p, p->pri)) { 02915 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 02916 ast_mutex_unlock(&p->lock); 02917 return -1; 02918 } 02919 if (!(p->call = pri_new_call(p->pri->pri))) { 02920 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel); 02921 pri_rel(p->pri); 02922 ast_mutex_unlock(&p->lock); 02923 return -1; 02924 } 02925 if (!(sr = pri_sr_new())) { 02926 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel); 02927 pri_rel(p->pri); 02928 ast_mutex_unlock(&p->lock); 02929 } 02930 if (p->bearer || (mysig == SIG_FXSKS)) { 02931 if (p->bearer) { 02932 ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel); 02933 p->bearer->call = p->call; 02934 } else 02935 ast_debug(1, "I'm being setup with no bearer right now...\n"); 02936 02937 pri_set_crv(p->pri->pri, p->call, p->channel, 0); 02938 } 02939 p->digital = IS_DIGITAL(ast->transfercapability); 02940 /* Add support for exclusive override */ 02941 if (p->priexclusive) 02942 exclusive = 1; 02943 else { 02944 /* otherwise, traditional behavior */ 02945 if (p->pri->nodetype == PRI_NETWORK) 02946 exclusive = 0; 02947 else 02948 exclusive = 1; 02949 } 02950 02951 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1); 02952 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 02953 (p->digital ? -1 : 02954 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW))); 02955 if (p->pri->facilityenable) 02956 pri_facility_enable(p->pri->pri); 02957 02958 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability)); 02959 dp_strip = 0; 02960 pridialplan = p->pri->dialplan - 1; 02961 if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */ 02962 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 02963 if (pridialplan == -2) { 02964 dp_strip = strlen(p->pri->internationalprefix); 02965 } 02966 pridialplan = PRI_INTERNATIONAL_ISDN; 02967 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 02968 if (pridialplan == -2) { 02969 dp_strip = strlen(p->pri->nationalprefix); 02970 } 02971 pridialplan = PRI_NATIONAL_ISDN; 02972 } else { 02973 pridialplan = PRI_LOCAL_ISDN; 02974 } 02975 } 02976 while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') { 02977 switch (c[p->stripmsd]) { 02978 case 'U': 02979 pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf); 02980 break; 02981 case 'I': 02982 pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf); 02983 break; 02984 case 'N': 02985 pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf); 02986 break; 02987 case 'L': 02988 pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf); 02989 break; 02990 case 'S': 02991 pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf); 02992 break; 02993 case 'V': 02994 pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf); 02995 break; 02996 case 'R': 02997 pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf); 02998 break; 02999 case 'u': 03000 pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0); 03001 break; 03002 case 'e': 03003 pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0); 03004 break; 03005 case 'x': 03006 pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0); 03007 break; 03008 case 'f': 03009 pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0); 03010 break; 03011 case 'n': 03012 pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0); 03013 break; 03014 case 'p': 03015 pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0); 03016 break; 03017 case 'r': 03018 pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0); 03019 break; 03020 default: 03021 if (isalpha(c[p->stripmsd])) { 03022 ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n", 03023 c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]); 03024 } 03025 break; 03026 } 03027 c++; 03028 } 03029 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0); 03030 03031 ldp_strip = 0; 03032 prilocaldialplan = p->pri->localdialplan - 1; 03033 if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */ 03034 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 03035 if (prilocaldialplan == -2) { 03036 ldp_strip = strlen(p->pri->internationalprefix); 03037 } 03038 prilocaldialplan = PRI_INTERNATIONAL_ISDN; 03039 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 03040 if (prilocaldialplan == -2) { 03041 ldp_strip = strlen(p->pri->nationalprefix); 03042 } 03043 prilocaldialplan = PRI_NATIONAL_ISDN; 03044 } else { 03045 prilocaldialplan = PRI_LOCAL_ISDN; 03046 } 03047 } 03048 if (l != NULL) { 03049 while (*l > '9' && *l != '*' && *l != '#') { 03050 switch (*l) { 03051 case 'U': 03052 prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf); 03053 break; 03054 case 'I': 03055 prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf); 03056 break; 03057 case 'N': 03058 prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf); 03059 break; 03060 case 'L': 03061 prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf); 03062 break; 03063 case 'S': 03064 prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf); 03065 break; 03066 case 'V': 03067 prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf); 03068 break; 03069 case 'R': 03070 prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf); 03071 break; 03072 case 'u': 03073 prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0); 03074 break; 03075 case 'e': 03076 prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0); 03077 break; 03078 case 'x': 03079 prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0); 03080 break; 03081 case 'f': 03082 prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0); 03083 break; 03084 case 'n': 03085 prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0); 03086 break; 03087 case 'p': 03088 prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0); 03089 break; 03090 case 'r': 03091 prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0); 03092 break; 03093 default: 03094 if (isalpha(*l)) { 03095 ast_log(LOG_WARNING, 03096 "Unrecognized prilocaldialplan %s modifier: %c\n", 03097 *l > 'Z' ? "NPI" : "TON", *l); 03098 } 03099 break; 03100 } 03101 l++; 03102 } 03103 } 03104 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan, 03105 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE)); 03106 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) { 03107 if (!strcasecmp(rr_str, "UNKNOWN")) 03108 redirect_reason = 0; 03109 else if (!strcasecmp(rr_str, "BUSY")) 03110 redirect_reason = 1; 03111 else if (!strcasecmp(rr_str, "NO_REPLY")) 03112 redirect_reason = 2; 03113 else if (!strcasecmp(rr_str, "UNCONDITIONAL")) 03114 redirect_reason = 15; 03115 else 03116 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03117 } else 03118 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03119 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason); 03120 03121 #ifdef SUPPORT_USERUSER 03122 /* User-user info */ 03123 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO"); 03124 03125 if (useruser) 03126 pri_sr_set_useruser(sr, useruser); 03127 #endif 03128 03129 if (pri_setup(p->pri->pri, p->call, sr)) { 03130 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 03131 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan)); 03132 pri_rel(p->pri); 03133 ast_mutex_unlock(&p->lock); 03134 pri_sr_free(sr); 03135 return -1; 03136 } 03137 pri_sr_free(sr); 03138 ast_setstate(ast, AST_STATE_DIALING); 03139 pri_rel(p->pri); 03140 } 03141 #endif 03142 ast_mutex_unlock(&p->lock); 03143 return 0; 03144 }
static int dahdi_callwait | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 2408 of file chan_dahdi.c.
References ast_free, 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, LOG_WARNING, READ_SIZE, save_conference(), send_callerid(), and ast_channel::tech_pvt.
Referenced by dahdi_call(), and dahdi_read().
02409 { 02410 struct dahdi_pvt *p = ast->tech_pvt; 02411 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 02412 if (p->cidspill) { 02413 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 02414 ast_free(p->cidspill); 02415 } 02416 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 02417 return -1; 02418 save_conference(p); 02419 /* Silence */ 02420 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 02421 if (!p->callwaitrings && p->callwaitingcallerid) { 02422 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 02423 p->callwaitcas = 1; 02424 p->cidlen = 2400 + 680 + READ_SIZE * 4; 02425 } else { 02426 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 02427 p->callwaitcas = 0; 02428 p->cidlen = 2400 + READ_SIZE * 4; 02429 } 02430 p->cidpos = 0; 02431 send_callerid(p); 02432 02433 return 0; 02434 }
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 1091 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().
01091 { 01092 /* recall that if a field is not included here it is initialized 01093 * to 0 or equivalent 01094 */ 01095 struct dahdi_chan_conf conf = { 01096 #ifdef HAVE_PRI 01097 .pri = { 01098 .nsf = PRI_NSF_NONE, 01099 .switchtype = PRI_SWITCH_NI2, 01100 .dialplan = PRI_NATIONAL_ISDN + 1, 01101 .localdialplan = PRI_NATIONAL_ISDN + 1, 01102 .nodetype = PRI_CPE, 01103 01104 .minunused = 2, 01105 .idleext = "", 01106 .idledial = "", 01107 .internationalprefix = "", 01108 .nationalprefix = "", 01109 .localprefix = "", 01110 .privateprefix = "", 01111 .unknownprefix = "", 01112 .resetinterval = -1, 01113 }, 01114 #endif 01115 #ifdef HAVE_SS7 01116 .ss7 = { 01117 .called_nai = SS7_NAI_NATIONAL, 01118 .calling_nai = SS7_NAI_NATIONAL, 01119 .internationalprefix = "", 01120 .nationalprefix = "", 01121 .subscriberprefix = "", 01122 .unknownprefix = "" 01123 }, 01124 #endif 01125 .chan = { 01126 .context = "default", 01127 .cid_num = "", 01128 .cid_name = "", 01129 .mohinterpret = "default", 01130 .mohsuggest = "", 01131 .transfertobusy = 1, 01132 01133 .cid_signalling = CID_SIG_BELL, 01134 .cid_start = CID_START_RING, 01135 .dahditrcallerid = 0, 01136 .use_callerid = 1, 01137 .sig = -1, 01138 .outsigmod = -1, 01139 01140 .cid_rxgain = +5.0, 01141 01142 .tonezone = -1, 01143 01144 .echocancel.head.tap_length = 1, 01145 01146 .busycount = 3, 01147 .busycompare = 0, 01148 .busytonelength = 0, 01149 .busyquietlength = 0, 01150 .busyfuzziness = 0, 01151 .silencethreshold = 0, 01152 01153 .accountcode = "", 01154 01155 .mailbox = "", 01156 01157 01158 .polarityonanswerdelay = 600, 01159 01160 .sendcalleridafter = DEFAULT_CIDRINGS, 01161 01162 .buf_policy = DAHDI_POLICY_IMMEDIATE, 01163 .buf_no = numbufs 01164 }, 01165 .timing = { 01166 .prewinktime = -1, 01167 .preflashtime = -1, 01168 .winktime = -1, 01169 .flashtime = -1, 01170 .starttime = -1, 01171 .rxwinktime = -1, 01172 .rxflashtime = -1, 01173 .debouncetime = -1 01174 }, 01175 .is_sig_auto = 1, 01176 .smdi_port = "/dev/ttyS0", 01177 }; 01178 01179 return conf; 01180 }
static void dahdi_close | ( | int | fd | ) | [static] |
Definition at line 1484 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 1497 of file chan_dahdi.c.
References dahdi_close(), and dahdi_pri::fds.
Referenced by __unload_module(), dahdi_restart(), and start_pri().
01498 { 01499 dahdi_close(pri->fds[fd_num]); 01500 pri->fds[fd_num] = -1; 01501 }
static void dahdi_close_sub | ( | struct dahdi_pvt * | chan_pvt, | |
int | sub_num | |||
) | [static] |
Definition at line 1490 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().
01491 { 01492 dahdi_close(chan_pvt->subs[sub_num].dfd); 01493 chan_pvt->subs[sub_num].dfd = -1; 01494 }
static int dahdi_confmute | ( | struct dahdi_pvt * | p, | |
int | muted | |||
) | [inline, static] |
Definition at line 2225 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, errno, LOG_WARNING, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_PRI, SIG_SS7, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_handle_dtmfup(), dahdi_handle_event(), dahdi_hangup(), and dahdi_new().
02226 { 02227 int x, y, res; 02228 x = muted; 02229 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 02230 y = 1; 02231 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y); 02232 if (res) 02233 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno)); 02234 } 02235 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x); 02236 if (res < 0) 02237 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno)); 02238 return res; 02239 }
static char* dahdi_destroy_channel | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12222 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_destroy_channel_bynum(), RESULT_SUCCESS, and ast_cli_entry::usage.
12223 { 12224 int channel; 12225 int ret; 12226 switch (cmd) { 12227 case CLI_INIT: 12228 e->command = "dahdi destroy channel"; 12229 e->usage = 12230 "Usage: dahdi destroy channel <chan num>\n" 12231 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n"; 12232 return NULL; 12233 case CLI_GENERATE: 12234 return NULL; 12235 } 12236 if (a->argc != 4) 12237 return CLI_SHOWUSAGE; 12238 12239 channel = atoi(a->argv[3]); 12240 ret = dahdi_destroy_channel_bynum(channel); 12241 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE; 12242 }
static int dahdi_destroy_channel_bynum | ( | int | channel | ) | [static] |
Definition at line 7863 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().
07864 { 07865 struct dahdi_pvt *tmp = NULL; 07866 struct dahdi_pvt *prev = NULL; 07867 07868 tmp = iflist; 07869 while (tmp) { 07870 if (tmp->channel == channel) { 07871 int x = DAHDI_FLASH; 07872 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 */ 07873 destroy_channel(prev, tmp, 1); 07874 ast_module_unref(ast_module_info->self); 07875 return RESULT_SUCCESS; 07876 } 07877 prev = tmp; 07878 tmp = tmp->next; 07879 } 07880 return RESULT_FAILURE; 07881 }
static int dahdi_digit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 1592 of file chan_dahdi.c.
References ast_channel::_state, ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DIALING, dahdi_pvt::begindigit, dahdi_pvt::call, chan, dahdi_get_index(), dahdi_pvt::dialdest, dahdi_pvt::dialing, digit_to_dtmfindex(), errno, dahdi_pvt::lock, 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_BRI, SIG_BRI_PTMP, SIG_PRI, dahdi_pvt::span, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
01593 { 01594 struct dahdi_pvt *pvt; 01595 int index; 01596 int dtmf = -1; 01597 01598 pvt = chan->tech_pvt; 01599 01600 ast_mutex_lock(&pvt->lock); 01601 01602 index = dahdi_get_index(chan, pvt, 0); 01603 01604 if ((index != SUB_REAL) || !pvt->owner) 01605 goto out; 01606 01607 #ifdef HAVE_PRI 01608 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP)) 01609 && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) { 01610 if (pvt->setup_ack) { 01611 if (!pri_grab(pvt, pvt->pri)) { 01612 pri_information(pvt->pri->pri, pvt->call, digit); 01613 pri_rel(pvt->pri); 01614 } else 01615 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span); 01616 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) { 01617 int res; 01618 ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit); 01619 res = strlen(pvt->dialdest); 01620 pvt->dialdest[res++] = digit; 01621 pvt->dialdest[res] = '\0'; 01622 } 01623 goto out; 01624 } 01625 #endif 01626 if ((dtmf = digit_to_dtmfindex(digit)) == -1) 01627 goto out; 01628 01629 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) { 01630 int res; 01631 struct dahdi_dialoperation zo = { 01632 .op = DAHDI_DIAL_OP_APPEND, 01633 }; 01634 01635 zo.dialstr[0] = 'T'; 01636 zo.dialstr[1] = digit; 01637 zo.dialstr[2] = '\0'; 01638 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo))) 01639 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno)); 01640 else 01641 pvt->dialing = 1; 01642 } else { 01643 ast_debug(1, "Started VLDTMF digit '%c'\n", digit); 01644 pvt->dialing = 1; 01645 pvt->begindigit = digit; 01646 } 01647 01648 out: 01649 ast_mutex_unlock(&pvt->lock); 01650 01651 return 0; 01652 }
static int dahdi_digit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 1654 of file chan_dahdi.c.
References ast_debug, ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::begindigit, chan, dahdi_get_index(), dahdi_pvt::dialing, dahdi_pvt::lock, dahdi_pvt::owner, dahdi_pvt::pulse, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_PRI, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
01655 { 01656 struct dahdi_pvt *pvt; 01657 int res = 0; 01658 int index; 01659 int x; 01660 01661 pvt = chan->tech_pvt; 01662 01663 ast_mutex_lock(&pvt->lock); 01664 01665 index = dahdi_get_index(chan, pvt, 0); 01666 01667 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse) 01668 goto out; 01669 01670 #ifdef HAVE_PRI 01671 /* This means that the digit was already sent via PRI signalling */ 01672 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP)) 01673 && !pvt->begindigit) 01674 goto out; 01675 #endif 01676 01677 if (pvt->begindigit) { 01678 x = -1; 01679 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit); 01680 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x); 01681 pvt->dialing = 0; 01682 pvt->begindigit = 0; 01683 } 01684 01685 out: 01686 ast_mutex_unlock(&pvt->lock); 01687 01688 return res; 01689 }
static void dahdi_disable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2054 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_pvt::echocanon, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), dahdi_bridge(), dahdi_handle_event(), dahdi_hangup(), dahdi_setoption(), and handle_init_event().
02055 { 02056 int res; 02057 02058 if (p->echocanon) { 02059 struct dahdi_echocanparams ecp = { .tap_length = 0 }; 02060 02061 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp); 02062 02063 if (res) 02064 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno)); 02065 else 02066 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel); 02067 } 02068 02069 p->echocanon = 0; 02070 }
static void dahdi_dnd | ( | struct dahdi_pvt * | dahdichan, | |
int | on | |||
) | [static] |
enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
dahdichan | "Physical" DAHDI channel (e.g: DAHDI/5) | |
on | 1 to enable, 0 to disable |
Definition at line 6508 of file chan_dahdi.c.
References ast_verb, dahdi_pvt::channel, dahdi_pvt::dnd, EVENT_FLAG_SYSTEM, and manager_event.
Referenced by dahdi_set_dnd(), and ss_thread().
06509 { 06510 /* Do not disturb */ 06511 dahdichan->dnd = on; 06512 ast_verb(3, "%s DND on channel %d\n", 06513 on? "Enabled" : "Disabled", 06514 dahdichan->channel); 06515 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 06516 "Channel: DAHDI/%d\r\n" 06517 "Status: %s\r\n", dahdichan->channel, 06518 on? "enabled" : "disabled"); 06519 }
static void dahdi_enable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2005 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_pvt::digital, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, dahdi_pvt::head, LOG_WARNING, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_PRI, SIG_SS7, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), dahdi_answer(), dahdi_bridge(), dahdi_handle_event(), dahdi_indicate(), dahdi_setoption(), handle_init_event(), and ss_thread().
02006 { 02007 int x; 02008 int res; 02009 if (!p) 02010 return; 02011 if (p->echocanon) { 02012 ast_debug(1, "Echo cancellation already on\n"); 02013 return; 02014 } 02015 if (p->digital) { 02016 ast_debug(1, "Echo cancellation isn't required on digital connection\n"); 02017 return; 02018 } 02019 if (p->echocancel.head.tap_length) { 02020 if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) { 02021 x = 1; 02022 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x); 02023 if (res) 02024 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno)); 02025 } 02026 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel); 02027 if (res) { 02028 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno)); 02029 } else { 02030 p->echocanon = 1; 02031 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel); 02032 } 02033 } else 02034 ast_debug(1, "No echo cancellation requested\n"); 02035 }
static struct ast_frame * dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5637 of file chan_dahdi.c.
References __dahdi_exception(), ast_mutex_lock(), ast_mutex_unlock(), f, dahdi_pvt::lock, and ast_channel::tech_pvt.
05638 { 05639 struct dahdi_pvt *p = ast->tech_pvt; 05640 struct ast_frame *f; 05641 ast_mutex_lock(&p->lock); 05642 f = __dahdi_exception(ast); 05643 ast_mutex_unlock(&p->lock); 05644 return f; 05645 }
static int dahdi_fake_event | ( | struct dahdi_pvt * | p, | |
int | mode | |||
) | [static] |
Definition at line 13105 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().
13106 { 13107 if (p) { 13108 switch (mode) { 13109 case TRANSFER: 13110 p->fake_event = DAHDI_EVENT_WINKFLASH; 13111 break; 13112 case HANGUP: 13113 p->fake_event = DAHDI_EVENT_ONHOOK; 13114 break; 13115 default: 13116 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name); 13117 } 13118 } 13119 return 0; 13120 }
static int dahdi_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 4441 of file chan_dahdi.c.
References ast_debug, ast_mutex_lock(), dahdi_pvt::channel, dahdi_unlink(), dahdi_pvt::lock, ast_channel::name, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::subs, and ast_channel::tech_pvt.
04442 { 04443 struct dahdi_pvt *p = newchan->tech_pvt; 04444 int x; 04445 ast_mutex_lock(&p->lock); 04446 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name); 04447 if (p->owner == oldchan) { 04448 p->owner = newchan; 04449 } 04450 for (x = 0; x < 3; x++) 04451 if (p->subs[x].owner == oldchan) { 04452 if (!x) 04453 dahdi_unlink(NULL, p, 0); 04454 p->subs[x].owner = newchan; 04455 } 04456 if (newchan->_state == AST_STATE_RINGING) 04457 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0); 04458 update_conf(p); 04459 ast_mutex_unlock(&p->lock); 04460 return 0; 04461 }
static int dahdi_func_read | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 4014 of file chan_dahdi.c.
References ast_copy_string(), ast_mutex_lock(), ast_mutex_unlock(), chan, dahdi_pvt::lock, dahdi_pvt::rxgain, ast_channel::tech_pvt, and dahdi_pvt::txgain.
04015 { 04016 struct dahdi_pvt *p = chan->tech_pvt; 04017 04018 if (!strcasecmp(data, "rxgain")) { 04019 ast_mutex_lock(&p->lock); 04020 snprintf(buf, len, "%f", p->rxgain); 04021 ast_mutex_unlock(&p->lock); 04022 } else if (!strcasecmp(data, "txgain")) { 04023 ast_mutex_lock(&p->lock); 04024 snprintf(buf, len, "%f", p->txgain); 04025 ast_mutex_unlock(&p->lock); 04026 } else { 04027 ast_copy_string(buf, "", len); 04028 } 04029 return 0; 04030 }
static int dahdi_get_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition at line 297 of file chan_dahdi.c.
Referenced by __dahdi_exception(), dahdi_handle_event(), mwi_thread(), and ss_thread().
00298 { 00299 int j; 00300 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) 00301 return -1; 00302 return j; 00303 }
static int dahdi_get_index | ( | struct ast_channel * | ast, | |
struct dahdi_pvt * | p, | |||
int | nullok | |||
) | [static] |
Definition at line 1298 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().
01299 { 01300 int res; 01301 if (p->subs[SUB_REAL].owner == ast) 01302 res = 0; 01303 else if (p->subs[SUB_CALLWAIT].owner == ast) 01304 res = 1; 01305 else if (p->subs[SUB_THREEWAY].owner == ast) 01306 res = 2; 01307 else { 01308 res = -1; 01309 if (!nullok) 01310 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n"); 01311 } 01312 return res; 01313 }
static void dahdi_handle_dtmfup | ( | struct ast_channel * | ast, | |
int | index, | |||
struct ast_frame ** | dest | |||
) | [static] |
Definition at line 4602 of file chan_dahdi.c.
References ast_async_goto(), ast_channel_lock, ast_channel_unlock, AST_CONTROL_ANSWER, ast_debug, ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_NULL, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verb, dahdi_pvt::callprogress, CALLPROGRESS_FAX, 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, dahdi_pvt::lock, LOG_NOTICE, ast_channel::macrocontext, ast_channel::name, pbx_builtin_setvar_helper(), S_OR, send_cwcidspill(), ast_frame::subclass, dahdi_pvt::subs, and ast_channel::tech_pvt.
Referenced by dahdi_handle_event(), and dahdi_read().
04603 { 04604 struct dahdi_pvt *p = ast->tech_pvt; 04605 struct ast_frame *f = *dest; 04606 04607 ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name); 04608 04609 if (p->confirmanswer) { 04610 ast_debug(1, "Confirm answer on %s!\n", ast->name); 04611 /* Upon receiving a DTMF digit, consider this an answer confirmation instead 04612 of a DTMF digit */ 04613 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04614 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 04615 *dest = &p->subs[index].f; 04616 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */ 04617 p->confirmanswer = 0; 04618 } else if (p->callwaitcas) { 04619 if ((f->subclass == 'A') || (f->subclass == 'D')) { 04620 ast_debug(1, "Got some DTMF, but it's for the CAS\n"); 04621 if (p->cidspill) 04622 ast_free(p->cidspill); 04623 send_cwcidspill(p); 04624 } 04625 if ((f->subclass != 'm') && (f->subclass != 'u')) 04626 p->callwaitcas = 0; 04627 p->subs[index].f.frametype = AST_FRAME_NULL; 04628 p->subs[index].f.subclass = 0; 04629 *dest = &p->subs[index].f; 04630 } else if (f->subclass == 'f') { 04631 /* Fax tone -- Handle and return NULL */ 04632 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) { 04633 p->faxhandled = 1; 04634 if (strcmp(ast->exten, "fax")) { 04635 const char *target_context = S_OR(ast->macrocontext, ast->context); 04636 04637 /* We need to unlock 'ast' here because ast_exists_extension has the 04638 * potential to start autoservice on the channel. Such action is prone 04639 * to deadlock. 04640 */ 04641 ast_mutex_unlock(&p->lock); 04642 ast_channel_unlock(ast); 04643 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) { 04644 ast_channel_lock(ast); 04645 ast_mutex_lock(&p->lock); 04646 ast_verb(3, "Redirecting %s to fax extension\n", ast->name); 04647 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 04648 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 04649 if (ast_async_goto(ast, target_context, "fax", 1)) 04650 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 04651 } else { 04652 ast_channel_lock(ast); 04653 ast_mutex_lock(&p->lock); 04654 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 04655 } 04656 } else { 04657 ast_debug(1, "Already in a fax extension, not redirecting\n"); 04658 } 04659 } else { 04660 ast_debug(1, "Fax already handled\n"); 04661 } 04662 dahdi_confmute(p, 0); 04663 p->subs[index].f.frametype = AST_FRAME_NULL; 04664 p->subs[index].f.subclass = 0; 04665 *dest = &p->subs[index].f; 04666 } else if (f->subclass == 'm') { 04667 /* Confmute request */ 04668 dahdi_confmute(p, 1); 04669 p->subs[index].f.frametype = AST_FRAME_NULL; 04670 p->subs[index].f.subclass = 0; 04671 *dest = &p->subs[index].f; 04672 } else if (f->subclass == 'u') { 04673 /* Unmute */ 04674 dahdi_confmute(p, 0); 04675 p->subs[index].f.frametype = AST_FRAME_NULL; 04676 p->subs[index].f.subclass = 0; 04677 *dest = &p->subs[index].f; 04678 } else 04679 dahdi_confmute(p, 0); 04680 }
static struct ast_frame* dahdi_handle_event | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 4693 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, alloc_sub(), dahdi_pvt::answeronpolarityswitch, ast_bridged_channel(), ast_channel_lock, ast_channel_trylock, ast_channel_unlock, 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_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_free, ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_detached, 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_verb, attempt_transfer(), dahdi_pvt::bearer, dahdi_pvt::call, CALLPROGRESS_PROGRESS, dahdi_pvt::callwaitcas, CANPROGRESSDETECT, chan, 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_get_event(), dahdi_get_index(), dahdi_handle_dtmfup(), dahdi_new(), DAHDI_OVERLAPDIAL_INCOMING, dahdi_ring_phone(), dahdi_set_hook(), dahdi_train_ec(), dahdi_pvt::dahditrcallerid, ast_frame::data, ast_frame::datalen, 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, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::inalarm, dahdi_subchannel::inthreeway, 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, 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_BRI, SIG_BRI_PTMP, 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, SIG_SS7, 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(), update_conf(), and dahdi_pvt::whichwink.
Referenced by __dahdi_exception().
04694 { 04695 int res, x; 04696 int index, mysig; 04697 char *c; 04698 struct dahdi_pvt *p = ast->tech_pvt; 04699 pthread_t threadid; 04700 struct ast_channel *chan; 04701 struct ast_frame *f; 04702 04703 index = dahdi_get_index(ast, p, 0); 04704 mysig = p->sig; 04705 if (p->outsigmod > -1) 04706 mysig = p->outsigmod; 04707 p->subs[index].f.frametype = AST_FRAME_NULL; 04708 p->subs[index].f.subclass = 0; 04709 p->subs[index].f.datalen = 0; 04710 p->subs[index].f.samples = 0; 04711 p->subs[index].f.mallocd = 0; 04712 p->subs[index].f.offset = 0; 04713 p->subs[index].f.src = "dahdi_handle_event"; 04714 p->subs[index].f.data = NULL; 04715 f = &p->subs[index].f; 04716 04717 if (index < 0) 04718 return &p->subs[index].f; 04719 if (p->fake_event) { 04720 res = p->fake_event; 04721 p->fake_event = 0; 04722 } else 04723 res = dahdi_get_event(p->subs[index].dfd); 04724 04725 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index); 04726 04727 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) { 04728 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0; 04729 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff); 04730 #ifdef HAVE_PRI 04731 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 04732 /* absorb event */ 04733 } else { 04734 #endif 04735 p->subs[index].f.frametype = AST_FRAME_DTMF_END; 04736 p->subs[index].f.subclass = res & 0xff; 04737 #ifdef HAVE_PRI 04738 } 04739 #endif 04740 dahdi_handle_dtmfup(ast, index, &f); 04741 return f; 04742 } 04743 04744 if (res & DAHDI_EVENT_DTMFDOWN) { 04745 ast_debug(1, "DTMF Down '%c'\n", res & 0xff); 04746 /* Mute conference */ 04747 dahdi_confmute(p, 1); 04748 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN; 04749 p->subs[index].f.subclass = res & 0xff; 04750 return &p->subs[index].f; 04751 } 04752 04753 switch (res) { 04754 case DAHDI_EVENT_EC_DISABLED: 04755 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel); 04756 p->echocanon = 0; 04757 break; 04758 case DAHDI_EVENT_BITSCHANGED: 04759 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig)); 04760 case DAHDI_EVENT_PULSE_START: 04761 /* Stop tone if there's a pulse start and the PBX isn't started */ 04762 if (!ast->pbx) 04763 tone_zone_play_tone(p->subs[index].dfd, -1); 04764 break; 04765 case DAHDI_EVENT_DIALCOMPLETE: 04766 if (p->inalarm) break; 04767 if ((p->radio || (p->oprmode < 0))) break; 04768 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) { 04769 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno)); 04770 return NULL; 04771 } 04772 if (!x) { /* if not still dialing in driver */ 04773 dahdi_enable_ec(p); 04774 if (p->echobreak) { 04775 dahdi_train_ec(p); 04776 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); 04777 p->dop.op = DAHDI_DIAL_OP_REPLACE; 04778 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 04779 p->echobreak = 0; 04780 } else { 04781 p->dialing = 0; 04782 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) { 04783 /* if thru with dialing after offhook */ 04784 if (ast->_state == AST_STATE_DIALING_OFFHOOK) { 04785 ast_setstate(ast, AST_STATE_UP); 04786 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04787 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 04788 break; 04789 } else { /* if to state wait for offhook to dial rest */ 04790 /* we now wait for off hook */ 04791 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK); 04792 } 04793 } 04794 if (ast->_state == AST_STATE_DIALING) { 04795 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 04796 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n"); 04797 } 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)))) { 04798 ast_setstate(ast, AST_STATE_RINGING); 04799 } else if (!p->answeronpolarityswitch) { 04800 ast_setstate(ast, AST_STATE_UP); 04801 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04802 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 04803 /* If aops=0 and hops=1, this is necessary */ 04804 p->polarity = POLARITY_REV; 04805 } else { 04806 /* Start clean, so we can catch the change to REV polarity when party answers */ 04807 p->polarity = POLARITY_IDLE; 04808 } 04809 } 04810 } 04811 } 04812 break; 04813 case DAHDI_EVENT_ALARM: 04814 #ifdef HAVE_PRI 04815 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 04816 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) { 04817 /* T309 is not enabled : hangup calls when alarm occurs */ 04818 if (p->call) { 04819 if (p->pri && p->pri->pri) { 04820 if (!pri_grab(p, p->pri)) { 04821 pri_hangup(p->pri->pri, p->call, -1); 04822 pri_destroycall(p->pri->pri, p->call); 04823 p->call = NULL; 04824 pri_rel(p->pri); 04825 } else 04826 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 04827 } else 04828 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n"); 04829 } 04830 if (p->owner) 04831 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 04832 } 04833 } 04834 if (p->bearer) 04835 p->bearer->inalarm = 1; 04836 else 04837 #endif 04838 p->inalarm = 1; 04839 res = get_alarms(p); 04840 handle_alarms(p, res); 04841 #ifdef HAVE_PRI 04842 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 04843 /* fall through intentionally */ 04844 } else { 04845 break; 04846 } 04847 #endif 04848 #ifdef HAVE_SS7 04849 if (p->sig == SIG_SS7) 04850 break; 04851 #endif 04852 case DAHDI_EVENT_ONHOOK: 04853 if (p->radio) { 04854 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04855 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY; 04856 break; 04857 } 04858 if (p->oprmode < 0) 04859 { 04860 if (p->oprmode != -1) break; 04861 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 04862 { 04863 /* Make sure it starts ringing */ 04864 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 04865 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING); 04866 save_conference(p->oprpeer); 04867 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04868 } 04869 break; 04870 } 04871 switch (p->sig) { 04872 case SIG_FXOLS: 04873 case SIG_FXOGS: 04874 case SIG_FXOKS: 04875 p->onhooktime = time(NULL); 04876 p->msgstate = -1; 04877 /* Check for some special conditions regarding call waiting */ 04878 if (index == SUB_REAL) { 04879 /* The normal line was hung up */ 04880 if (p->subs[SUB_CALLWAIT].owner) { 04881 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */ 04882 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 04883 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel); 04884 unalloc_sub(p, SUB_CALLWAIT); 04885 #if 0 04886 p->subs[index].needanswer = 0; 04887 p->subs[index].needringing = 0; 04888 #endif 04889 p->callwaitingrepeat = 0; 04890 p->cidcwexpire = 0; 04891 p->owner = NULL; 04892 /* Don't start streaming audio yet if the incoming call isn't up yet */ 04893 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP) 04894 p->dialing = 1; 04895 dahdi_ring_phone(p); 04896 } else if (p->subs[SUB_THREEWAY].owner) { 04897 unsigned int mssinceflash; 04898 /* Here we have to retain the lock on both the main channel, the 3-way channel, and 04899 the private structure -- not especially easy or clean */ 04900 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) { 04901 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */ 04902 ast_mutex_unlock(&p->lock); 04903 ast_channel_unlock(ast); 04904 usleep(1); 04905 /* We can grab ast and p in that order, without worry. We should make sure 04906 nothing seriously bad has happened though like some sort of bizarre double 04907 masquerade! */ 04908 ast_channel_lock(ast); 04909 ast_mutex_lock(&p->lock); 04910 if (p->owner != ast) { 04911 ast_log(LOG_WARNING, "This isn't good...\n"); 04912 return NULL; 04913 } 04914 } 04915 if (!p->subs[SUB_THREEWAY].owner) { 04916 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n"); 04917 return NULL; 04918 } 04919 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime); 04920 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash); 04921 if (mssinceflash < MIN_MS_SINCE_FLASH) { 04922 /* It hasn't been long enough since the last flashook. This is probably a bounce on 04923 hanging up. Hangup both channels now */ 04924 if (p->subs[SUB_THREEWAY].owner) 04925 ast_queue_hangup(p->subs[SUB_THREEWAY].owner); 04926 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04927 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel); 04928 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04929 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) { 04930 if (p->transfer) { 04931 /* In any case this isn't a threeway call anymore */ 04932 p->subs[SUB_REAL].inthreeway = 0; 04933 p->subs[SUB_THREEWAY].inthreeway = 0; 04934 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */ 04935 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) { 04936 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04937 /* Swap subs and dis-own channel */ 04938 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04939 p->owner = NULL; 04940 /* Ring the phone */ 04941 dahdi_ring_phone(p); 04942 } else { 04943 if ((res = attempt_transfer(p)) < 0) { 04944 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04945 if (p->subs[SUB_THREEWAY].owner) 04946 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04947 } else if (res) { 04948 /* Don't actually hang up at this point */ 04949 if (p->subs[SUB_THREEWAY].owner) 04950 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04951 break; 04952 } 04953 } 04954 } else { 04955 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04956 if (p->subs[SUB_THREEWAY].owner) 04957 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04958 } 04959 } else { 04960 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04961 /* Swap subs and dis-own channel */ 04962 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04963 p->owner = NULL; 04964 /* Ring the phone */ 04965 dahdi_ring_phone(p); 04966 } 04967 } 04968 } else { 04969 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index); 04970 } 04971 /* Fall through */ 04972 default: 04973 dahdi_disable_ec(p); 04974 return NULL; 04975 } 04976 break; 04977 case DAHDI_EVENT_RINGOFFHOOK: 04978 if (p->inalarm) break; 04979 if (p->oprmode < 0) 04980 { 04981 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 04982 { 04983 /* Make sure it stops ringing */ 04984 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 04985 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1); 04986 restore_conference(p->oprpeer); 04987 } 04988 break; 04989 } 04990 if (p->radio) 04991 { 04992 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04993 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY; 04994 break; 04995 } 04996 /* for E911, its supposed to wait for offhook then dial 04997 the second half of the dial string */ 04998 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) { 04999 c = strchr(p->dialdest, '/'); 05000 if (c) 05001 c++; 05002 else 05003 c = p->dialdest; 05004 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c); 05005 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr)); 05006 if (strlen(p->dop.dialstr) > 4) { 05007 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 05008 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 05009 p->echorest[sizeof(p->echorest) - 1] = '\0'; 05010 p->echobreak = 1; 05011 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 05012 } else 05013 p->echobreak = 0; 05014 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 05015 int saveerr = errno; 05016 05017 x = DAHDI_ONHOOK; 05018 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 05019 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 05020 return NULL; 05021 } 05022 p->dialing = 1; 05023 return &p->subs[index].f; 05024 } 05025 switch (p->sig) { 05026 case SIG_FXOLS: 05027 case SIG_FXOGS: 05028 case SIG_FXOKS: 05029 switch (ast->_state) { 05030 case AST_STATE_RINGING: 05031 dahdi_enable_ec(p); 05032 dahdi_train_ec(p); 05033 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05034 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05035 /* Make sure it stops ringing */ 05036 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 05037 ast_debug(1, "channel %d answered\n", p->channel); 05038 if (p->cidspill) { 05039 /* Cancel any running CallerID spill */ 05040 ast_free(p->cidspill); 05041 p->cidspill = NULL; 05042 } 05043 p->dialing = 0; 05044 p->callwaitcas = 0; 05045 if (p->confirmanswer) { 05046 /* Ignore answer if "confirm answer" is enabled */ 05047 p->subs[index].f.frametype = AST_FRAME_NULL; 05048 p->subs[index].f.subclass = 0; 05049 } else if (!ast_strlen_zero(p->dop.dialstr)) { 05050 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ 05051 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05052 if (res < 0) { 05053 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05054 p->dop.dialstr[0] = '\0'; 05055 return NULL; 05056 } else { 05057 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr); 05058 p->subs[index].f.frametype = AST_FRAME_NULL; 05059 p->subs[index].f.subclass = 0; 05060 p->dialing = 1; 05061 } 05062 p->dop.dialstr[0] = '\0'; 05063 ast_setstate(ast, AST_STATE_DIALING); 05064 } else 05065 ast_setstate(ast, AST_STATE_UP); 05066 return &p->subs[index].f; 05067 case AST_STATE_DOWN: 05068 ast_setstate(ast, AST_STATE_RING); 05069 ast->rings = 1; 05070 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05071 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK; 05072 ast_debug(1, "channel %d picked up\n", p->channel); 05073 return &p->subs[index].f; 05074 case AST_STATE_UP: 05075 /* Make sure it stops ringing */ 05076 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 05077 /* Okay -- probably call waiting*/ 05078 if (ast_bridged_channel(p->owner)) 05079 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05080 p->subs[index].needunhold = 1; 05081 break; 05082 case AST_STATE_RESERVED: 05083 /* Start up dialtone */ 05084 if (has_voicemail(p)) 05085 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 05086 else 05087 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 05088 break; 05089 default: 05090 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state); 05091 } 05092 break; 05093 case SIG_FXSLS: 05094 case SIG_FXSGS: 05095 case SIG_FXSKS: 05096 if (ast->_state == AST_STATE_RING) { 05097 p->ringt = p->ringt_base; 05098 } 05099 05100 /* If we get a ring then we cannot be in 05101 * reversed polarity. So we reset to idle */ 05102 ast_debug(1, "Setting IDLE polarity due " 05103 "to ring. Old polarity was %d\n", 05104 p->polarity); 05105 p->polarity = POLARITY_IDLE; 05106 05107 /* Fall through */ 05108 case SIG_EM: 05109 case SIG_EM_E1: 05110 case SIG_EMWINK: 05111 case SIG_FEATD: 05112 case SIG_FEATDMF: 05113 case SIG_FEATDMF_TA: 05114 case SIG_E911: 05115 case SIG_FGC_CAMA: 05116 case SIG_FGC_CAMAMF: 05117 case SIG_FEATB: 05118 case SIG_SF: 05119 case SIG_SFWINK: 05120 case SIG_SF_FEATD: 05121 case SIG_SF_FEATDMF: 05122 case SIG_SF_FEATB: 05123 if (ast->_state == AST_STATE_PRERING) 05124 ast_setstate(ast, AST_STATE_RING); 05125 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) { 05126 ast_debug(1, "Ring detected\n"); 05127 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05128 p->subs[index].f.subclass = AST_CONTROL_RING; 05129 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) { 05130 ast_debug(1, "Line answered\n"); 05131 if (p->confirmanswer) { 05132 p->subs[index].f.frametype = AST_FRAME_NULL; 05133 p->subs[index].f.subclass = 0; 05134 } else { 05135 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05136 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05137 ast_setstate(ast, AST_STATE_UP); 05138 } 05139 } else if (ast->_state != AST_STATE_RING) 05140 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel); 05141 break; 05142 default: 05143 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 05144 } 05145 break; 05146 case DAHDI_EVENT_RINGBEGIN: 05147 switch (p->sig) { 05148 case SIG_FXSLS: 05149 case SIG_FXSGS: 05150 case SIG_FXSKS: 05151 if (ast->_state == AST_STATE_RING) { 05152 p->ringt = p->ringt_base; 05153 } 05154 break; 05155 } 05156 break; 05157 case DAHDI_EVENT_RINGEROFF: 05158 if (p->inalarm) break; 05159 if ((p->radio || (p->oprmode < 0))) break; 05160 ast->rings++; 05161 if ((ast->rings > p->cidrings) && (p->cidspill)) { 05162 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n"); 05163 ast_free(p->cidspill); 05164 p->cidspill = NULL; 05165 p->callwaitcas = 0; 05166 } 05167 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05168 p->subs[index].f.subclass = AST_CONTROL_RINGING; 05169 break; 05170 case DAHDI_EVENT_RINGERON: 05171 break; 05172 case DAHDI_EVENT_NOALARM: 05173 p->inalarm = 0; 05174 #ifdef HAVE_PRI 05175 /* Extremely unlikely but just in case */ 05176 if (p->bearer) 05177 p->bearer->inalarm = 0; 05178 #endif 05179 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 05180 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 05181 "Channel: %d\r\n", p->channel); 05182 break; 05183 case DAHDI_EVENT_WINKFLASH: 05184 if (p->inalarm) break; 05185 if (p->radio) break; 05186 if (p->oprmode < 0) break; 05187 if (p->oprmode > 1) 05188 { 05189 struct dahdi_params par; 05190 05191 memset(&par, 0, sizeof(par)); 05192 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1) 05193 { 05194 if (!par.rxisoffhook) 05195 { 05196 /* Make sure it stops ringing */ 05197 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 05198 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING); 05199 save_conference(p); 05200 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05201 } 05202 } 05203 break; 05204 } 05205 /* Remember last time we got a flash-hook */ 05206 p->flashtime = ast_tvnow(); 05207 switch (mysig) { 05208 case SIG_FXOLS: 05209 case SIG_FXOGS: 05210 case SIG_FXOKS: 05211 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n", 05212 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 05213 p->callwaitcas = 0; 05214 05215 if (index != SUB_REAL) { 05216 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel); 05217 goto winkflashdone; 05218 } 05219 05220 if (p->subs[SUB_CALLWAIT].owner) { 05221 /* Swap to call-wait */ 05222 swap_subs(p, SUB_REAL, SUB_CALLWAIT); 05223 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 05224 p->owner = p->subs[SUB_REAL].owner; 05225 ast_debug(1, "Making %s the new owner\n", p->owner->name); 05226 if (p->owner->_state == AST_STATE_RINGING) { 05227 ast_setstate(p->owner, AST_STATE_UP); 05228 p->subs[SUB_REAL].needanswer = 1; 05229 } 05230 p->callwaitingrepeat = 0; 05231 p->cidcwexpire = 0; 05232 /* Start music on hold if appropriate */ 05233 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 05234 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 05235 S_OR(p->mohsuggest, NULL), 05236 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05237 } 05238 p->subs[SUB_CALLWAIT].needhold = 1; 05239 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 05240 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD, 05241 S_OR(p->mohsuggest, NULL), 05242 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05243 } 05244 p->subs[SUB_REAL].needunhold = 1; 05245 } else if (!p->subs[SUB_THREEWAY].owner) { 05246 if (!p->threewaycalling) { 05247 /* Just send a flash if no 3-way calling */ 05248 p->subs[SUB_REAL].needflash = 1; 05249 goto winkflashdone; 05250 } else if (!check_for_conference(p)) { 05251 char cid_num[256]; 05252 char cid_name[256]; 05253 05254 cid_num[0] = 0; 05255 cid_name[0] = 0; 05256 if (p->dahditrcallerid && p->owner) { 05257 if (p->owner->cid.cid_num) 05258 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num)); 05259 if (p->owner->cid.cid_name) 05260 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name)); 05261 } 05262 /* XXX This section needs much more error checking!!! XXX */ 05263 /* Start a 3-way call if feasible */ 05264 if (!((ast->pbx) || 05265 (ast->_state == AST_STATE_UP) || 05266 (ast->_state == AST_STATE_RING))) { 05267 ast_debug(1, "Flash when call not up or ringing\n"); 05268 goto winkflashdone; 05269 } 05270 if (alloc_sub(p, SUB_THREEWAY)) { 05271 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n"); 05272 goto winkflashdone; 05273 } 05274 /* Make new channel */ 05275 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0); 05276 if (p->dahditrcallerid) { 05277 if (!p->origcid_num) 05278 p->origcid_num = ast_strdup(p->cid_num); 05279 if (!p->origcid_name) 05280 p->origcid_name = ast_strdup(p->cid_name); 05281 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num)); 05282 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name)); 05283 } 05284 /* Swap things around between the three-way and real call */ 05285 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05286 /* Disable echo canceller for better dialing */ 05287 dahdi_disable_ec(p); 05288 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL); 05289 if (res) 05290 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel); 05291 p->owner = chan; 05292 if (!chan) { 05293 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel); 05294 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 05295 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel); 05296 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 05297 dahdi_enable_ec(p); 05298 ast_hangup(chan); 05299 } else { 05300 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 05301 int way3bridge = 0, cdr3way = 0; 05302 05303 if (!other) { 05304 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 05305 } else 05306 way3bridge = 1; 05307 05308 if (p->subs[SUB_THREEWAY].owner->cdr) 05309 cdr3way = 1; 05310 05311 ast_verb(3, "Started three way call on channel %d\n", p->channel); 05312 05313 /* Start music on hold if appropriate */ 05314 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 05315 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 05316 S_OR(p->mohsuggest, NULL), 05317 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05318 } 05319 p->subs[SUB_THREEWAY].needhold = 1; 05320 } 05321 } 05322 } else { 05323 /* Already have a 3 way call */ 05324 if (p->subs[SUB_THREEWAY].inthreeway) { 05325 /* Call is already up, drop the last person */ 05326 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel); 05327 /* If the primary call isn't answered yet, use it */ 05328 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) { 05329 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/ 05330 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05331 p->owner = p->subs[SUB_REAL].owner; 05332 } 05333 /* Drop the last call and stop the conference */ 05334 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name); 05335 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05336 p->subs[SUB_REAL].inthreeway = 0; 05337 p->subs[SUB_THREEWAY].inthreeway = 0; 05338 } else { 05339 /* Lets see what we're up to */ 05340 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 05341 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) { 05342 int otherindex = SUB_THREEWAY; 05343 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 05344 int way3bridge = 0, cdr3way = 0; 05345 05346 if (!other) { 05347 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 05348 } else 05349 way3bridge = 1; 05350 05351 if (p->subs[SUB_THREEWAY].owner->cdr) 05352 cdr3way = 1; 05353 05354 ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name); 05355 /* Put them in the threeway, and flip */ 05356 p->subs[SUB_THREEWAY].inthreeway = 1; 05357 p->subs[SUB_REAL].inthreeway = 1; 05358 if (ast->_state == AST_STATE_UP) { 05359 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05360 otherindex = SUB_REAL; 05361 } 05362 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner)) 05363 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD); 05364 p->subs[otherindex].needunhold = 1; 05365 p->owner = p->subs[SUB_REAL].owner; 05366 if (ast->_state == AST_STATE_RINGING) { 05367 ast_debug(1, "Enabling ringtone on real and threeway\n"); 05368 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05369 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 05370 } 05371 } else { 05372 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name); 05373 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05374 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05375 p->owner = p->subs[SUB_REAL].owner; 05376 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner)) 05377 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 05378 p->subs[SUB_REAL].needunhold = 1; 05379 dahdi_enable_ec(p); 05380 } 05381 05382 } 05383 } 05384 winkflashdone: 05385 update_conf(p); 05386 break; 05387 case SIG_EM: 05388 case SIG_EM_E1: 05389 case SIG_EMWINK: 05390 case SIG_FEATD: 05391 case SIG_SF: 05392 case SIG_SFWINK: 05393 case SIG_SF_FEATD: 05394 case SIG_FXSLS: 05395 case SIG_FXSGS: 05396 if (option_debug) { 05397 if (p->dialing) 05398 ast_debug(1, "Ignoring wink on channel %d\n", p->channel); 05399 else 05400 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel); 05401 } 05402 break; 05403 case SIG_FEATDMF_TA: 05404 switch (p->whichwink) { 05405 case 0: 05406 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 05407 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 05408 break; 05409 case 1: 05410 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr)); 05411 break; 05412 case 2: 05413 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n"); 05414 return NULL; 05415 } 05416 p->whichwink++; 05417 /* Fall through */ 05418 case SIG_FEATDMF: 05419 case SIG_E911: 05420 case SIG_FGC_CAMAMF: 05421 case SIG_FGC_CAMA: 05422 case SIG_FEATB: 05423 case SIG_SF_FEATDMF: 05424 case SIG_SF_FEATB: 05425 /* FGD MF *Must* wait for wink */ 05426 if (!ast_strlen_zero(p->dop.dialstr)) { 05427 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05428 if (res < 0) { 05429 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05430 p->dop.dialstr[0] = '\0'; 05431 return NULL; 05432 } else 05433 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 05434 } 05435 p->dop.dialstr[0] = '\0'; 05436 break; 05437 default: 05438 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig); 05439 } 05440 break; 05441 case DAHDI_EVENT_HOOKCOMPLETE: 05442 if (p->inalarm) break; 05443 if ((p->radio || (p->oprmode < 0))) break; 05444 switch (mysig) { 05445 case SIG_FXSLS: /* only interesting for FXS */ 05446 case SIG_FXSGS: 05447 case SIG_FXSKS: 05448 case SIG_EM: 05449 case SIG_EM_E1: 05450 case SIG_EMWINK: 05451 case SIG_FEATD: 05452 case SIG_SF: 05453 case SIG_SFWINK: 05454 case SIG_SF_FEATD: 05455 if (!ast_strlen_zero(p->dop.dialstr)) { 05456 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05457 if (res < 0) { 05458 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05459 p->dop.dialstr[0] = '\0'; 05460 return NULL; 05461 } else 05462 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 05463 } 05464 p->dop.dialstr[0] = '\0'; 05465 p->dop.op = DAHDI_DIAL_OP_REPLACE; 05466 break; 05467 case SIG_FEATDMF: 05468 case SIG_FEATDMF_TA: 05469 case SIG_E911: 05470 case SIG_FGC_CAMA: 05471 case SIG_FGC_CAMAMF: 05472 case SIG_FEATB: 05473 case SIG_SF_FEATDMF: 05474 case SIG_SF_FEATB: 05475 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel); 05476 break; 05477 default: 05478 break; 05479 } 05480 break; 05481 case DAHDI_EVENT_POLARITY: 05482 /* 05483 * If we get a Polarity Switch event, check to see 05484 * if we should change the polarity state and 05485 * mark the channel as UP or if this is an indication 05486 * of remote end disconnect. 05487 */ 05488 if (p->polarity == POLARITY_IDLE) { 05489 p->polarity = POLARITY_REV; 05490 if (p->answeronpolarityswitch && 05491 ((ast->_state == AST_STATE_DIALING) || 05492 (ast->_state == AST_STATE_RINGING))) { 05493 ast_debug(1, "Answering on polarity switch!\n"); 05494 ast_setstate(p->owner, AST_STATE_UP); 05495 if (p->hanguponpolarityswitch) { 05496 p->polaritydelaytv = ast_tvnow(); 05497 } 05498 } else 05499 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state); 05500 05501 } 05502 /* Removed else statement from here as it was preventing hangups from ever happening*/ 05503 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */ 05504 if (p->hanguponpolarityswitch && 05505 (p->polarityonanswerdelay > 0) && 05506 (p->polarity == POLARITY_REV) && 05507 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) { 05508 /* Added log_debug information below to provide a better indication of what is going on */ 05509 ast_debug(1, "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) ); 05510 05511 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) { 05512 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel); 05513 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 05514 p->polarity = POLARITY_IDLE; 05515 } else 05516 ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state); 05517 05518 } else { 05519 p->polarity = POLARITY_IDLE; 05520 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state); 05521 } 05522 /* Added more log_debug information below to provide a better indication of what is going on */ 05523 ast_debug(1, "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) ); 05524 break; 05525 default: 05526 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel); 05527 } 05528 return &p->subs[index].f; 05529 }
static int dahdi_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3376 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_debug, ast_dsp_digitmode(), ast_dsp_free(), ast_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_verb, 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, dahdi_pvt::guardtime, ast_channel::hangupcause, dahdi_pvt::hidecallerid, iflist, iflock, dahdi_pvt::ignoredtmf, dahdi_subchannel::inthreeway, dahdi_subchannel::linear, dahdi_pvt::lock, 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, 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, dahdi_pvt::rlt, S_OR, dahdi_pvt::setup_ack, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SS7, dahdi_pvt::span, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, unalloc_sub(), and update_conf().
Referenced by pri_dchannel().
03377 { 03378 int res; 03379 int index,x, law; 03380 /*static int restore_gains(struct dahdi_pvt *p);*/ 03381 struct dahdi_pvt *p = ast->tech_pvt; 03382 struct dahdi_pvt *tmp = NULL; 03383 struct dahdi_pvt *prev = NULL; 03384 struct dahdi_params par; 03385 03386 ast_debug(1, "dahdi_hangup(%s)\n", ast->name); 03387 if (!ast->tech_pvt) { 03388 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 03389 return 0; 03390 } 03391 03392 ast_mutex_lock(&p->lock); 03393 03394 index = dahdi_get_index(ast, p, 1); 03395 03396 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 03397 x = 1; 03398 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 03399 } 03400 03401 x = 0; 03402 dahdi_confmute(p, 0); 03403 restore_gains(p); 03404 if (p->origcid_num) { 03405 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num)); 03406 ast_free(p->origcid_num); 03407 p->origcid_num = NULL; 03408 } 03409 if (p->origcid_name) { 03410 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name)); 03411 ast_free(p->origcid_name); 03412 p->origcid_name = NULL; 03413 } 03414 if (p->dsp) 03415 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 03416 p->exten[0] = '\0'; 03417 03418 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n", 03419 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 03420 p->ignoredtmf = 0; 03421 03422 if (index > -1) { 03423 /* Real channel, do some fixup */ 03424 p->subs[index].owner = NULL; 03425 p->subs[index].needanswer = 0; 03426 p->subs[index].needflash = 0; 03427 p->subs[index].needringing = 0; 03428 p->subs[index].needbusy = 0; 03429 p->subs[index].needcongestion = 0; 03430 p->subs[index].linear = 0; 03431 p->subs[index].needcallerid = 0; 03432 p->polarity = POLARITY_IDLE; 03433 dahdi_setlinear(p->subs[index].dfd, 0); 03434 if (index == SUB_REAL) { 03435 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) { 03436 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n"); 03437 if (p->subs[SUB_CALLWAIT].inthreeway) { 03438 /* We had flipped over to answer a callwait and now it's gone */ 03439 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n"); 03440 /* Move to the call-wait, but un-own us until they flip back. */ 03441 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03442 unalloc_sub(p, SUB_CALLWAIT); 03443 p->owner = NULL; 03444 } else { 03445 /* The three way hung up, but we still have a call wait */ 03446 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n"); 03447 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03448 unalloc_sub(p, SUB_THREEWAY); 03449 if (p->subs[SUB_REAL].inthreeway) { 03450 /* This was part of a three way call. Immediately make way for 03451 another call */ 03452 ast_debug(1, "Call was complete, setting owner to former third call\n"); 03453 p->owner = p->subs[SUB_REAL].owner; 03454 } else { 03455 /* This call hasn't been completed yet... Set owner to NULL */ 03456 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 03457 p->owner = NULL; 03458 } 03459 p->subs[SUB_REAL].inthreeway = 0; 03460 } 03461 } else if (p->subs[SUB_CALLWAIT].dfd > -1) { 03462 /* Move to the call-wait and switch back to them. */ 03463 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03464 unalloc_sub(p, SUB_CALLWAIT); 03465 p->owner = p->subs[SUB_REAL].owner; 03466 if (p->owner->_state != AST_STATE_UP) 03467 p->subs[SUB_REAL].needanswer = 1; 03468 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 03469 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 03470 } else if (p->subs[SUB_THREEWAY].dfd > -1) { 03471 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03472 unalloc_sub(p, SUB_THREEWAY); 03473 if (p->subs[SUB_REAL].inthreeway) { 03474 /* This was part of a three way call. Immediately make way for 03475 another call */ 03476 ast_debug(1, "Call was complete, setting owner to former third call\n"); 03477 p->owner = p->subs[SUB_REAL].owner; 03478 } else { 03479 /* This call hasn't been completed yet... Set owner to NULL */ 03480 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 03481 p->owner = NULL; 03482 } 03483 p->subs[SUB_REAL].inthreeway = 0; 03484 } 03485 } else if (index == SUB_CALLWAIT) { 03486 /* Ditch the holding callwait call, and immediately make it availabe */ 03487 if (p->subs[SUB_CALLWAIT].inthreeway) { 03488 /* This is actually part of a three way, placed on hold. Place the third part 03489 on music on hold now */ 03490 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 03491 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 03492 S_OR(p->mohsuggest, NULL), 03493 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 03494 } 03495 p->subs[SUB_THREEWAY].inthreeway = 0; 03496 /* Make it the call wait now */ 03497 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 03498 unalloc_sub(p, SUB_THREEWAY); 03499 } else 03500 unalloc_sub(p, SUB_CALLWAIT); 03501 } else if (index == SUB_THREEWAY) { 03502 if (p->subs[SUB_CALLWAIT].inthreeway) { 03503 /* The other party of the three way call is currently in a call-wait state. 03504 Start music on hold for them, and take the main guy out of the third call */ 03505 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 03506 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 03507 S_OR(p->mohsuggest, NULL), 03508 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 03509 } 03510 p->subs[SUB_CALLWAIT].inthreeway = 0; 03511 } 03512 p->subs[SUB_REAL].inthreeway = 0; 03513 /* If this was part of a three way call index, let us make 03514 another three way call */ 03515 unalloc_sub(p, SUB_THREEWAY); 03516 } else { 03517 /* This wasn't any sort of call, but how are we an index? */ 03518 ast_log(LOG_WARNING, "Index found but not any type of call?\n"); 03519 } 03520 } 03521 03522 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 03523 p->owner = NULL; 03524 p->ringt = 0; 03525 p->distinctivering = 0; 03526 p->confirmanswer = 0; 03527 p->cidrings = 1; 03528 p->outgoing = 0; 03529 p->digital = 0; 03530 p->faxhandled = 0; 03531 p->pulsedial = 0; 03532 p->onhooktime = time(NULL); 03533 #if defined(HAVE_PRI) || defined(HAVE_SS7) 03534 p->proceeding = 0; 03535 p->dialing = 0; 03536 p->progress = 0; 03537 p->alerting = 0; 03538 p->setup_ack = 0; 03539 p->rlt = 0; 03540 #endif 03541 if (p->dsp) { 03542 ast_dsp_free(p->dsp); 03543 p->dsp = NULL; 03544 } 03545 03546 law = DAHDI_LAW_DEFAULT; 03547 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 03548 if (res < 0) 03549 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 03550 /* Perform low level hangup if no owner left */ 03551 #ifdef HAVE_SS7 03552 if (p->ss7) { 03553 if (p->ss7call) { 03554 if (!ss7_grab(p, p->ss7)) { 03555 if (!p->alreadyhungup) { 03556 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE"); 03557 int icause = ast->hangupcause ? ast->hangupcause : -1; 03558 03559 if (cause) { 03560 if (atoi(cause)) 03561 icause = atoi(cause); 03562 } 03563 isup_rel(p->ss7->ss7, p->ss7call, icause); 03564 ss7_rel(p->ss7); 03565 p->alreadyhungup = 1; 03566 } else 03567 ast_log(LOG_WARNING, "Trying to hangup twice!\n"); 03568 } else { 03569 ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic); 03570 res = -1; 03571 } 03572 } 03573 } 03574 #endif 03575 #ifdef HAVE_PRI 03576 if (p->pri) { 03577 #ifdef SUPPORT_USERUSER 03578 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO"); 03579 #endif 03580 03581 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */ 03582 if (p->call && (!p->bearer || (p->bearer->call == p->call))) { 03583 if (!pri_grab(p, p->pri)) { 03584 if (p->alreadyhungup) { 03585 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n"); 03586 03587 #ifdef SUPPORT_USERUSER 03588 pri_call_set_useruser(p->call, useruser); 03589 #endif 03590 03591 pri_hangup(p->pri->pri, p->call, -1); 03592 p->call = NULL; 03593 if (p->bearer) 03594 p->bearer->call = NULL; 03595 } else { 03596 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE"); 03597 int icause = ast->hangupcause ? ast->hangupcause : -1; 03598 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n"); 03599 03600 #ifdef SUPPORT_USERUSER 03601 pri_call_set_useruser(p->call, useruser); 03602 #endif 03603 03604 p->alreadyhungup = 1; 03605 if (p->bearer) 03606 p->bearer->alreadyhungup = 1; 03607 if (cause) { 03608 if (atoi(cause)) 03609 icause = atoi(cause); 03610 } 03611 pri_hangup(p->pri->pri, p->call, icause); 03612 } 03613 if (res < 0) 03614 ast_log(LOG_WARNING, "pri_disconnect failed\n"); 03615 pri_rel(p->pri); 03616 } else { 03617 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 03618 res = -1; 03619 } 03620 } else { 03621 if (p->bearer) 03622 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call); 03623 p->call = NULL; 03624 res = 0; 03625 } 03626 } 03627 #endif 03628 if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7) && (p->sig != SIG_BRI) && (p->sig != SIG_BRI_PTMP))) 03629 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 03630 if (res < 0) { 03631 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name); 03632 } 03633 switch (p->sig) { 03634 case SIG_FXOGS: 03635 case SIG_FXOLS: 03636 case SIG_FXOKS: 03637 memset(&par, 0, sizeof(par)); 03638 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 03639 if (!res) { 03640 #if 0 03641 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook); 03642 #endif 03643 /* If they're off hook, try playing congestion */ 03644 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0)))) 03645 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 03646 else 03647 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03648 } 03649 break; 03650 case SIG_FXSGS: 03651 case SIG_FXSLS: 03652 case SIG_FXSKS: 03653 /* Make sure we're not made available for at least two seconds assuming 03654 we were actually used for an inbound or outbound call. */ 03655 if (ast->_state != AST_STATE_RESERVED) { 03656 time(&p->guardtime); 03657 p->guardtime += 2; 03658 } 03659 break; 03660 default: 03661 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03662 } 03663 if (p->cidspill) 03664 ast_free(p->cidspill); 03665 if (p->sig) 03666 dahdi_disable_ec(p); 03667 x = 0; 03668 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); 03669 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0); 03670 p->didtdd = 0; 03671 p->cidspill = NULL; 03672 p->callwaitcas = 0; 03673 p->callwaiting = p->permcallwaiting; 03674 p->hidecallerid = p->permhidecallerid; 03675 p->dialing = 0; 03676 p->rdnis[0] = '\0'; 03677 update_conf(p); 03678 reset_conf(p); 03679 /* Restore data mode */ 03680 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 03681 x = 0; 03682 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 03683 } 03684 #ifdef HAVE_PRI 03685 if (p->bearer) { 03686 ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel); 03687 /* Free up the bearer channel as well, and 03688 don't use its file descriptor anymore */ 03689 update_conf(p->bearer); 03690 reset_conf(p->bearer); 03691 p->bearer->owner = NULL; 03692 p->bearer->realcall = NULL; 03693 p->bearer = NULL; 03694 p->subs[SUB_REAL].dfd = -1; 03695 p->pri = NULL; 03696 } 03697 #endif 03698 if (num_restart_pending == 0) 03699 restart_monitor(); 03700 } 03701 03702 p->callwaitingrepeat = 0; 03703 p->cidcwexpire = 0; 03704 p->oprmode = 0; 03705 ast->tech_pvt = NULL; 03706 ast_mutex_unlock(&p->lock); 03707 ast_module_unref(ast_module_info->self); 03708 ast_verb(3, "Hungup '%s'\n", ast->name); 03709 03710 ast_mutex_lock(&iflock); 03711 03712 if (p->restartpending) { 03713 num_restart_pending--; 03714 } 03715 03716 tmp = iflist; 03717 prev = NULL; 03718 if (p->destroy) { 03719 while (tmp) { 03720 if (tmp == p) { 03721 destroy_channel(prev, tmp, 0); 03722 break; 03723 } else { 03724 prev = tmp; 03725 tmp = tmp->next; 03726 } 03727 } 03728 } 03729 ast_mutex_unlock(&iflock); 03730 return 0; 03731 }
static int dahdi_indicate | ( | struct ast_channel * | chan, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 6041 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_debug, 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, chan, dahdi_enable_ec(), dahdi_get_index(), dahdi_set_hook(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::digital, dahdi_pvt::dop, errno, ast_channel::hangupcause, ISTRUNK, dahdi_pvt::lock, dahdi_pvt::mohinterpret, ast_channel::name, dahdi_pvt::outgoing, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::priindication_oob, dahdi_pvt::prioffset, dahdi_pvt::proceeding, dahdi_pvt::progress, PVT_TO_CHANNEL, dahdi_pvt::radio, dahdi_pvt::rlt, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SS7, dahdi_pvt::span, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
06042 { 06043 struct dahdi_pvt *p = chan->tech_pvt; 06044 int res=-1; 06045 int index; 06046 int func = DAHDI_FLASH; 06047 ast_mutex_lock(&p->lock); 06048 index = dahdi_get_index(chan, p, 0); 06049 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name); 06050 if (index == SUB_REAL) { 06051 switch (condition) { 06052 case AST_CONTROL_BUSY: 06053 #ifdef HAVE_PRI 06054 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) { 06055 chan->hangupcause = AST_CAUSE_USER_BUSY; 06056 chan->_softhangup |= AST_SOFTHANGUP_DEV; 06057 res = 0; 06058 } else if (!p->progress && 06059 ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06060 && p->pri && !p->outgoing) { 06061 if (p->pri->pri) { 06062 if (!pri_grab(p, p->pri)) { 06063 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06064 pri_rel(p->pri); 06065 } 06066 else 06067 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06068 } 06069 p->progress = 1; 06070 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY); 06071 } else 06072 #endif 06073 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY); 06074 break; 06075 case AST_CONTROL_RINGING: 06076 #ifdef HAVE_PRI 06077 if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06078 && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) { 06079 if (p->pri->pri) { 06080 if (!pri_grab(p, p->pri)) { 06081 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06082 pri_rel(p->pri); 06083 } 06084 else 06085 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06086 } 06087 p->alerting = 1; 06088 } 06089 06090 #endif 06091 #ifdef HAVE_SS7 06092 if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) { 06093 if (p->ss7->ss7) { 06094 ss7_grab(p, p->ss7); 06095 06096 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) 06097 p->rlt = 1; 06098 if (p->rlt != 1) /* No need to send CPG if call will be RELEASE */ 06099 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING); 06100 p->alerting = 1; 06101 ss7_rel(p->ss7); 06102 } 06103 } 06104 #endif 06105 06106 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE); 06107 06108 if (chan->_state != AST_STATE_UP) { 06109 if ((chan->_state != AST_STATE_RING) || 06110 ((p->sig != SIG_FXSKS) && 06111 (p->sig != SIG_FXSLS) && 06112 (p->sig != SIG_FXSGS))) 06113 ast_setstate(chan, AST_STATE_RINGING); 06114 } 06115 break; 06116 case AST_CONTROL_PROCEEDING: 06117 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name); 06118 #ifdef HAVE_PRI 06119 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06120 && p->pri && !p->outgoing) { 06121 if (p->pri->pri) { 06122 if (!pri_grab(p, p->pri)) { 06123 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06124 pri_rel(p->pri); 06125 } 06126 else 06127 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06128 } 06129 p->proceeding = 1; 06130 p->dialing = 0; 06131 } 06132 #endif 06133 #ifdef HAVE_SS7 06134 /* This IF sends the FAR for an answered ALEG call */ 06135 if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){ 06136 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) 06137 p->rlt = 1; 06138 } 06139 06140 if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) { 06141 if (p->ss7->ss7) { 06142 ss7_grab(p, p->ss7); 06143 isup_acm(p->ss7->ss7, p->ss7call); 06144 p->proceeding = 1; 06145 ss7_rel(p->ss7); 06146 06147 } 06148 } 06149 #endif 06150 /* don't continue in ast_indicate */ 06151 res = 0; 06152 break; 06153 case AST_CONTROL_PROGRESS: 06154 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name); 06155 #ifdef HAVE_PRI 06156 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */ 06157 if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06158 && p->pri && !p->outgoing) { 06159 if (p->pri->pri) { 06160 if (!pri_grab(p, p->pri)) { 06161 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06162 pri_rel(p->pri); 06163 } 06164 else 06165 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06166 } 06167 p->progress = 1; 06168 } 06169 #endif 06170 #ifdef HAVE_SS7 06171 if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) { 06172 if (p->ss7->ss7) { 06173 ss7_grab(p, p->ss7); 06174 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO); 06175 p->progress = 1; 06176 ss7_rel(p->ss7); 06177 /* enable echo canceler here on SS7 calls */ 06178 dahdi_enable_ec(p); 06179 06180 } 06181 } 06182 #endif 06183 /* don't continue in ast_indicate */ 06184 res = 0; 06185 break; 06186 case AST_CONTROL_CONGESTION: 06187 chan->hangupcause = AST_CAUSE_CONGESTION; 06188 #ifdef HAVE_PRI 06189 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) { 06190 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 06191 chan->_softhangup |= AST_SOFTHANGUP_DEV; 06192 res = 0; 06193 } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06194 && p->pri && !p->outgoing) { 06195 if (p->pri) { 06196 if (!pri_grab(p, p->pri)) { 06197 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06198 pri_rel(p->pri); 06199 } else 06200 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06201 } 06202 p->progress = 1; 06203 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06204 } else 06205 #endif 06206 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06207 break; 06208 case AST_CONTROL_HOLD: 06209 #ifdef HAVE_PRI 06210 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 06211 if (!pri_grab(p, p->pri)) { 06212 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD); 06213 pri_rel(p->pri); 06214 } else 06215 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06216 } else 06217 #endif 06218 ast_moh_start(chan, data, p->mohinterpret); 06219 break; 06220 case AST_CONTROL_UNHOLD: 06221 #ifdef HAVE_PRI 06222 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 06223 if (!pri_grab(p, p->pri)) { 06224 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL); 06225 pri_rel(p->pri); 06226 } else 06227 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06228 } else 06229 #endif 06230 ast_moh_stop(chan); 06231 break; 06232 case AST_CONTROL_RADIO_KEY: 06233 if (p->radio) 06234 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 06235 res = 0; 06236 break; 06237 case AST_CONTROL_RADIO_UNKEY: 06238 if (p->radio) 06239 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF); 06240 res = 0; 06241 break; 06242 case AST_CONTROL_FLASH: 06243 /* flash hookswitch */ 06244 if (ISTRUNK(p) && (p->sig != SIG_PRI)) { 06245 /* Clear out the dial buffer */ 06246 p->dop.dialstr[0] = '\0'; 06247 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 06248 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 06249 chan->name, strerror(errno)); 06250 } else 06251 res = 0; 06252 } else 06253 res = 0; 06254 break; 06255 case AST_CONTROL_SRCUPDATE: 06256 res = 0; 06257 break; 06258 case -1: 06259 res = tone_zone_play_tone(p->subs[index].dfd, -1); 06260 break; 06261 } 06262 } else 06263 res = 0; 06264 ast_mutex_unlock(&p->lock); 06265 return res; 06266 }
Definition at line 4089 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and master.
Referenced by dahdi_bridge().
04089 { 04090 int x; 04091 if (!slave || !master) { 04092 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n"); 04093 return; 04094 } 04095 for (x = 0; x < MAX_SLAVES; x++) { 04096 if (!master->slaves[x]) { 04097 master->slaves[x] = slave; 04098 break; 04099 } 04100 } 04101 if (x >= MAX_SLAVES) { 04102 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel); 04103 master->slaves[MAX_SLAVES - 1] = slave; 04104 } 04105 if (slave->master) 04106 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel); 04107 slave->master = master; 04108 04109 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x); 04110 }
static struct ast_channel * dahdi_new | ( | struct dahdi_pvt * | , | |
int | , | |||
int | , | |||
int | , | |||
int | , | |||
int | ||||
) | [static] |
Definition at line 6268 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_channel_set_fd(), ast_copy_string(), ast_debug, ast_device_state_changed_literal(), ast_dsp_digitmode(), ast_dsp_new(), ast_dsp_set_busy_compare(), ast_dsp_set_busy_count(), ast_dsp_set_busy_pattern(), ast_dsp_set_call_progress_zone(), ast_dsp_set_features(), ast_dsp_set_threshold(), AST_FORMAT_ALAW, AST_FORMAT_ULAW, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_random(), AST_STATE_RING, ast_str_alloca, ast_str_set(), ast_strdup, ast_string_field_set, ast_strlen_zero(), AST_TRANS_CAP_DIGITAL, 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, CALLPROGRESS_FAX_INCOMING, CALLPROGRESS_FAX_OUTGOING, CALLPROGRESS_PROGRESS, CANBUSYDETECT, CANPROGRESSDETECT, CHAN_PSEUDO, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_ani, dahdi_pvt::cid_ani2, ast_callerid::cid_ani2, 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_confmute(), dahdi_setlinear(), dahdi_tech, 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, global_jbconf, dahdi_pvt::hardwaredtmf, dahdi_pvt::isidlecall, language, dahdi_pvt::language, dahdi_subchannel::linear, ast_variable::name, ast_channel::name, ast_channel::nativeformats, NEED_MFDETECT, ast_variable::next, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::pickupgroup, ast_channel::pickupgroup, dahdi_pvt::pri, ast_channel::rawreadformat, ast_channel::rawwriteformat, dahdi_pvt::rdnis, ast_channel::readformat, ast_channel::rings, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSKS, SIG_PRI, SIG_SS7, dahdi_pvt::silencethreshold, ast_str::str, SUB_REAL, dahdi_pvt::subs, ast_channel::tech, ast_channel::tech_pvt, ast_channel::transfercapability, dahdi_pri::trunkgroup, ast_variable::value, dahdi_pvt::vars, and ast_channel::writeformat.
Referenced by dahdi_handle_event(), dahdi_request(), handle_init_event(), mwi_thread(), and register_translator().
06269 { 06270 struct ast_channel *tmp; 06271 int deflaw; 06272 int res; 06273 int x,y; 06274 int features; 06275 struct ast_str *chan_name; 06276 struct ast_variable *v; 06277 struct dahdi_params ps; 06278 if (i->subs[index].owner) { 06279 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]); 06280 return NULL; 06281 } 06282 y = 1; 06283 chan_name = ast_str_alloca(32); 06284 do { 06285 #ifdef HAVE_PRI 06286 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS))) 06287 ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y); 06288 else 06289 #endif 06290 if (i->channel == CHAN_PSEUDO) 06291 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random()); 06292 else 06293 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y); 06294 for (x = 0; x < 3; x++) { 06295 if ((index != x) && i->subs[x].owner && !strcasecmp(chan_name->str, i->subs[x].owner->name + 6)) 06296 break; 06297 } 06298 y++; 06299 } while (x < 3); 06300 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "DAHDI/%s", chan_name->str); 06301 if (!tmp) 06302 return NULL; 06303 tmp->tech = &dahdi_tech; 06304 memset(&ps, 0, sizeof(ps)); 06305 ps.channo = i->channel; 06306 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps); 06307 if (res) { 06308 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno)); 06309 ps.curlaw = DAHDI_LAW_MULAW; 06310 } 06311 if (ps.curlaw == DAHDI_LAW_ALAW) 06312 deflaw = AST_FORMAT_ALAW; 06313 else 06314 deflaw = AST_FORMAT_ULAW; 06315 if (law) { 06316 if (law == DAHDI_LAW_ALAW) 06317 deflaw = AST_FORMAT_ALAW; 06318 else 06319 deflaw = AST_FORMAT_ULAW; 06320 } 06321 ast_channel_set_fd(tmp, 0, i->subs[index].dfd); 06322 tmp->nativeformats = deflaw; 06323 /* Start out assuming ulaw since it's smaller :) */ 06324 tmp->rawreadformat = deflaw; 06325 tmp->readformat = deflaw; 06326 tmp->rawwriteformat = deflaw; 06327 tmp->writeformat = deflaw; 06328 i->subs[index].linear = 0; 06329 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear); 06330 features = 0; 06331 if (index == SUB_REAL) { 06332 if (i->busydetect && CANBUSYDETECT(i)) 06333 features |= DSP_FEATURE_BUSY_DETECT; 06334 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i)) 06335 features |= DSP_FEATURE_CALL_PROGRESS; 06336 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) || 06337 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) { 06338 features |= DSP_FEATURE_FAX_DETECT; 06339 } 06340 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 06341 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) { 06342 i->hardwaredtmf = 0; 06343 features |= DSP_FEATURE_DTMF_DETECT; 06344 } else if (NEED_MFDETECT(i)) { 06345 i->hardwaredtmf = 1; 06346 features |= DSP_FEATURE_DTMF_DETECT; 06347 } 06348 } 06349 if (features) { 06350 if (i->dsp) { 06351 ast_debug(1, "Already have a dsp on %s?\n", tmp->name); 06352 } else { 06353 if (i->channel != CHAN_PSEUDO) 06354 i->dsp = ast_dsp_new(); 06355 else 06356 i->dsp = NULL; 06357 if (i->dsp) { 06358 i->dsp_features = features; 06359 #if defined(HAVE_PRI) || defined(HAVE_SS7) 06360 /* We cannot do progress detection until receives PROGRESS message */ 06361 if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) { 06362 /* Remember requested DSP features, don't treat 06363 talking as ANSWER */ 06364 i->dsp_features = features & ~DSP_PROGRESS_TALK; 06365 features = 0; 06366 } 06367 #endif 06368 ast_dsp_set_features(i->dsp, features); 06369 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax); 06370 if (!ast_strlen_zero(progzone)) 06371 ast_dsp_set_call_progress_zone(i->dsp, progzone); 06372 if (i->busydetect && CANBUSYDETECT(i)) { 06373 if(i->silencethreshold > 0) 06374 ast_dsp_set_threshold(i->dsp, i->silencethreshold); 06375 ast_dsp_set_busy_count(i->dsp, i->busycount); 06376 if(i->busytonelength > 0) 06377 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness); 06378 if((i->busytonelength == i->busyquietlength) && i->busycompare) 06379 ast_dsp_set_busy_compare(i->dsp, i->busycompare); 06380 } 06381 } 06382 } 06383 } 06384 06385 if (state == AST_STATE_RING) 06386 tmp->rings = 1; 06387 tmp->tech_pvt = i; 06388 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) { 06389 /* Only FXO signalled stuff can be picked up */ 06390 tmp->callgroup = i->callgroup; 06391 tmp->pickupgroup = i->pickupgroup; 06392 } 06393 if (!ast_strlen_zero(i->language)) 06394 ast_string_field_set(tmp, language, i->language); 06395 if (!i->owner) 06396 i->owner = tmp; 06397 if (!ast_strlen_zero(i->accountcode)) 06398 ast_string_field_set(tmp, accountcode, i->accountcode); 06399 if (i->amaflags) 06400 tmp->amaflags = i->amaflags; 06401 i->subs[index].owner = tmp; 06402 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 06403 ast_string_field_set(tmp, call_forward, i->call_forward); 06404 /* If we've been told "no ADSI" then enforce it */ 06405 if (!i->adsi) 06406 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 06407 if (!ast_strlen_zero(i->exten)) 06408 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 06409 if (!ast_strlen_zero(i->rdnis)) 06410 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 06411 if (!ast_strlen_zero(i->dnid)) 06412 tmp->cid.cid_dnid = ast_strdup(i->dnid); 06413 06414 /* Don't use ast_set_callerid() here because it will 06415 * generate a needless NewCallerID event */ 06416 #ifdef PRI_ANI 06417 if (!ast_strlen_zero(i->cid_ani)) 06418 tmp->cid.cid_ani = ast_strdup(i->cid_ani); 06419 else 06420 tmp->cid.cid_ani = ast_strdup(i->cid_num); 06421 #else 06422 tmp->cid.cid_ani = ast_strdup(i->cid_num); 06423 #endif 06424 tmp->cid.cid_pres = i->callingpres; 06425 tmp->cid.cid_ton = i->cid_ton; 06426 tmp->cid.cid_ani2 = i->cid_ani2; 06427 #if defined(HAVE_PRI) || defined(HAVE_SS7) 06428 tmp->transfercapability = transfercapability; 06429 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability)); 06430 if (transfercapability & AST_TRANS_CAP_DIGITAL) 06431 i->digital = 1; 06432 /* Assume calls are not idle calls unless we're told differently */ 06433 i->isidlecall = 0; 06434 i->alreadyhungup = 0; 06435 #endif 06436 /* clear the fake event in case we posted one before we had ast_channel */ 06437 i->fake_event = 0; 06438 /* Assure there is no confmute on this channel */ 06439 dahdi_confmute(i, 0); 06440 /* Configure the new channel jb */ 06441 ast_jb_configure(tmp, &global_jbconf); 06442 06443 ast_device_state_changed_literal(tmp->name); 06444 06445 for (v = i->vars ; v ; v = v->next) 06446 pbx_builtin_setvar_helper(tmp, v->name, v->value); 06447 06448 if (startpbx) { 06449 if (ast_pbx_start(tmp)) { 06450 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 06451 ast_hangup(tmp); 06452 i->owner = NULL; 06453 return NULL; 06454 } 06455 } 06456 06457 ast_module_ref(ast_module_info->self); 06458 return tmp; 06459 }
static int dahdi_open | ( | char * | fn | ) | [static] |
Definition at line 1437 of file chan_dahdi.c.
References ast_log(), chan, errno, LOG_WARNING, and READ_SIZE.
Referenced by alloc_sub(), chandup(), and mkintf().
01438 { 01439 int fd; 01440 int isnum; 01441 int chan = 0; 01442 int bs; 01443 int x; 01444 isnum = 1; 01445 for (x = 0; x < strlen(fn); x++) { 01446 if (!isdigit(fn[x])) { 01447 isnum = 0; 01448 break; 01449 } 01450 } 01451 if (isnum) { 01452 chan = atoi(fn); 01453 if (chan < 1) { 01454 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn); 01455 return -1; 01456 } 01457 fn = "/dev/dahdi/channel"; 01458 } 01459 fd = open(fn, O_RDWR | O_NONBLOCK); 01460 if (fd < 0) { 01461 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno)); 01462 return -1; 01463 } 01464 if (chan) { 01465 if (ioctl(fd, DAHDI_SPECIFY, &chan)) { 01466 x = errno; 01467 close(fd); 01468 errno = x; 01469 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno)); 01470 return -1; 01471 } 01472 } 01473 bs = READ_SIZE; 01474 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) { 01475 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno)); 01476 x = errno; 01477 close(fd); 01478 errno = x; 01479 return -1; 01480 } 01481 return fd; 01482 }
static void dahdi_pri_error | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 10536 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), errno, LOG_ERROR, NUM_SPANS, pridebugfdlock, and pris.
Referenced by dahdi_restart(), and load_module().
10537 { 10538 int x, y; 10539 int dchan = -1, span = -1; 10540 int dchancount = 0; 10541 10542 if (pri) { 10543 for (x = 0; x < NUM_SPANS; x++) { 10544 for (y = 0; y < NUM_DCHANS; y++) { 10545 if (pris[x].dchans[y]) 10546 dchancount++; 10547 10548 if (pris[x].dchans[y] == pri) 10549 dchan = y; 10550 } 10551 if (dchan >= 0) { 10552 span = x; 10553 break; 10554 } 10555 dchancount = 0; 10556 } 10557 if ((dchancount > 1) && (span > -1)) 10558 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s); 10559 else 10560 ast_log(LOG_ERROR, "%s", s); 10561 } else 10562 ast_log(LOG_ERROR, "%s", s); 10563 10564 ast_mutex_lock(&pridebugfdlock); 10565 10566 if (pridebugfd >= 0) { 10567 if (write(pridebugfd, s, strlen(s)) < 0) { 10568 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 10569 } 10570 } 10571 10572 ast_mutex_unlock(&pridebugfdlock); 10573 }
static void dahdi_pri_message | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 10497 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), errno, NUM_SPANS, pridebugfdlock, and pris.
Referenced by dahdi_restart(), and load_module().
10498 { 10499 int x, y; 10500 int dchan = -1, span = -1; 10501 int dchancount = 0; 10502 10503 if (pri) { 10504 for (x = 0; x < NUM_SPANS; x++) { 10505 for (y = 0; y < NUM_DCHANS; y++) { 10506 if (pris[x].dchans[y]) 10507 dchancount++; 10508 10509 if (pris[x].dchans[y] == pri) 10510 dchan = y; 10511 } 10512 if (dchan >= 0) { 10513 span = x; 10514 break; 10515 } 10516 dchancount = 0; 10517 } 10518 if (dchancount > 1 && (span > -1)) 10519 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s); 10520 else 10521 ast_verbose("%s", s); 10522 } else 10523 ast_verbose("%s", s); 10524 10525 ast_mutex_lock(&pridebugfdlock); 10526 10527 if (pridebugfd >= 0) { 10528 if (write(pridebugfd, s, strlen(s)) < 0) { 10529 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 10530 } 10531 } 10532 10533 ast_mutex_unlock(&pridebugfdlock); 10534 }
Definition at line 1343 of file chan_dahdi.c.
References ast_channel_trylock, ast_channel_unlock, ast_mutex_unlock(), ast_queue_frame(), DEADLOCK_AVOIDANCE, f, dahdi_pvt::lock, dahdi_pri::lock, dahdi_pvt::owner, dahdi_pri::pri, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_PRI, and SIG_SS7.
Referenced by action_dahdidialoffhook().
01344 { 01345 #ifdef HAVE_PRI 01346 struct dahdi_pri *pri = (struct dahdi_pri*) data; 01347 #endif 01348 #ifdef HAVE_SS7 01349 struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data; 01350 #endif 01351 /* We must unlock the PRI to avoid the possibility of a deadlock */ 01352 #if defined(HAVE_PRI) || defined(HAVE_SS7) 01353 if (data) { 01354 switch (p->sig) { 01355 #ifdef HAVE_PRI 01356 case SIG_BRI: 01357 case SIG_BRI_PTMP: 01358 case SIG_PRI: 01359 ast_mutex_unlock(&pri->lock); 01360 break; 01361 #endif 01362 #ifdef HAVE_SS7 01363 case SIG_SS7: 01364 ast_mutex_unlock(&ss7->lock); 01365 break; 01366 #endif 01367 default: 01368 break; 01369 } 01370 } 01371 #endif 01372 for (;;) { 01373 if (p->owner) { 01374 if (ast_channel_trylock(p->owner)) { 01375 DEADLOCK_AVOIDANCE(&p->lock); 01376 } else { 01377 ast_queue_frame(p->owner, f); 01378 ast_channel_unlock(p->owner); 01379 break; 01380 } 01381 } else 01382 break; 01383 } 01384 #if defined(HAVE_PRI) || defined(HAVE_SS7) 01385 if (data) { 01386 switch (p->sig) { 01387 #ifdef HAVE_PRI 01388 case SIG_BRI: 01389 case SIG_BRI_PTMP: 01390 case SIG_PRI: 01391 ast_mutex_lock(&pri->lock); 01392 break; 01393 #endif 01394 #ifdef HAVE_SS7 01395 case SIG_SS7: 01396 ast_mutex_lock(&ss7->lock); 01397 break; 01398 #endif 01399 default: 01400 break; 01401 } 01402 } 01403 01404 #endif 01405 }
static struct ast_frame * dahdi_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5647 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_debug, 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_verb, dahdi_subchannel::buffer, dahdi_pvt::busydetect, dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitingrepeat, dahdi_pvt::callwaitrings, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, CHECK_BLOCKING, dahdi_pvt::cidcwexpire, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_callwait(), dahdi_get_index(), dahdi_handle_dtmfup(), DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_setlinear(), ast_frame::data, ast_frame::datalen, 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, dahdi_pvt::lock, 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, 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_BRI, SIG_BRI_PTMP, SIG_PRI, ast_frame::src, SUB_CALLWAIT, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_feed(), and ast_channel::tech_pvt.
05648 { 05649 struct dahdi_pvt *p = ast->tech_pvt; 05650 int res; 05651 int index; 05652 void *readbuf; 05653 struct ast_frame *f; 05654 05655 while (ast_mutex_trylock(&p->lock)) { 05656 CHANNEL_DEADLOCK_AVOIDANCE(ast); 05657 } 05658 05659 index = dahdi_get_index(ast, p, 0); 05660 05661 /* Hang up if we don't really exist */ 05662 if (index < 0) { 05663 ast_log(LOG_WARNING, "We dont exist?\n"); 05664 ast_mutex_unlock(&p->lock); 05665 return NULL; 05666 } 05667 05668 if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL; 05669 05670 p->subs[index].f.frametype = AST_FRAME_NULL; 05671 p->subs[index].f.datalen = 0; 05672 p->subs[index].f.samples = 0; 05673 p->subs[index].f.mallocd = 0; 05674 p->subs[index].f.offset = 0; 05675 p->subs[index].f.subclass = 0; 05676 p->subs[index].f.delivery = ast_tv(0,0); 05677 p->subs[index].f.src = "dahdi_read"; 05678 p->subs[index].f.data = NULL; 05679 05680 /* make sure it sends initial key state as first frame */ 05681 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio)) 05682 { 05683 struct dahdi_params ps; 05684 05685 memset(&ps, 0, sizeof(ps)); 05686 ps.channo = p->channel; 05687 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 05688 ast_mutex_unlock(&p->lock); 05689 return NULL; 05690 } 05691 p->firstradio = 1; 05692 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05693 if (ps.rxisoffhook) 05694 { 05695 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY; 05696 } 05697 else 05698 { 05699 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY; 05700 } 05701 ast_mutex_unlock(&p->lock); 05702 return &p->subs[index].f; 05703 } 05704 if (p->ringt == 1) { 05705 ast_mutex_unlock(&p->lock); 05706 return NULL; 05707 } 05708 else if (p->ringt > 0) 05709 p->ringt--; 05710 05711 if (p->subs[index].needringing) { 05712 /* Send ringing frame if requested */ 05713 p->subs[index].needringing = 0; 05714 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05715 p->subs[index].f.subclass = AST_CONTROL_RINGING; 05716 ast_setstate(ast, AST_STATE_RINGING); 05717 ast_mutex_unlock(&p->lock); 05718 return &p->subs[index].f; 05719 } 05720 05721 if (p->subs[index].needbusy) { 05722 /* Send busy frame if requested */ 05723 p->subs[index].needbusy = 0; 05724 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05725 p->subs[index].f.subclass = AST_CONTROL_BUSY; 05726 ast_mutex_unlock(&p->lock); 05727 return &p->subs[index].f; 05728 } 05729 05730 if (p->subs[index].needcongestion) { 05731 /* Send congestion frame if requested */ 05732 p->subs[index].needcongestion = 0; 05733 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05734 p->subs[index].f.subclass = AST_CONTROL_CONGESTION; 05735 ast_mutex_unlock(&p->lock); 05736 return &p->subs[index].f; 05737 } 05738 05739 if (p->subs[index].needcallerid) { 05740 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL), 05741 S_OR(p->lastcid_name, NULL), 05742 S_OR(p->lastcid_num, NULL) 05743 ); 05744 p->subs[index].needcallerid = 0; 05745 } 05746 05747 if (p->subs[index].needanswer) { 05748 /* Send answer frame if requested */ 05749 p->subs[index].needanswer = 0; 05750 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05751 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05752 ast_mutex_unlock(&p->lock); 05753 return &p->subs[index].f; 05754 } 05755 05756 if (p->subs[index].needflash) { 05757 /* Send answer frame if requested */ 05758 p->subs[index].needflash = 0; 05759 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05760 p->subs[index].f.subclass = AST_CONTROL_FLASH; 05761 ast_mutex_unlock(&p->lock); 05762 return &p->subs[index].f; 05763 } 05764 05765 if (p->subs[index].needhold) { 05766 /* Send answer frame if requested */ 05767 p->subs[index].needhold = 0; 05768 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05769 p->subs[index].f.subclass = AST_CONTROL_HOLD; 05770 ast_mutex_unlock(&p->lock); 05771 ast_debug(1, "Sending hold on '%s'\n", ast->name); 05772 return &p->subs[index].f; 05773 } 05774 05775 if (p->subs[index].needunhold) { 05776 /* Send answer frame if requested */ 05777 p->subs[index].needunhold = 0; 05778 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05779 p->subs[index].f.subclass = AST_CONTROL_UNHOLD; 05780 ast_mutex_unlock(&p->lock); 05781 ast_debug(1, "Sending unhold on '%s'\n", ast->name); 05782 return &p->subs[index].f; 05783 } 05784 05785 if (ast->rawreadformat == AST_FORMAT_SLINEAR) { 05786 if (!p->subs[index].linear) { 05787 p->subs[index].linear = 1; 05788 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 05789 if (res) 05790 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index); 05791 } 05792 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) || 05793 (ast->rawreadformat == AST_FORMAT_ALAW)) { 05794 if (p->subs[index].linear) { 05795 p->subs[index].linear = 0; 05796 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 05797 if (res) 05798 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index); 05799 } 05800 } else { 05801 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat)); 05802 ast_mutex_unlock(&p->lock); 05803 return NULL; 05804 } 05805 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET; 05806 CHECK_BLOCKING(ast); 05807 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE); 05808 ast_clear_flag(ast, AST_FLAG_BLOCKING); 05809 /* Check for hangup */ 05810 if (res < 0) { 05811 f = NULL; 05812 if (res == -1) { 05813 if (errno == EAGAIN) { 05814 /* Return "NULL" frame if there is nobody there */ 05815 ast_mutex_unlock(&p->lock); 05816 return &p->subs[index].f; 05817 } else if (errno == ELAST) { 05818 f = __dahdi_exception(ast); 05819 } else 05820 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno)); 05821 } 05822 ast_mutex_unlock(&p->lock); 05823 return f; 05824 } 05825 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) { 05826 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE); 05827 f = __dahdi_exception(ast); 05828 ast_mutex_unlock(&p->lock); 05829 return f; 05830 } 05831 if (p->tdd) { /* if in TDD mode, see if we receive that */ 05832 int c; 05833 05834 c = tdd_feed(p->tdd,readbuf,READ_SIZE); 05835 if (c < 0) { 05836 ast_debug(1,"tdd_feed failed\n"); 05837 ast_mutex_unlock(&p->lock); 05838 return NULL; 05839 } 05840 if (c) { /* if a char to return */ 05841 p->subs[index].f.subclass = 0; 05842 p->subs[index].f.frametype = AST_FRAME_TEXT; 05843 p->subs[index].f.mallocd = 0; 05844 p->subs[index].f.offset = AST_FRIENDLY_OFFSET; 05845 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET; 05846 p->subs[index].f.datalen = 1; 05847 *((char *) p->subs[index].f.data) = c; 05848 ast_mutex_unlock(&p->lock); 05849 return &p->subs[index].f; 05850 } 05851 } 05852 /* Ensure the CW timer decrements only on a single subchannel */ 05853 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) { 05854 p->callwaitingrepeat--; 05855 } 05856 if (p->cidcwexpire) 05857 p->cidcwexpire--; 05858 /* Repeat callwaiting */ 05859 if (p->callwaitingrepeat == 1) { 05860 p->callwaitrings++; 05861 dahdi_callwait(ast); 05862 } 05863 /* Expire CID/CW */ 05864 if (p->cidcwexpire == 1) { 05865 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n"); 05866 restore_conference(p); 05867 } 05868 if (p->subs[index].linear) { 05869 p->subs[index].f.datalen = READ_SIZE * 2; 05870 } else 05871 p->subs[index].f.datalen = READ_SIZE; 05872 05873 /* Handle CallerID Transmission */ 05874 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) { 05875 send_callerid(p); 05876 } 05877 05878 p->subs[index].f.frametype = AST_FRAME_VOICE; 05879 p->subs[index].f.subclass = ast->rawreadformat; 05880 p->subs[index].f.samples = READ_SIZE; 05881 p->subs[index].f.mallocd = 0; 05882 p->subs[index].f.offset = AST_FRIENDLY_OFFSET; 05883 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]); 05884 #if 0 05885 ast_debug(1, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name); 05886 #endif 05887 if (p->dialing || /* Transmitting something */ 05888 (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */ 05889 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */ 05890 ) { 05891 /* Whoops, we're still dialing, or in a state where we shouldn't transmit.... 05892 don't send anything */ 05893 p->subs[index].f.frametype = AST_FRAME_NULL; 05894 p->subs[index].f.subclass = 0; 05895 p->subs[index].f.samples = 0; 05896 p->subs[index].f.mallocd = 0; 05897 p->subs[index].f.offset = 0; 05898 p->subs[index].f.data = NULL; 05899 p->subs[index].f.datalen= 0; 05900 } 05901 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) { 05902 /* Perform busy detection. etc on the dahdi line */ 05903 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f); 05904 if (f) { 05905 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) { 05906 if ((ast->_state == AST_STATE_UP) && !p->outgoing) { 05907 /* Treat this as a "hangup" instead of a "busy" on the assumption that 05908 a busy */ 05909 f = NULL; 05910 } 05911 } else if (f->frametype == AST_FRAME_DTMF) { 05912 #ifdef HAVE_PRI 05913 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && 05914 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) || 05915 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) { 05916 /* Don't accept in-band DTMF when in overlap dial mode */ 05917 f->frametype = AST_FRAME_NULL; 05918 f->subclass = 0; 05919 } 05920 #endif 05921 /* DSP clears us of being pulse */ 05922 p->pulsedial = 0; 05923 } 05924 } 05925 } else 05926 f = &p->subs[index].f; 05927 05928 if (f && (f->frametype == AST_FRAME_DTMF)) 05929 dahdi_handle_dtmfup(ast, index, &f); 05930 05931 /* If we have a fake_event, trigger exception to handle it */ 05932 if (p->fake_event) 05933 ast_set_flag(ast, AST_FLAG_EXCEPTION); 05934 05935 ast_mutex_unlock(&p->lock); 05936 return f; 05937 }
static struct ast_channel * dahdi_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 9248 of file chan_dahdi.c.
References alloc_sub(), AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CDR_CALLWAIT, ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RESERVED, ast_strdupa, AST_TRANS_CAP_DIGITAL, ast_verbose(), available(), dahdi_pvt::bearer, 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_NOTICE, ast_channel::name, dahdi_pvt::next, NUM_SPANS, 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, strsep(), SUB_CALLWAIT, SUB_REAL, dahdi_pvt::subs, and ast_channel::transfercapability.
Referenced by pri_dchannel().
09249 { 09250 ast_group_t groupmatch = 0; 09251 int channelmatch = -1; 09252 int roundrobin = 0; 09253 int callwait = 0; 09254 int busy = 0; 09255 struct dahdi_pvt *p; 09256 struct ast_channel *tmp = NULL; 09257 char *dest=NULL; 09258 int x; 09259 char *s; 09260 char opt=0; 09261 int res=0, y=0; 09262 int backwards = 0; 09263 #ifdef HAVE_PRI 09264 int crv; 09265 int bearer = -1; 09266 int trunkgroup; 09267 struct dahdi_pri *pri=NULL; 09268 #endif 09269 struct dahdi_pvt *exit, *start, *end; 09270 ast_mutex_t *lock; 09271 int channelmatched = 0; 09272 int groupmatched = 0; 09273 09274 /* 09275 * data is ---v 09276 * Dial(DAHDI/pseudo[/extension]) 09277 * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension]) 09278 * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension]) 09279 * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension]) 09280 * 09281 * g - channel group allocation search forward 09282 * G - channel group allocation search backward 09283 * r - channel group allocation round robin search forward 09284 * R - channel group allocation round robin search backward 09285 * 09286 * c - Wait for DTMF digit to confirm answer 09287 * r<cadance#> - Set distintive ring cadance number 09288 * d - Force bearer capability for ISDN/SS7 call to digital. 09289 */ 09290 09291 /* Assume we're locking the iflock */ 09292 lock = &iflock; 09293 start = iflist; 09294 end = ifend; 09295 if (data) { 09296 dest = ast_strdupa((char *)data); 09297 } else { 09298 ast_log(LOG_WARNING, "Channel requested with no data\n"); 09299 return NULL; 09300 } 09301 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') { 09302 /* Retrieve the group number */ 09303 char *stringp; 09304 09305 stringp = dest + 1; 09306 s = strsep(&stringp, "/"); 09307 if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) { 09308 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data); 09309 return NULL; 09310 } 09311 groupmatch = ((ast_group_t) 1 << x); 09312 if (toupper(dest[0]) == 'G') { 09313 if (dest[0] == 'G') { 09314 backwards = 1; 09315 p = ifend; 09316 } else 09317 p = iflist; 09318 } else { 09319 if (dest[0] == 'R') { 09320 backwards = 1; 09321 p = round_robin[x]?round_robin[x]->prev:ifend; 09322 if (!p) 09323 p = ifend; 09324 } else { 09325 p = round_robin[x]?round_robin[x]->next:iflist; 09326 if (!p) 09327 p = iflist; 09328 } 09329 roundrobin = 1; 09330 } 09331 } else { 09332 char *stringp; 09333 09334 stringp = dest; 09335 s = strsep(&stringp, "/"); 09336 p = iflist; 09337 if (!strcasecmp(s, "pseudo")) { 09338 /* Special case for pseudo */ 09339 x = CHAN_PSEUDO; 09340 channelmatch = x; 09341 } 09342 #ifdef HAVE_PRI 09343 else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) { 09344 if ((trunkgroup < 1) || (crv < 1)) { 09345 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data); 09346 return NULL; 09347 } 09348 res--; 09349 for (x = 0; x < NUM_SPANS; x++) { 09350 if (pris[x].trunkgroup == trunkgroup) { 09351 pri = pris + x; 09352 lock = &pri->lock; 09353 start = pri->crvs; 09354 end = pri->crvend; 09355 break; 09356 } 09357 } 09358 if (!pri) { 09359 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup); 09360 return NULL; 09361 } 09362 channelmatch = crv; 09363 p = pris[x].crvs; 09364 } 09365 #endif 09366 else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) { 09367 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data); 09368 return NULL; 09369 } else { 09370 channelmatch = x; 09371 } 09372 } 09373 /* Search for an unowned channel */ 09374 ast_mutex_lock(lock); 09375 exit = p; 09376 while (p && !tmp) { 09377 if (roundrobin) 09378 round_robin[x] = p; 09379 #if 0 09380 ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch); 09381 #endif 09382 09383 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) { 09384 ast_debug(1, "Using channel %d\n", p->channel); 09385 if (p->inalarm) 09386 goto next; 09387 09388 callwait = (p->owner != NULL); 09389 #ifdef HAVE_PRI 09390 if (pri && (p->subs[SUB_REAL].dfd < 0)) { 09391 if (p->sig != SIG_FXSKS) { 09392 /* Gotta find an actual channel to use for this 09393 CRV if this isn't a callwait */ 09394 bearer = pri_find_empty_chan(pri, 0); 09395 if (bearer < 0) { 09396 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv); 09397 p = NULL; 09398 break; 09399 } 09400 pri_assign_bearer(p, pri, pri->pvts[bearer]); 09401 } else { 09402 if (alloc_sub(p, 0)) { 09403 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n"); 09404 p = NULL; 09405 break; 09406 } else 09407 ast_debug(1, "Allocated placeholder pseudo channel\n"); 09408 09409 p->pri = pri; 09410 } 09411 } 09412 #endif 09413 if (p->channel == CHAN_PSEUDO) { 09414 p = chandup(p); 09415 if (!p) { 09416 break; 09417 } 09418 } 09419 if (p->owner) { 09420 if (alloc_sub(p, SUB_CALLWAIT)) { 09421 p = NULL; 09422 break; 09423 } 09424 } 09425 p->outgoing = 1; 09426 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0); 09427 #ifdef HAVE_PRI 09428 if (p->bearer) { 09429 /* Log owner to bearer channel, too */ 09430 p->bearer->owner = tmp; 09431 } 09432 #endif 09433 /* Make special notes */ 09434 if (res > 1) { 09435 if (opt == 'c') { 09436 /* Confirm answer */ 09437 p->confirmanswer = 1; 09438 } else if (opt == 'r') { 09439 /* Distinctive ring */ 09440 if (res < 3) 09441 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data); 09442 else 09443 p->distinctivering = y; 09444 } else if (opt == 'd') { 09445 /* If this is an ISDN call, make it digital */ 09446 p->digital = 1; 09447 if (tmp) 09448 tmp->transfercapability = AST_TRANS_CAP_DIGITAL; 09449 } else { 09450 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data); 09451 } 09452 } 09453 /* Note if the call is a call waiting call */ 09454 if (tmp && callwait) 09455 tmp->cdrflags |= AST_CDR_CALLWAIT; 09456 break; 09457 } 09458 next: 09459 if (backwards) { 09460 p = p->prev; 09461 if (!p) 09462 p = end; 09463 } else { 09464 p = p->next; 09465 if (!p) 09466 p = start; 09467 } 09468 /* stop when you roll to the one that we started from */ 09469 if (p == exit) 09470 break; 09471 } 09472 ast_mutex_unlock(lock); 09473 restart_monitor(); 09474 if (callwait) 09475 *cause = AST_CAUSE_BUSY; 09476 else if (!tmp) { 09477 if (channelmatched) { 09478 if (busy) 09479 *cause = AST_CAUSE_BUSY; 09480 } else if (groupmatched) { 09481 *cause = AST_CAUSE_CONGESTION; 09482 } 09483 } 09484 09485 return tmp; 09486 }
static int dahdi_restart | ( | void | ) | [static] |
Definition at line 12273 of file chan_dahdi.c.
References ast_active_channels(), ast_cond_wait(), ast_debug, ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_verb, dahdi_close_pri_fd(), dahdi_pri_error(), dahdi_pri_message(), dahdi_softhangup_all(), destroy_all_channels(), dahdi_subchannel::dfd, iflist, lock, monlock, dahdi_pvt::next, NUM_SPANS, dahdi_pvt::owner, pris, restart_lock, setup_dahdi(), ss_thread_lock, and dahdi_pvt::subs.
Referenced by action_dahdirestart(), and dahdi_restart_cmd().
12274 { 12275 #if defined(HAVE_PRI) || defined(HAVE_SS7) 12276 int i, j; 12277 #endif 12278 int cancel_code; 12279 struct dahdi_pvt *p; 12280 12281 ast_mutex_lock(&restart_lock); 12282 12283 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n"); 12284 dahdi_softhangup_all(); 12285 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n"); 12286 12287 #if defined(HAVE_PRI) 12288 for (i = 0; i < NUM_SPANS; i++) { 12289 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) { 12290 cancel_code = pthread_cancel(pris[i].master); 12291 pthread_kill(pris[i].master, SIGURG); 12292 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code); 12293 pthread_join(pris[i].master, NULL); 12294 ast_debug(4, "Joined thread of span %d\n", i); 12295 } 12296 } 12297 #endif 12298 12299 #if defined(HAVE_SS7) 12300 for (i = 0; i < NUM_SPANS; i++) { 12301 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) { 12302 cancel_code = pthread_cancel(linksets[i].master); 12303 pthread_kill(linksets[i].master, SIGURG); 12304 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code); 12305 pthread_join(linksets[i].master, NULL); 12306 ast_debug(4, "Joined thread of span %d\n", i); 12307 } 12308 } 12309 #endif 12310 12311 ast_mutex_lock(&monlock); 12312 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 12313 cancel_code = pthread_cancel(monitor_thread); 12314 pthread_kill(monitor_thread, SIGURG); 12315 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code); 12316 pthread_join(monitor_thread, NULL); 12317 ast_debug(4, "Joined monitor thread\n"); 12318 } 12319 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */ 12320 12321 ast_mutex_lock(&ss_thread_lock); 12322 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */ 12323 int x = DAHDI_FLASH; 12324 ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count); 12325 12326 for (p = iflist; p; p = p->next) { 12327 if (p->owner) 12328 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 */ 12329 } 12330 ast_cond_wait(&ss_thread_complete, &ss_thread_lock); 12331 } 12332 12333 /* ensure any created channels before monitor threads were stopped are hungup */ 12334 dahdi_softhangup_all(); 12335 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n"); 12336 destroy_all_channels(); 12337 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels()); 12338 12339 ast_mutex_unlock(&monlock); 12340 12341 #ifdef HAVE_PRI 12342 for (i = 0; i < NUM_SPANS; i++) { 12343 for (j = 0; j < NUM_DCHANS; j++) 12344 dahdi_close_pri_fd(&(pris[i]), j); 12345 } 12346 12347 memset(pris, 0, sizeof(pris)); 12348 for (i = 0; i < NUM_SPANS; i++) { 12349 ast_mutex_init(&pris[i].lock); 12350 pris[i].offset = -1; 12351 pris[i].master = AST_PTHREADT_NULL; 12352 for (j = 0; j < NUM_DCHANS; j++) 12353 pris[i].fds[j] = -1; 12354 } 12355 pri_set_error(dahdi_pri_error); 12356 pri_set_message(dahdi_pri_message); 12357 #endif 12358 #ifdef HAVE_SS7 12359 for (i = 0; i < NUM_SPANS; i++) { 12360 for (j = 0; j < NUM_DCHANS; j++) 12361 dahdi_close_ss7_fd(&(linksets[i]), j); 12362 } 12363 12364 memset(linksets, 0, sizeof(linksets)); 12365 for (i = 0; i < NUM_SPANS; i++) { 12366 ast_mutex_init(&linksets[i].lock); 12367 linksets[i].master = AST_PTHREADT_NULL; 12368 for (j = 0; j < NUM_DCHANS; j++) 12369 linksets[i].fds[j] = -1; 12370 } 12371 ss7_set_error(dahdi_ss7_error); 12372 ss7_set_message(dahdi_ss7_message); 12373 #endif 12374 12375 if (setup_dahdi(2) != 0) { 12376 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n"); 12377 ast_mutex_unlock(&ss_thread_lock); 12378 return 1; 12379 } 12380 ast_mutex_unlock(&ss_thread_lock); 12381 ast_mutex_unlock(&restart_lock); 12382 return 0; 12383 }
static char* dahdi_restart_cmd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12385 of file chan_dahdi.c.
References ast_cli_args::argc, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_restart(), and ast_cli_entry::usage.
12386 { 12387 switch (cmd) { 12388 case CLI_INIT: 12389 e->command = "dahdi restart"; 12390 e->usage = 12391 "Usage: dahdi restart\n" 12392 " Restarts the DAHDI channels: destroys them all and then\n" 12393 " re-reads them from chan_dahdi.conf.\n" 12394 " Note that this will STOP any running CALL on DAHDI channels.\n" 12395 ""; 12396 return NULL; 12397 case CLI_GENERATE: 12398 return NULL; 12399 } 12400 if (a->argc != 2) 12401 return CLI_SHOWUSAGE; 12402 12403 if (dahdi_restart() != 0) 12404 return CLI_FAILURE; 12405 return CLI_SUCCESS; 12406 }
static int dahdi_ring_phone | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4463 of file chan_dahdi.c.
References ast_log(), errno, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), and dahdi_handle_event().
04464 { 04465 int x; 04466 int res; 04467 /* Make sure our transmit state is on hook */ 04468 x = 0; 04469 x = DAHDI_ONHOOK; 04470 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04471 do { 04472 x = DAHDI_RING; 04473 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04474 if (res) { 04475 switch (errno) { 04476 case EBUSY: 04477 case EINTR: 04478 /* Wait just in case */ 04479 usleep(10000); 04480 continue; 04481 case EINPROGRESS: 04482 res = 0; 04483 break; 04484 default: 04485 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno)); 04486 res = 0; 04487 } 04488 } 04489 } while (res); 04490 return res; 04491 }
static int dahdi_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3257 of file chan_dahdi.c.
References ast_debug, ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), dahdi_pvt::call, chan, dahdi_pvt::lock, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), and ast_channel::tech_pvt.
Referenced by load_module().
03258 { 03259 /* Data will be our digit string */ 03260 struct dahdi_pvt *p; 03261 char *digits = (char *) data; 03262 03263 if (ast_strlen_zero(digits)) { 03264 ast_debug(1, "No digit string sent to application!\n"); 03265 return -1; 03266 } 03267 03268 p = (struct dahdi_pvt *)chan->tech_pvt; 03269 03270 if (!p) { 03271 ast_debug(1, "Unable to find technology private\n"); 03272 return -1; 03273 } 03274 03275 ast_mutex_lock(&p->lock); 03276 03277 if (!p->pri || !p->call) { 03278 ast_debug(1, "Unable to find pri or call on channel!\n"); 03279 ast_mutex_unlock(&p->lock); 03280 return -1; 03281 } 03282 03283 if (!pri_grab(p, p->pri)) { 03284 pri_keypad_facility(p->pri->pri, p->call, digits); 03285 pri_rel(p->pri); 03286 } else { 03287 ast_debug(1, "Unable to grab pri to send keypad facility!\n"); 03288 ast_mutex_unlock(&p->lock); 03289 return -1; 03290 } 03291 03292 ast_mutex_unlock(&p->lock); 03293 03294 return 0; 03295 }
static int dahdi_sendtext | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 15043 of file chan_dahdi.c.
References ASCII_BYTES_PER_CHAR, ast_check_hangup(), ast_debug, ast_free, AST_LAW, ast_log(), ast_malloc, dahdi_pvt::channel, dahdi_get_index(), dahdi_subchannel::dfd, END_SILENCE_LEN, errno, HEADER_LEN, HEADER_MS, len(), LOG_ERROR, dahdi_pvt::mate, PUT_CLID, PUT_CLID_MARKMS, READ_SIZE, dahdi_pvt::subs, dahdi_pvt::tdd, TDD_BYTES_PER_CHAR, tdd_generate(), ast_channel::tech_pvt, and TRAILER_MS.
15044 { 15045 #define END_SILENCE_LEN 400 15046 #define HEADER_MS 50 15047 #define TRAILER_MS 5 15048 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) 15049 #define ASCII_BYTES_PER_CHAR 80 15050 15051 unsigned char *buf,*mybuf; 15052 struct dahdi_pvt *p = c->tech_pvt; 15053 struct pollfd fds[1]; 15054 int size,res,fd,len,x; 15055 int bytes=0; 15056 /* Initial carrier (imaginary) */ 15057 float cr = 1.0; 15058 float ci = 0.0; 15059 float scont = 0.0; 15060 int index; 15061 15062 index = dahdi_get_index(c, p, 0); 15063 if (index < 0) { 15064 ast_log(LOG_WARNING, "Huh? I don't exist?\n"); 15065 return -1; 15066 } 15067 if (!text[0]) return(0); /* if nothing to send, dont */ 15068 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */ 15069 if (p->mate) 15070 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN); 15071 else 15072 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN); 15073 if (!buf) 15074 return -1; 15075 mybuf = buf; 15076 if (p->mate) { 15077 int codec = AST_LAW(p); 15078 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */ 15079 PUT_CLID_MARKMS; 15080 } 15081 /* Put actual message */ 15082 for (x = 0; text[x]; x++) { 15083 PUT_CLID(text[x]); 15084 } 15085 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */ 15086 PUT_CLID_MARKMS; 15087 } 15088 len = bytes; 15089 buf = mybuf; 15090 } else { 15091 len = tdd_generate(p->tdd, buf, text); 15092 if (len < 1) { 15093 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text)); 15094 ast_free(mybuf); 15095 return -1; 15096 } 15097 } 15098 memset(buf + len, 0x7f, END_SILENCE_LEN); 15099 len += END_SILENCE_LEN; 15100 fd = p->subs[index].dfd; 15101 while (len) { 15102 if (ast_check_hangup(c)) { 15103 ast_free(mybuf); 15104 return -1; 15105 } 15106 size = len; 15107 if (size > READ_SIZE) 15108 size = READ_SIZE; 15109 fds[0].fd = fd; 15110 fds[0].events = POLLOUT | POLLPRI; 15111 fds[0].revents = 0; 15112 res = poll(fds, 1, -1); 15113 if (!res) { 15114 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 15115 continue; 15116 } 15117 /* if got exception */ 15118 if (fds[0].revents & POLLPRI) { 15119 ast_free(mybuf); 15120 return -1; 15121 } 15122 if (!(fds[0].revents & POLLOUT)) { 15123 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 15124 continue; 15125 } 15126 res = write(fd, buf, size); 15127 if (res != size) { 15128 if (res == -1) { 15129 ast_free(mybuf); 15130 return -1; 15131 } 15132 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 15133 break; 15134 } 15135 len -= size; 15136 buf += size; 15137 } 15138 ast_free(mybuf); 15139 return(0); 15140 }
static char* dahdi_set_dnd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 13032 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_false(), ast_mutex_lock(), ast_mutex_unlock(), ast_true(), dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_dnd(), ast_cli_args::fd, iflist, iflock, dahdi_pvt::next, and ast_cli_entry::usage.
13033 { 13034 int channel; 13035 int on; 13036 struct dahdi_pvt *dahdi_chan = NULL; 13037 13038 switch (cmd) { 13039 case CLI_INIT: 13040 e->command = "dahdi set dnd"; 13041 e->usage = 13042 "Usage: dahdi set dnd <chan#> <on|off>\n" 13043 " Sets/resets DND (Do Not Disturb) mode on a channel.\n" 13044 " Changes take effect immediately.\n" 13045 " <chan num> is the channel number\n" 13046 " <on|off> Enable or disable DND mode?\n" 13047 ; 13048 return NULL; 13049 case CLI_GENERATE: 13050 return NULL; 13051 } 13052 13053 if (a->argc != 5) 13054 return CLI_SHOWUSAGE; 13055 13056 if ((channel = atoi(a->argv[3])) <= 0) { 13057 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]); 13058 return CLI_SHOWUSAGE; 13059 } 13060 13061 if (ast_true(a->argv[4])) 13062 on = 1; 13063 else if (ast_false(a->argv[4])) 13064 on = 0; 13065 else { 13066 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]); 13067 return CLI_SHOWUSAGE; 13068 } 13069 13070 ast_mutex_lock(&iflock); 13071 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) { 13072 if (dahdi_chan->channel != channel) 13073 continue; 13074 13075 /* Found the channel. Actually set it */ 13076 dahdi_dnd(dahdi_chan, on); 13077 break; 13078 } 13079 ast_mutex_unlock(&iflock); 13080 13081 if (!dahdi_chan) { 13082 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 13083 return CLI_FAILURE; 13084 } 13085 13086 return CLI_SUCCESS; 13087 }
static int dahdi_set_hook | ( | int | fd, | |
int | hs | |||
) | [inline, static] |
Definition at line 2208 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().
02209 { 02210 int x, res; 02211 02212 x = hs; 02213 res = ioctl(fd, DAHDI_HOOK, &x); 02214 02215 if (res < 0) { 02216 if (errno == EINPROGRESS) 02217 return 0; 02218 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno)); 02219 /* will expectedly fail if phone is off hook during operation, such as during a restart */ 02220 } 02221 02222 return res; 02223 }
static char* dahdi_set_hwgain | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12889 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, dahdi_subchannel::dfd, errno, ast_cli_args::fd, iflist, iflock, dahdi_pvt::next, dahdi_pvt::subs, and ast_cli_entry::usage.
12890 { 12891 int channel; 12892 int gain; 12893 int tx; 12894 struct dahdi_hwgain hwgain; 12895 struct dahdi_pvt *tmp = NULL; 12896 12897 switch (cmd) { 12898 case CLI_INIT: 12899 e->command = "dahdi set hwgain"; 12900 e->usage = 12901 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n" 12902 " Sets the hardware gain on a a given channel, overriding the\n" 12903 " value provided at module loadtime, whether the channel is in\n" 12904 " use or not. Changes take effect immediately.\n" 12905 " <rx|tx> which direction do you want to change (relative to our module)\n" 12906 " <chan num> is the channel number relative to the device\n" 12907 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"; 12908 return NULL; 12909 case CLI_GENERATE: 12910 return NULL; 12911 } 12912 12913 if (a->argc != 6) 12914 return CLI_SHOWUSAGE; 12915 12916 if (!strcasecmp("rx", a->argv[3])) 12917 tx = 0; /* rx */ 12918 else if (!strcasecmp("tx", a->argv[3])) 12919 tx = 1; /* tx */ 12920 else 12921 return CLI_SHOWUSAGE; 12922 12923 channel = atoi(a->argv[4]); 12924 gain = atof(a->argv[5])*10.0; 12925 12926 ast_mutex_lock(&iflock); 12927 12928 for (tmp = iflist; tmp; tmp = tmp->next) { 12929 12930 if (tmp->channel != channel) 12931 continue; 12932 12933 if (tmp->subs[SUB_REAL].dfd == -1) 12934 break; 12935 12936 hwgain.newgain = gain; 12937 hwgain.tx = tx; 12938 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) { 12939 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno)); 12940 ast_mutex_unlock(&iflock); 12941 return CLI_FAILURE; 12942 } 12943 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n", 12944 tx ? "tx" : "rx", gain, (float)gain/10.0, channel); 12945 break; 12946 } 12947 12948 ast_mutex_unlock(&iflock); 12949 12950 if (tmp) 12951 return CLI_SUCCESS; 12952 12953 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 12954 return CLI_FAILURE; 12955 12956 }
static char* dahdi_set_swgain | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12958 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_subchannel::dfd, ast_cli_args::fd, iflist, iflock, dahdi_pvt::law, lock, dahdi_pvt::next, set_actual_rxgain(), set_actual_txgain(), dahdi_pvt::subs, and ast_cli_entry::usage.
12959 { 12960 int channel; 12961 float gain; 12962 int tx; 12963 int res; 12964 ast_mutex_t *lock; 12965 struct dahdi_pvt *tmp = NULL; 12966 12967 switch (cmd) { 12968 case CLI_INIT: 12969 e->command = "dahdi set swgain"; 12970 e->usage = 12971 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n" 12972 " Sets the software gain on a a given channel, overriding the\n" 12973 " value provided at module loadtime, whether the channel is in\n" 12974 " use or not. Changes take effect immediately.\n" 12975 " <rx|tx> which direction do you want to change (relative to our module)\n" 12976 " <chan num> is the channel number relative to the device\n" 12977 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"; 12978 return NULL; 12979 case CLI_GENERATE: 12980 return NULL; 12981 } 12982 12983 lock = &iflock; 12984 12985 if (a->argc != 6) 12986 return CLI_SHOWUSAGE; 12987 12988 if (!strcasecmp("rx", a->argv[3])) 12989 tx = 0; /* rx */ 12990 else if (!strcasecmp("tx", a->argv[3])) 12991 tx = 1; /* tx */ 12992 else 12993 return CLI_SHOWUSAGE; 12994 12995 channel = atoi(a->argv[4]); 12996 gain = atof(a->argv[5]); 12997 12998 ast_mutex_lock(lock); 12999 for (tmp = iflist; tmp; tmp = tmp->next) { 13000 13001 if (tmp->channel != channel) 13002 continue; 13003 13004 if (tmp->subs[SUB_REAL].dfd == -1) 13005 break; 13006 13007 if (tx) 13008 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law); 13009 else 13010 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law); 13011 13012 if (res) { 13013 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel); 13014 ast_mutex_unlock(lock); 13015 return CLI_FAILURE; 13016 } 13017 13018 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n", 13019 tx ? "tx" : "rx", gain, channel); 13020 break; 13021 } 13022 ast_mutex_unlock(lock); 13023 13024 if (tmp) 13025 return CLI_SUCCESS; 13026 13027 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 13028 return CLI_FAILURE; 13029 13030 }
static int dahdi_setlaw | ( | int | dfd, | |
int | law | |||
) | [static] |
Definition at line 9489 of file chan_dahdi.c.
09490 { 09491 return ioctl(dfd, DAHDI_SETLAW, &law); 09492 }
static int dahdi_setlinear | ( | int | dfd, | |
int | linear | |||
) | [static] |
Definition at line 1512 of file chan_dahdi.c.
Referenced by dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_write(), send_callerid(), and ss_thread().
01513 { 01514 int res; 01515 res = ioctl(dfd, DAHDI_SETLINEAR, &linear); 01516 if (res) 01517 return res; 01518 return 0; 01519 }
static int dahdi_setoption | ( | struct ast_channel * | chan, | |
int | option, | |||
void * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 3833 of file chan_dahdi.c.
References ast_check_hangup(), ast_debug, 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(), buf, chan, dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_subchannel::dfd, dahdi_pvt::didtdd, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, errno, dahdi_pvt::law, len(), LOG_WARNING, dahdi_pvt::mate, oprmode::mode, ast_channel::name, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, oprmode::peer, pp, READ_SIZE, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_free(), tdd_new(), ast_channel::tech_pvt, and dahdi_pvt::txgain.
03834 { 03835 char *cp; 03836 signed char *scp; 03837 int x; 03838 int index; 03839 struct dahdi_pvt *p = chan->tech_pvt, *pp; 03840 struct oprmode *oprmode; 03841 03842 03843 /* all supported options require data */ 03844 if (!data || (datalen < 1)) { 03845 errno = EINVAL; 03846 return -1; 03847 } 03848 03849 switch (option) { 03850 case AST_OPTION_TXGAIN: 03851 scp = (signed char *) data; 03852 index = dahdi_get_index(chan, p, 0); 03853 if (index < 0) { 03854 ast_log(LOG_WARNING, "No index in TXGAIN?\n"); 03855 return -1; 03856 } 03857 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp); 03858 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law); 03859 case AST_OPTION_RXGAIN: 03860 scp = (signed char *) data; 03861 index = dahdi_get_index(chan, p, 0); 03862 if (index < 0) { 03863 ast_log(LOG_WARNING, "No index in RXGAIN?\n"); 03864 return -1; 03865 } 03866 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp); 03867 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law); 03868 case AST_OPTION_TONE_VERIFY: 03869 if (!p->dsp) 03870 break; 03871 cp = (char *) data; 03872 switch (*cp) { 03873 case 1: 03874 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name); 03875 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */ 03876 break; 03877 case 2: 03878 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name); 03879 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */ 03880 break; 03881 default: 03882 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name); 03883 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */ 03884 break; 03885 } 03886 break; 03887 case AST_OPTION_TDD: 03888 /* turn on or off TDD */ 03889 cp = (char *) data; 03890 p->mate = 0; 03891 if (!*cp) { /* turn it off */ 03892 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name); 03893 if (p->tdd) 03894 tdd_free(p->tdd); 03895 p->tdd = 0; 03896 break; 03897 } 03898 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n", 03899 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name); 03900 dahdi_disable_ec(p); 03901 /* otherwise, turn it on */ 03902 if (!p->didtdd) { /* if havent done it yet */ 03903 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */ 03904 unsigned char *buf; 03905 int size, res, fd, len; 03906 struct pollfd fds[1]; 03907 03908 buf = mybuf; 03909 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */ 03910 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */ 03911 len = 40000; 03912 index = dahdi_get_index(chan, p, 0); 03913 if (index < 0) { 03914 ast_log(LOG_WARNING, "No index in TDD?\n"); 03915 return -1; 03916 } 03917 fd = p->subs[index].dfd; 03918 while (len) { 03919 if (ast_check_hangup(chan)) 03920 return -1; 03921 size = len; 03922 if (size > READ_SIZE) 03923 size = READ_SIZE; 03924 fds[0].fd = fd; 03925 fds[0].events = POLLPRI | POLLOUT; 03926 fds[0].revents = 0; 03927 res = poll(fds, 1, -1); 03928 if (!res) { 03929 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 03930 continue; 03931 } 03932 /* if got exception */ 03933 if (fds[0].revents & POLLPRI) 03934 return -1; 03935 if (!(fds[0].revents & POLLOUT)) { 03936 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 03937 continue; 03938 } 03939 res = write(fd, buf, size); 03940 if (res != size) { 03941 if (res == -1) return -1; 03942 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 03943 break; 03944 } 03945 len -= size; 03946 buf += size; 03947 } 03948 p->didtdd = 1; /* set to have done it now */ 03949 } 03950 if (*cp == 2) { /* Mate mode */ 03951 if (p->tdd) 03952 tdd_free(p->tdd); 03953 p->tdd = 0; 03954 p->mate = 1; 03955 break; 03956 } 03957 if (!p->tdd) { /* if we dont have one yet */ 03958 p->tdd = tdd_new(); /* allocate one */ 03959 } 03960 break; 03961 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */ 03962 if (!p->dsp) 03963 break; 03964 cp = (char *) data; 03965 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n", 03966 *cp ? "ON" : "OFF", (int) *cp, chan->name); 03967 ast_dsp_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax); 03968 break; 03969 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */ 03970 cp = (char *) data; 03971 if (!*cp) { 03972 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name); 03973 x = 0; 03974 dahdi_disable_ec(p); 03975 } else { 03976 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name); 03977 x = 1; 03978 } 03979 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1) 03980 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno)); 03981 break; 03982 case AST_OPTION_OPRMODE: /* Operator services mode */ 03983 oprmode = (struct oprmode *) data; 03984 pp = oprmode->peer->tech_pvt; 03985 p->oprmode = pp->oprmode = 0; 03986 /* setup peers */ 03987 p->oprpeer = pp; 03988 pp->oprpeer = p; 03989 /* setup modes, if any */ 03990 if (oprmode->mode) 03991 { 03992 pp->oprmode = oprmode->mode; 03993 p->oprmode = -oprmode->mode; 03994 } 03995 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n", 03996 oprmode->mode, chan->name,oprmode->peer->name); 03997 break; 03998 case AST_OPTION_ECHOCAN: 03999 cp = (char *) data; 04000 if (*cp) { 04001 ast_debug(1, "Enabling echo cancelation on %s\n", chan->name); 04002 dahdi_enable_ec(p); 04003 } else { 04004 ast_debug(1, "Disabling echo cancelation on %s\n", chan->name); 04005 dahdi_disable_ec(p); 04006 } 04007 break; 04008 } 04009 errno = 0; 04010 04011 return 0; 04012 }
static char* dahdi_show_channel | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12542 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, 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, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_pvt::confno, dahdi_pvt::context, dahdi_pvt::destroy, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dnd, dahdi_pvt::dsp, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, dahdi_pvt::exten, dahdi_pvt::faxhandled, ast_cli_args::fd, dahdi_pvt::head, iflist, iflock, dahdi_pvt::inalarm, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, ISTRUNK, dahdi_pvt::law, dahdi_subchannel::linear, lock, dahdi_pvt::logicalspan, dahdi_pvt::mailbox, dahdi_pvt::master, ast_channel::name, ast_variable::name, ast_variable::next, NUM_SPANS, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::params, dahdi_pvt::pri, dahdi_pri::pri, pris, dahdi_pvt::propconfno, dahdi_pvt::pulsedial, dahdi_pvt::radio, dahdi_pvt::resetting, S_OR, dahdi_pvt::sig, sig2str, dahdi_pvt::slaves, dahdi_pvt::span, SUB_CALLWAIT, SUB_THREEWAY, dahdi_pvt::subs, dahdi_pvt::tdd, ast_cli_entry::usage, ast_variable::value, and dahdi_pvt::vars.
12543 { 12544 int channel; 12545 struct dahdi_pvt *tmp = NULL; 12546 struct dahdi_confinfo ci; 12547 struct dahdi_params ps; 12548 int x; 12549 ast_mutex_t *lock; 12550 struct dahdi_pvt *start; 12551 #ifdef HAVE_PRI 12552 char *c; 12553 int trunkgroup; 12554 struct dahdi_pri *pri=NULL; 12555 #endif 12556 switch (cmd) { 12557 case CLI_INIT: 12558 e->command = "dahdi show channel"; 12559 e->usage = 12560 "Usage: dahdi show channel <chan num>\n" 12561 " Detailed information about a given channel\n"; 12562 return NULL; 12563 case CLI_GENERATE: 12564 return NULL; 12565 } 12566 12567 lock = &iflock; 12568 start = iflist; 12569 12570 if (a->argc != 4) 12571 return CLI_SHOWUSAGE; 12572 #ifdef HAVE_PRI 12573 if ((c = strchr(a->argv[3], ':'))) { 12574 if (sscanf(a->argv[3], "%d:%d", &trunkgroup, &channel) != 2) 12575 return CLI_SHOWUSAGE; 12576 if ((trunkgroup < 1) || (channel < 1)) 12577 return CLI_SHOWUSAGE; 12578 for (x = 0; x < NUM_SPANS; x++) { 12579 if (pris[x].trunkgroup == trunkgroup) { 12580 pri = pris + x; 12581 break; 12582 } 12583 } 12584 if (pri) { 12585 start = pri->crvs; 12586 lock = &pri->lock; 12587 } else { 12588 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup); 12589 return CLI_FAILURE; 12590 } 12591 } else 12592 #endif 12593 channel = atoi(a->argv[3]); 12594 12595 ast_mutex_lock(lock); 12596 tmp = start; 12597 while (tmp) { 12598 if (tmp->channel == channel) { 12599 #ifdef HAVE_PRI 12600 if (pri) 12601 ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel); 12602 else 12603 #endif 12604 ast_cli(a->fd, "Channel: %d\n", tmp->channel); 12605 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd); 12606 ast_cli(a->fd, "Span: %d\n", tmp->span); 12607 ast_cli(a->fd, "Extension: %s\n", tmp->exten); 12608 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no"); 12609 ast_cli(a->fd, "Context: %s\n", tmp->context); 12610 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num); 12611 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton); 12612 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name); 12613 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none")); 12614 if (tmp->vars) { 12615 struct ast_variable *v; 12616 ast_cli(a->fd, "Variables:\n"); 12617 for (v = tmp->vars ; v ; v = v->next) 12618 ast_cli(a->fd, " %s = %s\n", v->name, v->value); 12619 } 12620 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy); 12621 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm); 12622 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig)); 12623 ast_cli(a->fd, "Radio: %d\n", tmp->radio); 12624 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>"); 12625 ast_cli(a->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)" : ""); 12626 ast_cli(a->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)" : ""); 12627 ast_cli(a->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)" : ""); 12628 ast_cli(a->fd, "Confno: %d\n", tmp->confno); 12629 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno); 12630 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference); 12631 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no"); 12632 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no"); 12633 if (tmp->busydetect) { 12634 #if defined(BUSYDETECT_TONEONLY) 12635 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n"); 12636 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE) 12637 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n"); 12638 #endif 12639 #ifdef BUSYDETECT_DEBUG 12640 ast_cli(a->fd, " Busy Detector Debug: Enabled\n"); 12641 #endif 12642 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount); 12643 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength); 12644 } 12645 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no"); 12646 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no"); 12647 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas); 12648 ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown"); 12649 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no"); 12650 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no"); 12651 ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no"); 12652 ast_cli(a->fd, "Echo Cancellation:\n"); 12653 if (tmp->echocancel.head.tap_length) { 12654 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length); 12655 for (x = 0; x < tmp->echocancel.head.param_count; x++) { 12656 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value); 12657 } 12658 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF"); 12659 } else { 12660 ast_cli(a->fd, "\tnone\n"); 12661 } 12662 if (tmp->master) 12663 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel); 12664 for (x = 0; x < MAX_SLAVES; x++) { 12665 if (tmp->slaves[x]) 12666 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel); 12667 } 12668 #ifdef HAVE_SS7 12669 if (tmp->ss7) { 12670 ast_cli(a->fd, "CIC: %d\n", tmp->cic); 12671 } 12672 #endif 12673 #ifdef HAVE_PRI 12674 if (tmp->pri) { 12675 ast_cli(a->fd, "PRI Flags: "); 12676 if (tmp->resetting) 12677 ast_cli(a->fd, "Resetting "); 12678 if (tmp->call) 12679 ast_cli(a->fd, "Call "); 12680 if (tmp->bearer) 12681 ast_cli(a->fd, "Bearer "); 12682 ast_cli(a->fd, "\n"); 12683 if (tmp->logicalspan) 12684 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan); 12685 else 12686 ast_cli(a->fd, "PRI Logical Span: Implicit\n"); 12687 } 12688 12689 #endif 12690 memset(&ci, 0, sizeof(ci)); 12691 ps.channo = tmp->channel; 12692 if (tmp->subs[SUB_REAL].dfd > -1) { 12693 memset(&ci, 0, sizeof(ci)); 12694 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 12695 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode); 12696 } 12697 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) { 12698 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No"); 12699 } 12700 memset(&ps, 0, sizeof(ps)); 12701 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 12702 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno)); 12703 } else { 12704 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook"); 12705 } 12706 } 12707 if (ISTRUNK(tmp)) { 12708 ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no"); 12709 if (!ast_strlen_zero(progzone)) 12710 ast_cli(a->fd, "Progress Zone: %s\n", progzone); 12711 ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no"); 12712 if(tmp->busydetect) { 12713 ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount); 12714 if(tmp->busytonelength > 0) { 12715 ast_cli(a->fd, "Busy Pattern:\n"); 12716 ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength); 12717 if (tmp->busyquietlength > 0) 12718 ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength); 12719 else 12720 ast_cli(a->fd, " -- Detect Tone Only\n"); 12721 if(tmp->busyfuzziness > 0) 12722 ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness); 12723 } 12724 } 12725 } 12726 ast_mutex_unlock(lock); 12727 return CLI_SUCCESS; 12728 } 12729 tmp = tmp->next; 12730 } 12731 12732 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 12733 ast_mutex_unlock(lock); 12734 return CLI_FAILURE; 12735 }
static char* dahdi_show_channels | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12418 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_pvt::context, dahdi_pvt::exten, ast_cli_args::fd, FORMAT, FORMAT2, dahdi_pvt::group, iflist, iflock, dahdi_pvt::language, dahdi_pvt::locallyblocked, lock, dahdi_pvt::mohinterpret, dahdi_pvt::next, NUM_SPANS, dahdi_pri::pri, pris, dahdi_pvt::remotelyblocked, and ast_cli_entry::usage.
12419 { 12420 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 12421 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 12422 unsigned int targetnum = 0; 12423 int filtertype = 0; 12424 struct dahdi_pvt *tmp = NULL; 12425 char tmps[20] = ""; 12426 char statestr[20] = ""; 12427 char blockstr[20] = ""; 12428 ast_mutex_t *lock; 12429 struct dahdi_pvt *start; 12430 #ifdef HAVE_PRI 12431 int trunkgroup; 12432 struct dahdi_pri *pri = NULL; 12433 int x; 12434 #endif 12435 switch (cmd) { 12436 case CLI_INIT: 12437 e->command = "dahdi show channels [trunkgroup|group|context]"; 12438 e->usage = 12439 "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n" 12440 " Shows a list of available channels with optional filtering\n" 12441 " <group> must be a number between 0 and 63\n"; 12442 return NULL; 12443 case CLI_GENERATE: 12444 return NULL; 12445 } 12446 12447 lock = &iflock; 12448 start = iflist; 12449 12450 /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */ 12451 12452 if (!((a->argc == 3) || (a->argc == 5))) 12453 return CLI_SHOWUSAGE; 12454 12455 if (a->argc == 5) { 12456 #ifdef HAVE_PRI 12457 if (!strcasecmp(a->argv[3], "trunkgroup")) { 12458 /* this option requires no special handling, so leave filtertype to zero */ 12459 if ((trunkgroup = atoi(a->argv[4])) < 1) 12460 return CLI_SHOWUSAGE; 12461 for (x = 0; x < NUM_SPANS; x++) { 12462 if (pris[x].trunkgroup == trunkgroup) { 12463 pri = pris + x; 12464 break; 12465 } 12466 } 12467 if (pri) { 12468 start = pri->crvs; 12469 lock = &pri->lock; 12470 } else { 12471 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup); 12472 return CLI_FAILURE; 12473 } 12474 } else 12475 #endif 12476 if (!strcasecmp(a->argv[3], "group")) { 12477 targetnum = atoi(a->argv[4]); 12478 if ((targetnum < 0) || (targetnum > 63)) 12479 return CLI_SHOWUSAGE; 12480 targetnum = 1 << targetnum; 12481 filtertype = 1; 12482 } else if (!strcasecmp(a->argv[3], "context")) { 12483 filtertype = 2; 12484 } 12485 } 12486 12487 ast_mutex_lock(lock); 12488 #ifdef HAVE_PRI 12489 ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State"); 12490 #else 12491 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State"); 12492 #endif 12493 12494 tmp = start; 12495 while (tmp) { 12496 if (filtertype) { 12497 switch(filtertype) { 12498 case 1: /* dahdi show channels group <group> */ 12499 if (!(tmp->group & targetnum)) { 12500 tmp = tmp->next; 12501 continue; 12502 } 12503 break; 12504 case 2: /* dahdi show channels context <context> */ 12505 if (strcasecmp(tmp->context, a->argv[4])) { 12506 tmp = tmp->next; 12507 continue; 12508 } 12509 break; 12510 default: 12511 ; 12512 } 12513 } 12514 if (tmp->channel > 0) { 12515 snprintf(tmps, sizeof(tmps), "%d", tmp->channel); 12516 } else 12517 ast_copy_string(tmps, "pseudo", sizeof(tmps)); 12518 12519 if (tmp->locallyblocked) 12520 blockstr[0] = 'L'; 12521 else 12522 blockstr[0] = ' '; 12523 12524 if (tmp->remotelyblocked) 12525 blockstr[1] = 'R'; 12526 else 12527 blockstr[1] = ' '; 12528 12529 blockstr[2] = '\0'; 12530 12531 snprintf(statestr, sizeof(statestr), "%s", "In Service"); 12532 12533 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr); 12534 tmp = tmp->next; 12535 } 12536 ast_mutex_unlock(lock); 12537 return CLI_SUCCESS; 12538 #undef FORMAT 12539 #undef FORMAT2 12540 }
static char* dahdi_show_status | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12774 of file chan_dahdi.c.
References alarms, ast_cli(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, errno, ast_cli_args::fd, FORMAT, FORMAT2, and ast_cli_entry::usage.
12775 { 12776 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n" 12777 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n" 12778 int span; 12779 int res; 12780 char alarms[50]; 12781 12782 int ctl; 12783 struct dahdi_spaninfo s; 12784 12785 switch (cmd) { 12786 case CLI_INIT: 12787 e->command = "dahdi show status"; 12788 e->usage = 12789 "Usage: dahdi show status\n" 12790 " Shows a list of DAHDI cards with status\n"; 12791 return NULL; 12792 case CLI_GENERATE: 12793 return NULL; 12794 } 12795 ctl = open("/dev/dahdi/ctl", O_RDWR); 12796 if (ctl < 0) { 12797 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno)); 12798 return CLI_FAILURE; 12799 } 12800 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO"); 12801 12802 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 12803 s.spanno = span; 12804 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 12805 if (res) { 12806 continue; 12807 } 12808 alarms[0] = '\0'; 12809 if (s.alarms > 0) { 12810 if (s.alarms & DAHDI_ALARM_BLUE) 12811 strcat(alarms, "BLU/"); 12812 if (s.alarms & DAHDI_ALARM_YELLOW) 12813 strcat(alarms, "YEL/"); 12814 if (s.alarms & DAHDI_ALARM_RED) 12815 strcat(alarms, "RED/"); 12816 if (s.alarms & DAHDI_ALARM_LOOPBACK) 12817 strcat(alarms, "LB/"); 12818 if (s.alarms & DAHDI_ALARM_RECOVER) 12819 strcat(alarms, "REC/"); 12820 if (s.alarms & DAHDI_ALARM_NOTOPEN) 12821 strcat(alarms, "NOP/"); 12822 if (!strlen(alarms)) 12823 strcat(alarms, "UUU/"); 12824 if (strlen(alarms)) { 12825 /* Strip trailing / */ 12826 alarms[strlen(alarms) - 1] = '\0'; 12827 } 12828 } else { 12829 if (s.numchans) 12830 strcpy(alarms, "OK"); 12831 else 12832 strcpy(alarms, "UNCONFIGURED"); 12833 } 12834 12835 ast_cli(a->fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count 12836 , s.lineconfig & DAHDI_CONFIG_D4 ? "D4" : 12837 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" : 12838 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" : 12839 "CAS" 12840 , s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" : 12841 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" : 12842 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" : 12843 "Unk" 12844 , s.lineconfig & DAHDI_CONFIG_CRC4 ? 12845 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL" 12846 , lbostr[s.lbo] 12847 ); 12848 } 12849 close(ctl); 12850 12851 return CLI_SUCCESS; 12852 #undef FORMAT 12853 #undef FORMAT2 12854 }
static char* dahdi_show_version | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12856 of file chan_dahdi.c.
References ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, errno, ast_cli_args::fd, and ast_cli_entry::usage.
12857 { 12858 int pseudo_fd = -1; 12859 struct dahdi_versioninfo vi; 12860 12861 switch (cmd) { 12862 case CLI_INIT: 12863 e->command = "dahdi show version"; 12864 e->usage = 12865 "Usage: dahdi show version\n" 12866 " Shows the DAHDI version in use\n"; 12867 return NULL; 12868 case CLI_GENERATE: 12869 return NULL; 12870 } 12871 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) { 12872 ast_cli(a->fd, "Failed to open control file to get version.\n"); 12873 return CLI_SUCCESS; 12874 } 12875 12876 strcpy(vi.version, "Unknown"); 12877 strcpy(vi.echo_canceller, "Unknown"); 12878 12879 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) 12880 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno)); 12881 else 12882 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller); 12883 12884 close(pseudo_fd); 12885 12886 return CLI_SUCCESS; 12887 }
static char* dahdi_sig2str | ( | int | sig | ) | [static] |
Definition at line 1755 of file chan_dahdi.c.
References buf, SIG_BRI, SIG_BRI_PTMP, 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, and SIG_SS7.
01756 { 01757 static char buf[256]; 01758 switch (sig) { 01759 case SIG_EM: 01760 return "E & M Immediate"; 01761 case SIG_EMWINK: 01762 return "E & M Wink"; 01763 case SIG_EM_E1: 01764 return "E & M E1"; 01765 case SIG_FEATD: 01766 return "Feature Group D (DTMF)"; 01767 case SIG_FEATDMF: 01768 return "Feature Group D (MF)"; 01769 case SIG_FEATDMF_TA: 01770 return "Feature Groud D (MF) Tandem Access"; 01771 case SIG_FEATB: 01772 return "Feature Group B (MF)"; 01773 case SIG_E911: 01774 return "E911 (MF)"; 01775 case SIG_FGC_CAMA: 01776 return "FGC/CAMA (Dialpulse)"; 01777 case SIG_FGC_CAMAMF: 01778 return "FGC/CAMA (MF)"; 01779 case SIG_FXSLS: 01780 return "FXS Loopstart"; 01781 case SIG_FXSGS: 01782 return "FXS Groundstart"; 01783 case SIG_FXSKS: 01784 return "FXS Kewlstart"; 01785 case SIG_FXOLS: 01786 return "FXO Loopstart"; 01787 case SIG_FXOGS: 01788 return "FXO Groundstart"; 01789 case SIG_FXOKS: 01790 return "FXO Kewlstart"; 01791 case SIG_PRI: 01792 return "ISDN PRI"; 01793 case SIG_BRI: 01794 return "ISDN BRI Point to Point"; 01795 case SIG_BRI_PTMP: 01796 return "ISDN BRI Point to MultiPoint"; 01797 case SIG_SS7: 01798 return "SS7"; 01799 case SIG_SF: 01800 return "SF (Tone) Immediate"; 01801 case SIG_SFWINK: 01802 return "SF (Tone) Wink"; 01803 case SIG_SF_FEATD: 01804 return "SF (Tone) with Feature Group D (DTMF)"; 01805 case SIG_SF_FEATDMF: 01806 return "SF (Tone) with Feature Group D (MF)"; 01807 case SIG_SF_FEATB: 01808 return "SF (Tone) with Feature Group B (MF)"; 01809 case SIG_GR303FXOKS: 01810 return "GR-303 with FXOKS"; 01811 case SIG_GR303FXSKS: 01812 return "GR-303 with FXSKS"; 01813 case 0: 01814 return "Pseudo"; 01815 default: 01816 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig); 01817 return buf; 01818 } 01819 }
static void dahdi_softhangup_all | ( | void | ) | [static] |
Definition at line 12244 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().
12245 { 12246 struct dahdi_pvt *p; 12247 retry: 12248 ast_mutex_lock(&iflock); 12249 for (p = iflist; p; p = p->next) { 12250 ast_mutex_lock(&p->lock); 12251 if (p->owner && !p->restartpending) { 12252 if (ast_channel_trylock(p->owner)) { 12253 if (option_debug > 2) 12254 ast_verbose("Avoiding deadlock\n"); 12255 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */ 12256 ast_mutex_unlock(&p->lock); 12257 ast_mutex_unlock(&iflock); 12258 goto retry; 12259 } 12260 if (option_debug > 2) 12261 ast_verbose("Softhanging up on %s\n", p->owner->name); 12262 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT); 12263 p->restartpending = 1; 12264 num_restart_pending++; 12265 ast_channel_unlock(p->owner); 12266 } 12267 ast_mutex_unlock(&p->lock); 12268 } 12269 ast_mutex_unlock(&iflock); 12270 }
static void dahdi_train_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2037 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_pvt::echocanon, dahdi_pvt::echotraining, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_answer(), and dahdi_handle_event().
02038 { 02039 int x; 02040 int res; 02041 02042 if (p && p->echocanon && p->echotraining) { 02043 x = p->echotraining; 02044 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x); 02045 if (res) 02046 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno)); 02047 else 02048 ast_debug(1, "Engaged echo training on channel %d\n", p->channel); 02049 } else { 02050 ast_debug(1, "No echo training requested\n"); 02051 } 02052 }
static void dahdi_unlink | ( | struct dahdi_pvt * | slave, | |
struct dahdi_pvt * | master, | |||
int | needlock | |||
) | [static] |
Definition at line 4033 of file chan_dahdi.c.
References ast_debug, ast_mutex_lock(), ast_mutex_trylock(), conf_del(), DEADLOCK_AVOIDANCE, dahdi_pvt::lock, master, and SUB_REAL.
Referenced by dahdi_bridge(), and dahdi_fixup().
04034 { 04035 /* Unlink a specific slave or all slaves/masters from a given master */ 04036 int x; 04037 int hasslaves; 04038 if (!master) 04039 return; 04040 if (needlock) { 04041 ast_mutex_lock(&master->lock); 04042 if (slave) { 04043 while (ast_mutex_trylock(&slave->lock)) { 04044 DEADLOCK_AVOIDANCE(&master->lock); 04045 } 04046 } 04047 } 04048 hasslaves = 0; 04049 for (x = 0; x < MAX_SLAVES; x++) { 04050 if (master->slaves[x]) { 04051 if (!slave || (master->slaves[x] == slave)) { 04052 /* Take slave out of the conference */ 04053 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel); 04054 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL); 04055 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL); 04056 master->slaves[x]->master = NULL; 04057 master->slaves[x] = NULL; 04058 } else 04059 hasslaves = 1; 04060 } 04061 if (!hasslaves) 04062 master->inconference = 0; 04063 } 04064 if (!slave) { 04065 if (master->master) { 04066 /* Take master out of the conference */ 04067 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL); 04068 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL); 04069 hasslaves = 0; 04070 for (x = 0; x < MAX_SLAVES; x++) { 04071 if (master->master->slaves[x] == master) 04072 master->master->slaves[x] = NULL; 04073 else if (master->master->slaves[x]) 04074 hasslaves = 1; 04075 } 04076 if (!hasslaves) 04077 master->master->inconference = 0; 04078 } 04079 master->master = NULL; 04080 } 04081 update_conf(master); 04082 if (needlock) { 04083 if (slave) 04084 ast_mutex_unlock(&slave->lock); 04085 ast_mutex_unlock(&master->lock); 04086 } 04087 }
static int dahdi_wait_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition at line 306 of file chan_dahdi.c.
Referenced by flash_exec(), and ss_thread().
00307 { 00308 int i, j = 0; 00309 i = DAHDI_IOMUX_SIGEVENT; 00310 if (ioctl(fd, DAHDI_IOMUX, &i) == -1) 00311 return -1; 00312 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) 00313 return -1; 00314 return j; 00315 }
static int dahdi_wink | ( | struct dahdi_pvt * | p, | |
int | index | |||
) | [static] |
Definition at line 6481 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by ss_thread().
06482 { 06483 int j; 06484 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK); 06485 for (;;) 06486 { 06487 /* set bits of interest */ 06488 j = DAHDI_IOMUX_SIGEVENT; 06489 /* wait for some happening */ 06490 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1); 06491 /* exit loop if we have it */ 06492 if (j & DAHDI_IOMUX_SIGEVENT) break; 06493 } 06494 /* get the event info */ 06495 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1); 06496 return 0; 06497 }
static int dahdi_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 5961 of file chan_dahdi.c.
References ast_debug, 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, my_dahdi_write(), ast_channel::name, 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.
05962 { 05963 struct dahdi_pvt *p = ast->tech_pvt; 05964 int res; 05965 int index; 05966 index = dahdi_get_index(ast, p, 0); 05967 if (index < 0) { 05968 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name); 05969 return -1; 05970 } 05971 05972 #if 0 05973 #ifdef HAVE_PRI 05974 ast_mutex_lock(&p->lock); 05975 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { 05976 if (p->pri->pri) { 05977 if (!pri_grab(p, p->pri)) { 05978 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 05979 pri_rel(p->pri); 05980 } else 05981 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05982 } 05983 p->proceeding=1; 05984 } 05985 ast_mutex_unlock(&p->lock); 05986 #endif 05987 #endif 05988 /* Write a frame of (presumably voice) data */ 05989 if (frame->frametype != AST_FRAME_VOICE) { 05990 if (frame->frametype != AST_FRAME_IMAGE) 05991 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); 05992 return 0; 05993 } 05994 if ((frame->subclass != AST_FORMAT_SLINEAR) && 05995 (frame->subclass != AST_FORMAT_ULAW) && 05996 (frame->subclass != AST_FORMAT_ALAW)) { 05997 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass); 05998 return -1; 05999 } 06000 if (p->dialing) { 06001 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name); 06002 return 0; 06003 } 06004 if (!p->owner) { 06005 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name); 06006 return 0; 06007 } 06008 if (p->cidspill) { 06009 ast_debug(1, "Dropping frame since I've still got a callerid spill\n"); 06010 return 0; 06011 } 06012 /* Return if it's not valid data */ 06013 if (!frame->data || !frame->datalen) 06014 return 0; 06015 06016 if (frame->subclass == AST_FORMAT_SLINEAR) { 06017 if (!p->subs[index].linear) { 06018 p->subs[index].linear = 1; 06019 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06020 if (res) 06021 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel); 06022 } 06023 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1); 06024 } else { 06025 /* x-law already */ 06026 if (p->subs[index].linear) { 06027 p->subs[index].linear = 0; 06028 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06029 if (res) 06030 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel); 06031 } 06032 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0); 06033 } 06034 if (res < 0) { 06035 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 06036 return -1; 06037 } 06038 return 0; 06039 }
static void destroy_all_channels | ( | void | ) | [static] |
Definition at line 3218 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().
03219 { 03220 int x; 03221 struct dahdi_pvt *p, *pl; 03222 03223 while (num_restart_pending) { 03224 usleep(1); 03225 } 03226 03227 ast_mutex_lock(&iflock); 03228 /* Destroy all the interfaces and free their memory */ 03229 p = iflist; 03230 while (p) { 03231 /* Free any callerid */ 03232 if (p->cidspill) 03233 ast_free(p->cidspill); 03234 pl = p; 03235 p = p->next; 03236 x = pl->channel; 03237 /* Free associated memory */ 03238 if (pl) 03239 destroy_dahdi_pvt(&pl); 03240 if (option_verbose > 2) 03241 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x); 03242 } 03243 iflist = NULL; 03244 ifcount = 0; 03245 ast_mutex_unlock(&iflock); 03246 }
Definition at line 3168 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().
03169 { 03170 int owned = 0; 03171 int i = 0; 03172 03173 if (!now) { 03174 if (cur->owner) { 03175 owned = 1; 03176 } 03177 03178 for (i = 0; i < 3; i++) { 03179 if (cur->subs[i].owner) { 03180 owned = 1; 03181 } 03182 } 03183 if (!owned) { 03184 if (prev) { 03185 prev->next = cur->next; 03186 if (prev->next) 03187 prev->next->prev = prev; 03188 else 03189 ifend = prev; 03190 } else { 03191 iflist = cur->next; 03192 if (iflist) 03193 iflist->prev = NULL; 03194 else 03195 ifend = NULL; 03196 } 03197 destroy_dahdi_pvt(&cur); 03198 } 03199 } else { 03200 if (prev) { 03201 prev->next = cur->next; 03202 if (prev->next) 03203 prev->next->prev = prev; 03204 else 03205 ifend = prev; 03206 } else { 03207 iflist = cur->next; 03208 if (iflist) 03209 iflist->prev = NULL; 03210 else 03211 ifend = NULL; 03212 } 03213 destroy_dahdi_pvt(&cur); 03214 } 03215 return 0; 03216 }
static void destroy_dahdi_pvt | ( | struct dahdi_pvt ** | pvt | ) | [static] |
Definition at line 3146 of file chan_dahdi.c.
References ast_event_unsubscribe(), ast_mutex_destroy(), ast_smdi_interface_unref(), ast_variables_destroy(), dahdi_close_sub(), free, dahdi_pvt::lock, dahdi_pvt::mwi_event_sub, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::prev, dahdi_pvt::smdi_iface, SUB_REAL, ast_channel::tech_pvt, dahdi_pvt::use_smdi, and dahdi_pvt::vars.
Referenced by chandup(), destroy_all_channels(), destroy_channel(), and mkintf().
03147 { 03148 struct dahdi_pvt *p = *pvt; 03149 /* Remove channel from the list */ 03150 if (p->prev) 03151 p->prev->next = p->next; 03152 if (p->next) 03153 p->next->prev = p->prev; 03154 if (p->use_smdi) 03155 ast_smdi_interface_unref(p->smdi_iface); 03156 if (p->mwi_event_sub) 03157 ast_event_unsubscribe(p->mwi_event_sub); 03158 if (p->vars) 03159 ast_variables_destroy(p->vars); 03160 ast_mutex_destroy(&p->lock); 03161 dahdi_close_sub(p, SUB_REAL); 03162 if (p->owner) 03163 p->owner->tech_pvt = NULL; 03164 free(p); 03165 *pvt = NULL; 03166 }
static char* dialplan2str | ( | int | dialplan | ) | [static] |
Definition at line 1746 of file chan_dahdi.c.
Referenced by dahdi_call(), and mkintf().
01747 { 01748 if (dialplan == -1 || dialplan == -2) { 01749 return("Dynamically set dialplan in ISDN"); 01750 } 01751 return (pri_plan2str(dialplan)); 01752 }
static int digit_to_dtmfindex | ( | char | digit | ) | [static] |
Definition at line 1576 of file chan_dahdi.c.
Referenced by dahdi_digit_begin().
01577 { 01578 if (isdigit(digit)) 01579 return DAHDI_TONE_DTMF_BASE + (digit - '0'); 01580 else if (digit >= 'A' && digit <= 'D') 01581 return DAHDI_TONE_DTMF_A + (digit - 'A'); 01582 else if (digit >= 'a' && digit <= 'd') 01583 return DAHDI_TONE_DTMF_A + (digit - 'a'); 01584 else if (digit == '*') 01585 return DAHDI_TONE_DTMF_s; 01586 else if (digit == '#') 01587 return DAHDI_TONE_DTMF_p; 01588 else 01589 return -1; 01590 }
static void disable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4112 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().
04113 { 04114 int val; 04115 04116 p->ignoredtmf = 1; 04117 04118 val = 0; 04119 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 04120 04121 if (!p->hardwaredtmf && p->dsp) { 04122 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT; 04123 ast_dsp_set_features(p->dsp, p->dsp_features); 04124 } 04125 }
static void* do_idle_thread | ( | void * | vchan | ) | [static] |
Definition at line 10446 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_verb, ast_waitfor(), chan, dahdi_pvt::channel, ast_channel::context, ast_channel::exten, f, dahdi_pri::idlecontext, dahdi_pri::idledial, dahdi_pri::idleext, ast_channel::name, dahdi_pvt::pri, ast_channel::priority, and ast_channel::tech_pvt.
Referenced by pri_dchannel().
10447 { 10448 struct ast_channel *chan = vchan; 10449 struct dahdi_pvt *pvt = chan->tech_pvt; 10450 struct ast_frame *f; 10451 char ex[80]; 10452 /* Wait up to 30 seconds for an answer */ 10453 int newms, ms = 30000; 10454 ast_verb(3, "Initiating idle call on channel %s\n", chan->name); 10455 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial); 10456 if (ast_call(chan, ex, 0)) { 10457 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex); 10458 ast_hangup(chan); 10459 return NULL; 10460 } 10461 while ((newms = ast_waitfor(chan, ms)) > 0) { 10462 f = ast_read(chan); 10463 if (!f) { 10464 /* Got hangup */ 10465 break; 10466 } 10467 if (f->frametype == AST_FRAME_CONTROL) { 10468 switch (f->subclass) { 10469 case AST_CONTROL_ANSWER: 10470 /* Launch the PBX */ 10471 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten)); 10472 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context)); 10473 chan->priority = 1; 10474 ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context); 10475 ast_pbx_run(chan); 10476 /* It's already hungup, return immediately */ 10477 return NULL; 10478 case AST_CONTROL_BUSY: 10479 ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name); 10480 break; 10481 case AST_CONTROL_CONGESTION: 10482 ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name); 10483 break; 10484 }; 10485 } 10486 ast_frfree(f); 10487 ms = newms; 10488 } 10489 /* Hangup the channel since nothing happend */ 10490 ast_hangup(chan); 10491 return NULL; 10492 }
static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 8103 of file chan_dahdi.c.
References ast_calloc, ast_debug, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), buf, dahdi_pvt::cidspill, iflist, iflock, last, dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitoractive, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::radio, dahdi_pvt::sig, SUB_REAL, and dahdi_pvt::subs.
Referenced by restart_monitor().
08104 { 08105 int count, res, res2, spoint, pollres=0; 08106 struct dahdi_pvt *i; 08107 struct dahdi_pvt *last = NULL; 08108 time_t thispass = 0, lastpass = 0; 08109 int found; 08110 char buf[1024]; 08111 struct pollfd *pfds=NULL; 08112 int lastalloc = -1; 08113 /* This thread monitors all the frame relay interfaces which are not yet in use 08114 (and thus do not have a separate thread) indefinitely */ 08115 /* From here on out, we die whenever asked */ 08116 #if 0 08117 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 08118 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 08119 return NULL; 08120 } 08121 ast_debug(1, "Monitor starting...\n"); 08122 #endif 08123 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08124 08125 for (;;) { 08126 /* Lock the interface list */ 08127 ast_mutex_lock(&iflock); 08128 if (!pfds || (lastalloc != ifcount)) { 08129 if (pfds) { 08130 ast_free(pfds); 08131 pfds = NULL; 08132 } 08133 if (ifcount) { 08134 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) { 08135 ast_mutex_unlock(&iflock); 08136 return NULL; 08137 } 08138 } 08139 lastalloc = ifcount; 08140 } 08141 /* Build the stuff we're going to poll on, that is the socket of every 08142 dahdi_pvt that does not have an associated owner channel */ 08143 count = 0; 08144 i = iflist; 08145 while (i) { 08146 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) { 08147 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive) { 08148 /* This needs to be watched, as it lacks an owner */ 08149 pfds[count].fd = i->subs[SUB_REAL].dfd; 08150 pfds[count].events = POLLPRI; 08151 pfds[count].revents = 0; 08152 /* If we are monitoring for VMWI or sending CID, we need to 08153 read from the channel as well */ 08154 if (i->cidspill || i->mwimonitor_fsk) 08155 pfds[count].events |= POLLIN; 08156 count++; 08157 } 08158 } 08159 i = i->next; 08160 } 08161 /* Okay, now that we know what to do, release the interface lock */ 08162 ast_mutex_unlock(&iflock); 08163 08164 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 08165 pthread_testcancel(); 08166 /* Wait at least a second for something to happen */ 08167 res = poll(pfds, count, 1000); 08168 pthread_testcancel(); 08169 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08170 08171 /* Okay, poll has finished. Let's see what happened. */ 08172 if (res < 0) { 08173 if ((errno != EAGAIN) && (errno != EINTR)) 08174 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno)); 08175 continue; 08176 } 08177 /* Alright, lock the interface list again, and let's look and see what has 08178 happened */ 08179 ast_mutex_lock(&iflock); 08180 found = 0; 08181 spoint = 0; 08182 lastpass = thispass; 08183 thispass = time(NULL); 08184 i = iflist; 08185 while (i) { 08186 if (thispass != lastpass) { 08187 if (!found && ((i == last) || ((i == iflist) && !last))) { 08188 last = i; 08189 if (last) { 08190 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) && 08191 (last->sig & __DAHDI_SIG_FXO)) { 08192 res = has_voicemail(last); 08193 if (last->msgstate != res) { 08194 int x; 08195 ast_debug(1, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel); 08196 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res); 08197 if (res2) 08198 /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */ 08199 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno)); 08200 x = DAHDI_FLUSH_BOTH; 08201 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 08202 if (res2) 08203 ast_log(LOG_WARNING, "Unable to flush input on channel %d\n", last->channel); 08204 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) { 08205 /* Turn on on hook transfer for 4 seconds */ 08206 x = 4000; 08207 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x); 08208 last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last)); 08209 last->cidpos = 0; 08210 last->msgstate = res; 08211 last->onhooktime = thispass; 08212 } 08213 found ++; 08214 } 08215 } 08216 last = last->next; 08217 } 08218 } 08219 } 08220 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) { 08221 if (i->radio && !i->owner) 08222 { 08223 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 08224 if (res) 08225 { 08226 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel); 08227 /* Don't hold iflock while handling init events */ 08228 ast_mutex_unlock(&iflock); 08229 handle_init_event(i, res); 08230 ast_mutex_lock(&iflock); 08231 } 08232 i = i->next; 08233 continue; 08234 } 08235 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint); 08236 if (pollres & POLLIN) { 08237 if (i->owner || i->subs[SUB_REAL].owner) { 08238 #ifdef HAVE_PRI 08239 if (!i->pri) 08240 #endif 08241 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd); 08242 i = i->next; 08243 continue; 08244 } 08245 if (!i->cidspill && !i->mwimonitor_fsk) { 08246 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd); 08247 i = i->next; 08248 continue; 08249 } 08250 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf)); 08251 if (res > 0) { 08252 if (i->mwimonitor_fsk) { 08253 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) { 08254 pthread_attr_t attr; 08255 pthread_t threadid; 08256 struct mwi_thread_data *mtd; 08257 08258 pthread_attr_init(&attr); 08259 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 08260 08261 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel); 08262 if ((mtd = ast_calloc(1, sizeof(*mtd)))) { 08263 mtd->pvt = i; 08264 memcpy(mtd->buf, buf, res); 08265 mtd->len = res; 08266 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) { 08267 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel); 08268 ast_free(mtd); 08269 } 08270 i->mwimonitoractive = 1; 08271 } 08272 } 08273 } else if (i->cidspill) { 08274 /* We read some number of bytes. Write an equal amount of data */ 08275 if (res > i->cidlen - i->cidpos) 08276 res = i->cidlen - i->cidpos; 08277 res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res); 08278 if (res2 > 0) { 08279 i->cidpos += res2; 08280 if (i->cidpos >= i->cidlen) { 08281 free(i->cidspill); 08282 i->cidspill = 0; 08283 i->cidpos = 0; 08284 i->cidlen = 0; 08285 } 08286 } else { 08287 ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno)); 08288 i->msgstate = -1; 08289 } 08290 } 08291 } else { 08292 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno)); 08293 } 08294 } 08295 if (pollres & POLLPRI) { 08296 if (i->owner || i->subs[SUB_REAL].owner) { 08297 #ifdef HAVE_PRI 08298 if (!i->pri) 08299 #endif 08300 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd); 08301 i = i->next; 08302 continue; 08303 } 08304 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 08305 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel); 08306 /* Don't hold iflock while handling init events */ 08307 ast_mutex_unlock(&iflock); 08308 handle_init_event(i, res); 08309 ast_mutex_lock(&iflock); 08310 } 08311 } 08312 i=i->next; 08313 } 08314 ast_mutex_unlock(&iflock); 08315 } 08316 /* Never reached */ 08317 return NULL; 08318 08319 }
static void enable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4127 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().
04128 { 04129 int val; 04130 04131 if (p->channel == CHAN_PSEUDO) 04132 return; 04133 04134 p->ignoredtmf = 0; 04135 04136 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 04137 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 04138 04139 if (!p->hardwaredtmf && p->dsp) { 04140 p->dsp_features |= DSP_FEATURE_DTMF_DETECT; 04141 ast_dsp_set_features(p->dsp, p->dsp_features); 04142 } 04143 }
static char* event2str | ( | int | event | ) | [static] |
Definition at line 1736 of file chan_dahdi.c.
References ARRAY_LEN, and buf.
Referenced by __dahdi_exception(), dahdi_handle_event(), mwi_thread(), and ss_thread().
01737 { 01738 static char buf[256]; 01739 if ((event < (ARRAY_LEN(events))) && (event > -1)) 01740 return events[event]; 01741 sprintf(buf, "Event %d", event); /* safe */ 01742 return buf; 01743 }
static void fill_rxgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2106 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_rxgain().
02107 { 02108 int j; 02109 int k; 02110 float linear_gain = pow(10.0, gain / 20.0); 02111 02112 switch (law) { 02113 case DAHDI_LAW_ALAW: 02114 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 02115 if (gain) { 02116 k = (int) (((float) AST_ALAW(j)) * linear_gain); 02117 if (k > 32767) k = 32767; 02118 if (k < -32767) k = -32767; 02119 g->rxgain[j] = AST_LIN2A(k); 02120 } else { 02121 g->rxgain[j] = j; 02122 } 02123 } 02124 break; 02125 case DAHDI_LAW_MULAW: 02126 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 02127 if (gain) { 02128 k = (int) (((float) AST_MULAW(j)) * linear_gain); 02129 if (k > 32767) k = 32767; 02130 if (k < -32767) k = -32767; 02131 g->rxgain[j] = AST_LIN2MU(k); 02132 } else { 02133 g->rxgain[j] = j; 02134 } 02135 } 02136 break; 02137 } 02138 }
static void fill_txgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2072 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_txgain().
02073 { 02074 int j; 02075 int k; 02076 float linear_gain = pow(10.0, gain / 20.0); 02077 02078 switch (law) { 02079 case DAHDI_LAW_ALAW: 02080 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 02081 if (gain) { 02082 k = (int) (((float) AST_ALAW(j)) * linear_gain); 02083 if (k > 32767) k = 32767; 02084 if (k < -32767) k = -32767; 02085 g->txgain[j] = AST_LIN2A(k); 02086 } else { 02087 g->txgain[j] = j; 02088 } 02089 } 02090 break; 02091 case DAHDI_LAW_MULAW: 02092 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 02093 if (gain) { 02094 k = (int) (((float) AST_MULAW(j)) * linear_gain); 02095 if (k > 32767) k = 32767; 02096 if (k < -32767) k = -32767; 02097 g->txgain[j] = AST_LIN2MU(k); 02098 } else { 02099 g->txgain[j] = j; 02100 } 02101 } 02102 break; 02103 } 02104 }
static struct dahdi_pvt* find_channel | ( | int | channel | ) | [static] |
Definition at line 13121 of file chan_dahdi.c.
References dahdi_pvt::channel, iflist, and dahdi_pvt::next.
Referenced by action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_transfer(), and action_transferhangup().
13122 { 13123 struct dahdi_pvt *p = iflist; 13124 while (p) { 13125 if (p->channel == channel) { 13126 break; 13127 } 13128 p = p->next; 13129 } 13130 return p; 13131 }
static int get_alarms | ( | struct dahdi_pvt * | p | ) | [static] |
Checks channel for alarms
p | a channel to check for alarms. |
Definition at line 4575 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, errno, dahdi_pvt::span, SUB_REAL, and dahdi_pvt::subs.
Referenced by action_dahdishowchannels(), dahdi_handle_event(), handle_init_event(), and mwi_thread().
04576 { 04577 int res; 04578 struct dahdi_spaninfo zi; 04579 struct dahdi_params params; 04580 04581 memset(&zi, 0, sizeof(zi)); 04582 zi.spanno = p->span; 04583 04584 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) { 04585 if (zi.alarms != DAHDI_ALARM_NONE) 04586 return zi.alarms; 04587 } else { 04588 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno)); 04589 return 0; 04590 } 04591 04592 /* No alarms on the span. Check for channel alarms. */ 04593 memset(¶ms, 0, sizeof(params)); 04594 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0) 04595 return params.chan_alarms; 04596 04597 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel); 04598 04599 return DAHDI_ALARM_NONE; 04600 }
static void handle_alarms | ( | struct dahdi_pvt * | p, | |
int | alarms | |||
) | [static] |
Definition at line 4682 of file chan_dahdi.c.
References alarm2str(), ast_log(), dahdi_pvt::channel, EVENT_FLAG_SYSTEM, and manager_event.
Referenced by dahdi_handle_event(), handle_init_event(), and mwi_thread().
04683 { 04684 const char *alarm_str = alarm2str(alarms); 04685 04686 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); 04687 manager_event(EVENT_FLAG_SYSTEM, "Alarm", 04688 "Alarm: %s\r\n" 04689 "Channel: %d\r\n", 04690 alarm_str, p->channel); 04691 }
static char* handle_dahdi_show_cadences | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12737 of file chan_dahdi.c.
References ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, COLOR_BLACK, COLOR_GREEN, COLOR_MAGENTA, ast_cli_entry::command, ast_cli_args::fd, term_color(), and ast_cli_entry::usage.
12738 { 12739 int i, j; 12740 switch (cmd) { 12741 case CLI_INIT: 12742 e->command = "dahdi show cadences"; 12743 e->usage = 12744 "Usage: dahdi show cadences\n" 12745 " Shows all cadences currently defined\n"; 12746 return NULL; 12747 case CLI_GENERATE: 12748 return NULL; 12749 } 12750 for (i = 0; i < num_cadence; i++) { 12751 char output[1024]; 12752 char tmp[16], tmp2[64]; 12753 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1); 12754 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output)); 12755 12756 for (j = 0; j < 16; j++) { 12757 if (cadences[i].ringcadence[j] == 0) 12758 break; 12759 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]); 12760 if (cidrings[i] * 2 - 1 == j) 12761 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1); 12762 else 12763 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1); 12764 if (j != 0) 12765 strncat(output, ",", sizeof(output) - strlen(output) - 1); 12766 strncat(output, tmp2, sizeof(output) - strlen(output) - 1); 12767 } 12768 ast_cli(a->fd,"%s\n",output); 12769 } 12770 return CLI_SUCCESS; 12771 }
static int handle_init_event | ( | struct dahdi_pvt * | i, | |
int | event | |||
) | [static] |
Definition at line 7883 of file chan_dahdi.c.
References ast_free, ast_hangup(), ast_log(), ast_pthread_create_detached, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, ast_verb, chan, dahdi_pvt::channel, dahdi_pvt::cid_start, CID_START_POLARITY, CID_START_POLARITY_IN, dahdi_pvt::cidspill, dahdi_destroy_channel_bynum(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_new(), dahdi_set_hook(), errno, EVENT_FLAG_SYSTEM, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::immediate, dahdi_pvt::inalarm, LOG_NOTICE, dahdi_pvt::mailbox, manager_event, dahdi_pvt::mwimonitor_neon, notify_message(), dahdi_pvt::polarity, POLARITY_REV, dahdi_pvt::radio, dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, sig2str, SIG_BRI, SIG_BRI_PTMP, 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, SIG_SS7, ss_thread(), SUB_REAL, and dahdi_pvt::subs.
07884 { 07885 int res; 07886 pthread_t threadid; 07887 struct ast_channel *chan; 07888 07889 /* Handle an event on a given channel for the monitor thread. */ 07890 07891 switch (event) { 07892 case DAHDI_EVENT_NONE: 07893 case DAHDI_EVENT_BITSCHANGED: 07894 break; 07895 case DAHDI_EVENT_WINKFLASH: 07896 case DAHDI_EVENT_RINGOFFHOOK: 07897 if (i->inalarm) break; 07898 if (i->radio) break; 07899 /* Got a ring/answer. What kind of channel are we? */ 07900 switch (i->sig) { 07901 case SIG_FXOLS: 07902 case SIG_FXOGS: 07903 case SIG_FXOKS: 07904 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07905 if (res && (errno == EBUSY)) 07906 break; 07907 if (i->cidspill) { 07908 /* Cancel VMWI spill */ 07909 ast_free(i->cidspill); 07910 i->cidspill = NULL; 07911 } 07912 if (i->immediate) { 07913 dahdi_enable_ec(i); 07914 /* The channel is immediately up. Start right away */ 07915 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 07916 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0); 07917 if (!chan) { 07918 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel); 07919 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07920 if (res < 0) 07921 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 07922 } 07923 } else { 07924 /* Check for callerid, digits, etc */ 07925 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0); 07926 if (chan) { 07927 if (has_voicemail(i)) 07928 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 07929 else 07930 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 07931 if (res < 0) 07932 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel); 07933 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 07934 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 07935 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07936 if (res < 0) 07937 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 07938 ast_hangup(chan); 07939 } 07940 } else 07941 ast_log(LOG_WARNING, "Unable to create channel\n"); 07942 } 07943 break; 07944 case SIG_FXSLS: 07945 case SIG_FXSGS: 07946 case SIG_FXSKS: 07947 i->ringt = i->ringt_base; 07948 /* Fall through */ 07949 case SIG_EMWINK: 07950 case SIG_FEATD: 07951 case SIG_FEATDMF: 07952 case SIG_FEATDMF_TA: 07953 case SIG_E911: 07954 case SIG_FGC_CAMA: 07955 case SIG_FGC_CAMAMF: 07956 case SIG_FEATB: 07957 case SIG_EM: 07958 case SIG_EM_E1: 07959 case SIG_SFWINK: 07960 case SIG_SF_FEATD: 07961 case SIG_SF_FEATDMF: 07962 case SIG_SF_FEATB: 07963 case SIG_SF: 07964 /* Check for callerid, digits, etc */ 07965 if (i->cid_start == CID_START_POLARITY_IN) { 07966 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 07967 } else { 07968 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0); 07969 } 07970 if (chan && ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 07971 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 07972 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07973 if (res < 0) 07974 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 07975 ast_hangup(chan); 07976 } else if (!chan) { 07977 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 07978 } 07979 break; 07980 default: 07981 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 07982 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07983 if (res < 0) 07984 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 07985 return -1; 07986 } 07987 break; 07988 case DAHDI_EVENT_NOALARM: 07989 i->inalarm = 0; 07990 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel); 07991 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 07992 "Channel: %d\r\n", i->channel); 07993 break; 07994 case DAHDI_EVENT_ALARM: 07995 i->inalarm = 1; 07996 res = get_alarms(i); 07997 handle_alarms(i, res); 07998 /* fall thru intentionally */ 07999 case DAHDI_EVENT_ONHOOK: 08000 if (i->radio) 08001 break; 08002 /* Back on hook. Hang up. */ 08003 switch (i->sig) { 08004 case SIG_FXOLS: 08005 case SIG_FXOGS: 08006 case SIG_FEATD: 08007 case SIG_FEATDMF: 08008 case SIG_FEATDMF_TA: 08009 case SIG_E911: 08010 case SIG_FGC_CAMA: 08011 case SIG_FGC_CAMAMF: 08012 case SIG_FEATB: 08013 case SIG_EM: 08014 case SIG_EM_E1: 08015 case SIG_EMWINK: 08016 case SIG_SF_FEATD: 08017 case SIG_SF_FEATDMF: 08018 case SIG_SF_FEATB: 08019 case SIG_SF: 08020 case SIG_SFWINK: 08021 case SIG_FXSLS: 08022 case SIG_FXSGS: 08023 case SIG_FXSKS: 08024 case SIG_GR303FXSKS: 08025 dahdi_disable_ec(i); 08026 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08027 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08028 break; 08029 case SIG_GR303FXOKS: 08030 case SIG_FXOKS: 08031 dahdi_disable_ec(i); 08032 /* Diddle the battery for the zhone */ 08033 #ifdef ZHONE_HACK 08034 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08035 usleep(1); 08036 #endif 08037 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08038 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08039 break; 08040 case SIG_PRI: 08041 case SIG_SS7: 08042 case SIG_BRI: 08043 case SIG_BRI_PTMP: 08044 dahdi_disable_ec(i); 08045 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08046 break; 08047 default: 08048 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 08049 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08050 return -1; 08051 } 08052 break; 08053 case DAHDI_EVENT_POLARITY: 08054 switch (i->sig) { 08055 case SIG_FXSLS: 08056 case SIG_FXSKS: 08057 case SIG_FXSGS: 08058 /* We have already got a PR before the channel was 08059 created, but it wasn't handled. We need polarity 08060 to be REV for remote hangup detection to work. 08061 At least in Spain */ 08062 if (i->hanguponpolarityswitch) 08063 i->polarity = POLARITY_REV; 08064 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) { 08065 i->polarity = POLARITY_REV; 08066 ast_verb(2, "Starting post polarity " 08067 "CID detection on channel %d\n", 08068 i->channel); 08069 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 08070 if (chan && ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 08071 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08072 } 08073 } 08074 break; 08075 default: 08076 ast_log(LOG_WARNING, "handle_init_event detected " 08077 "polarity reversal on non-FXO (SIG_FXS) " 08078 "interface %d\n", i->channel); 08079 } 08080 break; 08081 case DAHDI_EVENT_REMOVED: /* destroy channel */ 08082 ast_log(LOG_NOTICE, 08083 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 08084 i->channel); 08085 dahdi_destroy_channel_bynum(i->channel); 08086 break; 08087 case DAHDI_EVENT_NEONMWI_ACTIVE: 08088 if (i->mwimonitor_neon) { 08089 notify_message(i->mailbox, 1); 08090 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox); 08091 } 08092 break; 08093 case DAHDI_EVENT_NEONMWI_INACTIVE: 08094 if (i->mwimonitor_neon) { 08095 notify_message(i->mailbox, 0); 08096 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox); 08097 } 08098 break; 08099 } 08100 return 0; 08101 }
static char* handle_pri_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 11959 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_span_4(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, NUM_SPANS, ast_cli_args::pos, pris, ast_cli_entry::usage, and ast_cli_args::word.
11960 { 11961 int span; 11962 int x; 11963 switch (cmd) { 11964 case CLI_INIT: 11965 e->command = "pri debug span"; 11966 e->usage = 11967 "Usage: pri debug span <span>\n" 11968 " Enables debugging on a given PRI span\n"; 11969 return NULL; 11970 case CLI_GENERATE: 11971 return complete_span_4(a->line, a->word, a->pos, a->n); 11972 } 11973 if (a->argc < 4) { 11974 return CLI_SHOWUSAGE; 11975 } 11976 span = atoi(a->argv[3]); 11977 if ((span < 1) || (span > NUM_SPANS)) { 11978 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 11979 return CLI_SUCCESS; 11980 } 11981 if (!pris[span-1].pri) { 11982 ast_cli(a->fd, "No PRI running on span %d\n", span); 11983 return CLI_SUCCESS; 11984 } 11985 for (x = 0; x < NUM_DCHANS; x++) { 11986 if (pris[span-1].dchans[x]) 11987 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 11988 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 11989 PRI_DEBUG_Q921_STATE); 11990 } 11991 ast_cli(a->fd, "Enabled debugging on span %d\n", span); 11992 return CLI_SUCCESS; 11993 }
static char* handle_pri_no_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 11997 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_span_5(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, NUM_SPANS, ast_cli_args::pos, pris, ast_cli_entry::usage, and ast_cli_args::word.
11998 { 11999 int span; 12000 int x; 12001 switch (cmd) { 12002 case CLI_INIT: 12003 e->command = "pri no debug span"; 12004 e->usage = 12005 "Usage: pri no debug span <span>\n" 12006 " Disables debugging on a given PRI span\n"; 12007 return NULL; 12008 case CLI_GENERATE: 12009 return complete_span_5(a->line, a->word, a->pos, a->n); 12010 } 12011 if (a->argc < 5) 12012 return CLI_SHOWUSAGE; 12013 12014 span = atoi(a->argv[4]); 12015 if ((span < 1) || (span > NUM_SPANS)) { 12016 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS); 12017 return CLI_SUCCESS; 12018 } 12019 if (!pris[span-1].pri) { 12020 ast_cli(a->fd, "No PRI running on span %d\n", span); 12021 return CLI_SUCCESS; 12022 } 12023 for (x = 0; x < NUM_DCHANS; x++) { 12024 if (pris[span-1].dchans[x]) 12025 pri_set_debug(pris[span-1].dchans[x], 0); 12026 } 12027 ast_cli(a->fd, "Disabled debugging on span %d\n", span); 12028 return CLI_SUCCESS; 12029 }
static char* handle_pri_really_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12031 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_span_5(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, NUM_SPANS, ast_cli_args::pos, pris, ast_cli_entry::usage, and ast_cli_args::word.
12032 { 12033 int span; 12034 int x; 12035 switch (cmd) { 12036 case CLI_INIT: 12037 e->command = "pri intensive debug span"; 12038 e->usage = 12039 "Usage: pri intensive debug span <span>\n" 12040 " Enables debugging down to the Q.921 level\n"; 12041 return NULL; 12042 case CLI_GENERATE: 12043 return complete_span_5(a->line, a->word, a->pos, a->n); 12044 } 12045 12046 if (a->argc < 5) 12047 return CLI_SHOWUSAGE; 12048 span = atoi(a->argv[4]); 12049 if ((span < 1) || (span > NUM_SPANS)) { 12050 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS); 12051 return CLI_SUCCESS; 12052 } 12053 if (!pris[span-1].pri) { 12054 ast_cli(a->fd, "No PRI running on span %d\n", span); 12055 return CLI_SUCCESS; 12056 } 12057 for (x = 0; x < NUM_DCHANS; x++) { 12058 if (pris[span-1].dchans[x]) 12059 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 12060 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 12061 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE); 12062 } 12063 ast_cli(a->fd, "Enabled EXTENSIVE debugging on span %d\n", span); 12064 return CLI_SUCCESS; 12065 }
static char* handle_pri_set_debug_file | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 11923 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), AST_FILE_MODE, ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, pridebugfdlock, and ast_cli_entry::usage.
11924 { 11925 int myfd; 11926 switch (cmd) { 11927 case CLI_INIT: 11928 e->command = "pri set debug file"; 11929 e->usage = "Usage: pri set debug file [output-file]\n" 11930 " Sends PRI debug output to the specified output file\n"; 11931 return NULL; 11932 case CLI_GENERATE: 11933 return NULL; 11934 } 11935 if (a->argc < 5) 11936 return CLI_SHOWUSAGE; 11937 11938 if (ast_strlen_zero(a->argv[4])) 11939 return CLI_SHOWUSAGE; 11940 11941 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE); 11942 if (myfd < 0) { 11943 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]); 11944 return CLI_SUCCESS; 11945 } 11946 11947 ast_mutex_lock(&pridebugfdlock); 11948 11949 if (pridebugfd >= 0) 11950 close(pridebugfd); 11951 11952 pridebugfd = myfd; 11953 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename)); 11954 ast_mutex_unlock(&pridebugfdlock); 11955 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]); 11956 return CLI_SUCCESS; 11957 }
static char* handle_pri_show_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12171 of file chan_dahdi.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, debug, ast_cli_args::fd, NUM_SPANS, pridebugfdlock, and pris.
12172 { 12173 int x; 12174 int span; 12175 int count=0; 12176 int debug=0; 12177 12178 switch (cmd) { 12179 case CLI_INIT: 12180 e->command = "pri show debug"; 12181 return NULL; 12182 case CLI_GENERATE: 12183 return NULL; 12184 } 12185 12186 for (span = 0; span < NUM_SPANS; span++) { 12187 if (pris[span].pri) { 12188 for (x = 0; x < NUM_DCHANS; x++) { 12189 debug = 0; 12190 if (pris[span].dchans[x]) { 12191 debug = pri_get_debug(pris[span].dchans[x]); 12192 ast_cli(a->fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" ); 12193 count++; 12194 } 12195 } 12196 } 12197 12198 } 12199 ast_mutex_lock(&pridebugfdlock); 12200 if (pridebugfd >= 0) 12201 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename); 12202 ast_mutex_unlock(&pridebugfdlock); 12203 12204 if (!count) 12205 ast_cli(a->fd, "No debug set or no PRI running\n"); 12206 return CLI_SUCCESS; 12207 }
static char* handle_pri_show_span | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12121 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_free, build_status(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_span_4(), DAHDI_OVERLAPDIAL_INCOMING, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, NUM_SPANS, dahdi_pri::overlapdial, ast_cli_args::pos, pri_order(), pris, ast_cli_entry::usage, and ast_cli_args::word.
12122 { 12123 int span; 12124 int x; 12125 char status[256]; 12126 switch (cmd) { 12127 case CLI_INIT: 12128 e->command = "pri show span"; 12129 e->usage = 12130 "Usage: pri show span <span>\n" 12131 " Displays PRI Information on a given PRI span\n"; 12132 return NULL; 12133 case CLI_GENERATE: 12134 return complete_span_4(a->line, a->word, a->pos, a->n); 12135 } 12136 12137 if (a->argc < 4) 12138 return CLI_SHOWUSAGE; 12139 span = atoi(a->argv[3]); 12140 if ((span < 1) || (span > NUM_SPANS)) { 12141 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS); 12142 return CLI_SUCCESS; 12143 } 12144 if (!pris[span-1].pri) { 12145 ast_cli(a->fd, "No PRI running on span %d\n", span); 12146 return CLI_SUCCESS; 12147 } 12148 for (x = 0; x < NUM_DCHANS; x++) { 12149 if (pris[span-1].dchannels[x]) { 12150 #ifdef PRI_DUMP_INFO_STR 12151 char *info_str = NULL; 12152 #endif 12153 ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]); 12154 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri); 12155 ast_cli(a->fd, "Status: %s\n", status); 12156 #ifdef PRI_DUMP_INFO_STR 12157 info_str = pri_dump_info_str(pris[span-1].pri); 12158 if (info_str) { 12159 ast_cli(a->fd, "%s", info_str); 12160 ast_free(info_str); 12161 } 12162 #else 12163 pri_dump_info(pris[span-1].pri); 12164 #endif 12165 ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No"); 12166 } 12167 } 12168 return CLI_SUCCESS; 12169 }
static char* handle_pri_show_spans | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12088 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli(), build_status(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, NUM_SPANS, pris, and ast_cli_entry::usage.
12089 { 12090 int span; 12091 int x; 12092 char status[256]; 12093 12094 switch (cmd) { 12095 case CLI_INIT: 12096 e->command = "pri show spans"; 12097 e->usage = 12098 "Usage: pri show spans\n" 12099 " Displays PRI Information\n"; 12100 return NULL; 12101 case CLI_GENERATE: 12102 return NULL; 12103 } 12104 12105 if (a->argc != 3) 12106 return CLI_SHOWUSAGE; 12107 12108 for (span = 0; span < NUM_SPANS; span++) { 12109 if (pris[span].pri) { 12110 for (x = 0; x < NUM_DCHANS; x++) { 12111 if (pris[span].dchannels[x]) { 12112 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri); 12113 ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status); 12114 } 12115 } 12116 } 12117 } 12118 return CLI_SUCCESS; 12119 }
static char* handle_pri_unset_debug_file | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 11902 of file chan_dahdi.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, pridebugfdlock, and ast_cli_entry::usage.
11903 { 11904 switch (cmd) { 11905 case CLI_INIT: 11906 e->command = "pri unset debug file"; 11907 e->usage = "Usage: pri unset debug file\n" 11908 " Stop sending debug output to the previously \n" 11909 " specified file\n"; 11910 return NULL; 11911 case CLI_GENERATE: 11912 return NULL; 11913 } 11914 /* Assume it is unset */ 11915 ast_mutex_lock(&pridebugfdlock); 11916 close(pridebugfd); 11917 pridebugfd = -1; 11918 ast_cli(a->fd, "PRI debug output to file disabled\n"); 11919 ast_mutex_unlock(&pridebugfdlock); 11920 return CLI_SUCCESS; 11921 }
static int has_voicemail | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2349 of file chan_dahdi.c.
References ast_app_has_voicemail(), ast_event_destroy(), ast_event_get_cached(), ast_event_get_ie_uint(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_strdupa, ast_strlen_zero(), context, dahdi_pvt::mailbox, mailbox, and strsep().
Referenced by dahdi_handle_event(), do_housekeeping(), do_monitor(), handle_hd_hf(), handle_init_event(), handle_request(), load_module(), mgcp_hangup(), mgcp_request(), and vm_execmain().
02350 { 02351 int new_msgs; 02352 struct ast_event *event; 02353 char *mailbox, *context; 02354 02355 mailbox = context = ast_strdupa(p->mailbox); 02356 strsep(&context, "@"); 02357 if (ast_strlen_zero(context)) 02358 context = "default"; 02359 02360 event = ast_event_get_cached(AST_EVENT_MWI, 02361 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 02362 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 02363 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, 02364 AST_EVENT_IE_END); 02365 02366 if (event) { 02367 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 02368 ast_event_destroy(event); 02369 } else 02370 new_msgs = ast_app_has_voicemail(p->mailbox, NULL); 02371 02372 return new_msgs; 02373 }
static int isourconf | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c | |||
) | [static] |
Definition at line 1861 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::confno, and dahdi_subchannel::curconf.
Referenced by conf_del().
01862 { 01863 /* If they're listening to our channel, they're ours */ 01864 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON)) 01865 return 1; 01866 /* If they're a talker on our (allocated) conference, they're ours */ 01867 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER)) 01868 return 1; 01869 return 0; 01870 }
Definition at line 1891 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().
01892 { 01893 int x; 01894 int useslavenative; 01895 struct dahdi_pvt *slave = NULL; 01896 /* Start out optimistic */ 01897 useslavenative = 1; 01898 /* Update conference state in a stateless fashion */ 01899 for (x = 0; x < 3; x++) { 01900 /* Any three-way calling makes slave native mode *definitely* out 01901 of the question */ 01902 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) 01903 useslavenative = 0; 01904 } 01905 /* If we don't have any 3-way calls, check to see if we have 01906 precisely one slave */ 01907 if (useslavenative) { 01908 for (x = 0; x < MAX_SLAVES; x++) { 01909 if (p->slaves[x]) { 01910 if (slave) { 01911 /* Whoops already have a slave! No 01912 slave native and stop right away */ 01913 slave = NULL; 01914 useslavenative = 0; 01915 break; 01916 } else { 01917 /* We have one slave so far */ 01918 slave = p->slaves[x]; 01919 } 01920 } 01921 } 01922 } 01923 /* If no slave, slave native definitely out */ 01924 if (!slave) 01925 useslavenative = 0; 01926 else if (slave->law != p->law) { 01927 useslavenative = 0; 01928 slave = NULL; 01929 } 01930 if (out) 01931 *out = slave; 01932 return useslavenative; 01933 }
static int load_module | ( | void | ) | [static] |
Definition at line 14977 of file chan_dahdi.c.
References __unload_module(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdirestart(), action_dahdishowchannels(), action_transfer(), action_transferhangup(), ARRAY_LEN, ast_channel_register(), ast_cli_register_multiple(), ast_cond_init(), ast_log(), ast_manager_register, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, ast_mutex_init(), AST_PTHREADT_NULL, ast_register_application, ast_string_field_init, ast_string_field_set, dahdi_cli, dahdi_pri_cli, dahdi_pri_error(), dahdi_pri_message(), dahdi_send_keypad_facility_exec(), dahdi_tech, inuse, lock, LOG_ERROR, name, NUM_SPANS, pris, round_robin, and setup_dahdi().
14978 { 14979 int res; 14980 #if defined(HAVE_PRI) || defined(HAVE_SS7) 14981 int y, i; 14982 #endif 14983 14984 #ifdef HAVE_PRI 14985 memset(pris, 0, sizeof(pris)); 14986 for (y = 0; y < NUM_SPANS; y++) { 14987 ast_mutex_init(&pris[y].lock); 14988 pris[y].offset = -1; 14989 pris[y].master = AST_PTHREADT_NULL; 14990 for (i = 0; i < NUM_DCHANS; i++) 14991 pris[y].fds[i] = -1; 14992 } 14993 pri_set_error(dahdi_pri_error); 14994 pri_set_message(dahdi_pri_message); 14995 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec, 14996 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip); 14997 #endif 14998 #ifdef HAVE_SS7 14999 memset(linksets, 0, sizeof(linksets)); 15000 for (y = 0; y < NUM_SPANS; y++) { 15001 ast_mutex_init(&linksets[y].lock); 15002 linksets[y].master = AST_PTHREADT_NULL; 15003 for (i = 0; i < NUM_DCHANS; i++) 15004 linksets[y].fds[i] = -1; 15005 } 15006 ss7_set_error(dahdi_ss7_error); 15007 ss7_set_message(dahdi_ss7_message); 15008 #endif /* HAVE_SS7 */ 15009 res = setup_dahdi(0); 15010 /* Make sure we can register our DAHDI channel type */ 15011 if (res) 15012 return AST_MODULE_LOAD_DECLINE; 15013 if (ast_channel_register(&dahdi_tech)) { 15014 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n"); 15015 __unload_module(); 15016 return AST_MODULE_LOAD_FAILURE; 15017 } 15018 #ifdef HAVE_PRI 15019 ast_string_field_init(&inuse, 16); 15020 ast_string_field_set(&inuse, name, "GR-303InUse"); 15021 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry)); 15022 #endif 15023 #ifdef HAVE_SS7 15024 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli)); 15025 #endif 15026 15027 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 15028 15029 memset(round_robin, 0, sizeof(round_robin)); 15030 ast_manager_register("DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" ); 15031 ast_manager_register("DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" ); 15032 ast_manager_register("DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" ); 15033 ast_manager_register("DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" ); 15034 ast_manager_register("DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" ); 15035 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status dahdi channels"); 15036 ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)"); 15037 15038 ast_cond_init(&ss_thread_complete, NULL); 15039 15040 return res; 15041 }
static struct dahdi_pvt* mkintf | ( | int | channel, | |
const struct dahdi_chan_conf * | conf, | |||
struct dahdi_pri * | pri, | |||
int | reloading | |||
) | [static] |
Definition at line 8505 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_chan_conf::is_sig_auto, 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, 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_pri::sig, dahdi_pvt::sig, sig2str, SIG_BRI, SIG_BRI_PTMP, SIG_FXOKS, SIG_FXSKS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SIG_SS7, sigtype_to_signalling(), SUB_REAL, dahdi_pri::switchtype, and dahdi_pri::unknownprefix.
Referenced by build_channels().
08506 { 08507 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */ 08508 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL; 08509 char fn[80]; 08510 struct dahdi_bufferinfo bi; 08511 int res; 08512 int span = 0; 08513 int here = 0; 08514 int x; 08515 struct dahdi_pvt **wlist; 08516 struct dahdi_pvt **wend; 08517 struct dahdi_params p; 08518 08519 wlist = &iflist; 08520 wend = &ifend; 08521 08522 #ifdef HAVE_PRI 08523 if (pri) { 08524 wlist = &pri->crvs; 08525 wend = &pri->crvend; 08526 } 08527 #endif 08528 08529 tmp2 = *wlist; 08530 prev = NULL; 08531 08532 while (tmp2) { 08533 if (!tmp2->destroy) { 08534 if (tmp2->channel == channel) { 08535 tmp = tmp2; 08536 here = 1; 08537 break; 08538 } 08539 if (tmp2->channel > channel) { 08540 break; 08541 } 08542 } 08543 prev = tmp2; 08544 tmp2 = tmp2->next; 08545 } 08546 08547 if (!here && reloading != 1) { 08548 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { 08549 if (tmp) 08550 free(tmp); 08551 return NULL; 08552 } 08553 ast_mutex_init(&tmp->lock); 08554 ifcount++; 08555 for (x = 0; x < 3; x++) 08556 tmp->subs[x].dfd = -1; 08557 tmp->channel = channel; 08558 } 08559 08560 if (tmp) { 08561 int chan_sig = conf->chan.sig; 08562 if (!here) { 08563 if ((channel != CHAN_PSEUDO) && !pri) { 08564 int count = 0; 08565 snprintf(fn, sizeof(fn), "%d", channel); 08566 /* Open non-blocking */ 08567 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 08568 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 */ 08569 usleep(1); 08570 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 08571 count++; 08572 } 08573 /* Allocate a DAHDI structure */ 08574 if (tmp->subs[SUB_REAL].dfd < 0) { 08575 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); 08576 destroy_dahdi_pvt(&tmp); 08577 return NULL; 08578 } 08579 memset(&p, 0, sizeof(p)); 08580 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 08581 if (res < 0) { 08582 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno)); 08583 destroy_dahdi_pvt(&tmp); 08584 return NULL; 08585 } 08586 if (conf->is_sig_auto) 08587 chan_sig = sigtype_to_signalling(p.sigtype); 08588 if (p.sigtype != (chan_sig & 0x3ffff)) { 08589 ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(chan_sig), sig2str(p.sigtype)); 08590 destroy_dahdi_pvt(&tmp); 08591 return NULL; 08592 } 08593 tmp->law = p.curlaw; 08594 tmp->span = p.spanno; 08595 span = p.spanno - 1; 08596 } else { 08597 if (channel == CHAN_PSEUDO) 08598 chan_sig = 0; 08599 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) { 08600 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n"); 08601 return NULL; 08602 } 08603 } 08604 #ifdef HAVE_SS7 08605 if (chan_sig == SIG_SS7) { 08606 struct dahdi_ss7 *ss7; 08607 int clear = 0; 08608 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) { 08609 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 08610 destroy_dahdi_pvt(&tmp); 08611 return NULL; 08612 } 08613 08614 ss7 = ss7_resolve_linkset(cur_linkset); 08615 if (!ss7) { 08616 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset); 08617 destroy_dahdi_pvt(&tmp); 08618 return NULL; 08619 } 08620 if (cur_cicbeginswith < 0) { 08621 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n"); 08622 destroy_dahdi_pvt(&tmp); 08623 return NULL; 08624 } 08625 08626 tmp->cic = cur_cicbeginswith++; 08627 08628 /* DB: Add CIC's DPC information */ 08629 tmp->dpc = cur_defaultdpc; 08630 08631 tmp->ss7 = ss7; 08632 tmp->ss7call = NULL; 08633 ss7->pvts[ss7->numchans++] = tmp; 08634 08635 ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix)); 08636 ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix)); 08637 ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix)); 08638 ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix)); 08639 08640 ss7->called_nai = conf->ss7.called_nai; 08641 ss7->calling_nai = conf->ss7.calling_nai; 08642 } 08643 #endif 08644 #ifdef HAVE_PRI 08645 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) { 08646 int offset; 08647 int myswitchtype; 08648 int matchesdchan; 08649 int x,y; 08650 offset = 0; 08651 if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP)) 08652 && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) { 08653 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 08654 destroy_dahdi_pvt(&tmp); 08655 return NULL; 08656 } 08657 if (span >= NUM_SPANS) { 08658 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span); 08659 destroy_dahdi_pvt(&tmp); 08660 return NULL; 08661 } else { 08662 struct dahdi_spaninfo si; 08663 si.spanno = 0; 08664 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) { 08665 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); 08666 destroy_dahdi_pvt(&tmp); 08667 return NULL; 08668 } 08669 /* Store the logical span first based upon the real span */ 08670 tmp->logicalspan = pris[span].prilogicalspan; 08671 pri_resolve_span(&span, channel, (channel - p.chanpos), &si); 08672 if (span < 0) { 08673 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel); 08674 destroy_dahdi_pvt(&tmp); 08675 return NULL; 08676 } 08677 if ((chan_sig == SIG_PRI) || 08678 (chan_sig == SIG_BRI) || 08679 (chan_sig == SIG_BRI_PTMP)) 08680 myswitchtype = conf->pri.switchtype; 08681 else 08682 myswitchtype = PRI_SWITCH_GR303_TMC; 08683 /* Make sure this isn't a d-channel */ 08684 matchesdchan=0; 08685 for (x = 0; x < NUM_SPANS; x++) { 08686 for (y = 0; y < NUM_DCHANS; y++) { 08687 if (pris[x].dchannels[y] == tmp->channel) { 08688 matchesdchan = 1; 08689 break; 08690 } 08691 } 08692 } 08693 offset = p.chanpos; 08694 if (!matchesdchan) { 08695 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) { 08696 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype)); 08697 destroy_dahdi_pvt(&tmp); 08698 return NULL; 08699 } 08700 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) { 08701 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype)); 08702 destroy_dahdi_pvt(&tmp); 08703 return NULL; 08704 } 08705 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) { 08706 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan)); 08707 destroy_dahdi_pvt(&tmp); 08708 return NULL; 08709 } 08710 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) { 08711 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial); 08712 destroy_dahdi_pvt(&tmp); 08713 return NULL; 08714 } 08715 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) { 08716 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext); 08717 destroy_dahdi_pvt(&tmp); 08718 return NULL; 08719 } 08720 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) { 08721 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused); 08722 destroy_dahdi_pvt(&tmp); 08723 return NULL; 08724 } 08725 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) { 08726 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle); 08727 destroy_dahdi_pvt(&tmp); 08728 return NULL; 08729 } 08730 if (pris[span].numchans >= MAX_CHANNELS) { 08731 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, 08732 pris[span].trunkgroup); 08733 destroy_dahdi_pvt(&tmp); 08734 return NULL; 08735 } 08736 08737 pris[span].sig = chan_sig; 08738 pris[span].nodetype = conf->pri.nodetype; 08739 pris[span].switchtype = myswitchtype; 08740 pris[span].nsf = conf->pri.nsf; 08741 pris[span].dialplan = conf->pri.dialplan; 08742 pris[span].localdialplan = conf->pri.localdialplan; 08743 pris[span].pvts[pris[span].numchans++] = tmp; 08744 pris[span].minunused = conf->pri.minunused; 08745 pris[span].minidle = conf->pri.minidle; 08746 pris[span].overlapdial = conf->pri.overlapdial; 08747 #ifdef HAVE_PRI_INBANDDISCONNECT 08748 pris[span].inbanddisconnect = conf->pri.inbanddisconnect; 08749 #endif 08750 pris[span].facilityenable = conf->pri.facilityenable; 08751 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial)); 08752 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext)); 08753 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix)); 08754 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix)); 08755 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix)); 08756 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix)); 08757 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix)); 08758 pris[span].resetinterval = conf->pri.resetinterval; 08759 08760 tmp->pri = &pris[span]; 08761 tmp->prioffset = offset; 08762 tmp->call = NULL; 08763 } else { 08764 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset); 08765 destroy_dahdi_pvt(&tmp); 08766 return NULL; 08767 } 08768 } 08769 } else { 08770 tmp->prioffset = 0; 08771 } 08772 #endif 08773 } else { 08774 chan_sig = tmp->sig; 08775 if (tmp->subs[SUB_REAL].dfd > -1) { 08776 memset(&p, 0, sizeof(p)); 08777 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 08778 } 08779 } 08780 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */ 08781 switch (chan_sig) { 08782 case SIG_FXSKS: 08783 case SIG_FXSLS: 08784 case SIG_EM: 08785 case SIG_EM_E1: 08786 case SIG_EMWINK: 08787 case SIG_FEATD: 08788 case SIG_FEATDMF: 08789 case SIG_FEATDMF_TA: 08790 case SIG_FEATB: 08791 case SIG_E911: 08792 case SIG_SF: 08793 case SIG_SFWINK: 08794 case SIG_FGC_CAMA: 08795 case SIG_FGC_CAMAMF: 08796 case SIG_SF_FEATD: 08797 case SIG_SF_FEATDMF: 08798 case SIG_SF_FEATB: 08799 p.starttime = 250; 08800 break; 08801 } 08802 08803 if (tmp->radio) { 08804 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */ 08805 p.channo = channel; 08806 p.rxwinktime = 1; 08807 p.rxflashtime = 1; 08808 p.starttime = 1; 08809 p.debouncetime = 5; 08810 } 08811 if (!tmp->radio) { 08812 p.channo = channel; 08813 /* Override timing settings based on config file */ 08814 if (conf->timing.prewinktime >= 0) 08815 p.prewinktime = conf->timing.prewinktime; 08816 if (conf->timing.preflashtime >= 0) 08817 p.preflashtime = conf->timing.preflashtime; 08818 if (conf->timing.winktime >= 0) 08819 p.winktime = conf->timing.winktime; 08820 if (conf->timing.flashtime >= 0) 08821 p.flashtime = conf->timing.flashtime; 08822 if (conf->timing.starttime >= 0) 08823 p.starttime = conf->timing.starttime; 08824 if (conf->timing.rxwinktime >= 0) 08825 p.rxwinktime = conf->timing.rxwinktime; 08826 if (conf->timing.rxflashtime >= 0) 08827 p.rxflashtime = conf->timing.rxflashtime; 08828 if (conf->timing.debouncetime >= 0) 08829 p.debouncetime = conf->timing.debouncetime; 08830 } 08831 08832 /* dont set parms on a pseudo-channel (or CRV) */ 08833 if (tmp->subs[SUB_REAL].dfd >= 0) 08834 { 08835 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p); 08836 if (res < 0) { 08837 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno)); 08838 destroy_dahdi_pvt(&tmp); 08839 return NULL; 08840 } 08841 } 08842 #if 1 08843 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) { 08844 memset(&bi, 0, sizeof(bi)); 08845 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 08846 if (!res) { 08847 bi.txbufpolicy = conf->chan.buf_policy; 08848 bi.rxbufpolicy = conf->chan.buf_policy; 08849 bi.numbufs = conf->chan.buf_no; 08850 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 08851 if (res < 0) { 08852 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno)); 08853 } 08854 } else 08855 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno)); 08856 } 08857 #endif 08858 tmp->immediate = conf->chan.immediate; 08859 tmp->transfertobusy = conf->chan.transfertobusy; 08860 if (chan_sig & __DAHDI_SIG_FXS) { 08861 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk; 08862 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon; 08863 } 08864 tmp->sig = chan_sig; 08865 tmp->outsigmod = conf->chan.outsigmod; 08866 tmp->ringt_base = ringt_base; 08867 tmp->firstradio = 0; 08868 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS)) 08869 tmp->permcallwaiting = conf->chan.callwaiting; 08870 else 08871 tmp->permcallwaiting = 0; 08872 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */ 08873 tmp->destroy = 0; 08874 tmp->drings = conf->chan.drings; 08875 08876 /* 10 is a nice default. */ 08877 if (tmp->drings.ringnum[0].range == 0) 08878 tmp->drings.ringnum[0].range = 10; 08879 if (tmp->drings.ringnum[1].range == 0) 08880 tmp->drings.ringnum[1].range = 10; 08881 if (tmp->drings.ringnum[2].range == 0) 08882 tmp->drings.ringnum[2].range = 10; 08883 08884 tmp->usedistinctiveringdetection = usedistinctiveringdetection; 08885 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid; 08886 tmp->threewaycalling = conf->chan.threewaycalling; 08887 tmp->adsi = conf->chan.adsi; 08888 tmp->use_smdi = conf->chan.use_smdi; 08889 tmp->permhidecallerid = conf->chan.hidecallerid; 08890 tmp->callreturn = conf->chan.callreturn; 08891 tmp->echocancel = conf->chan.echocancel; 08892 tmp->echotraining = conf->chan.echotraining; 08893 tmp->pulse = conf->chan.pulse; 08894 if (tmp->echocancel.head.tap_length) { 08895 tmp->echocanbridged = conf->chan.echocanbridged; 08896 } else { 08897 if (conf->chan.echocanbridged) 08898 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n"); 08899 tmp->echocanbridged = 0; 08900 } 08901 tmp->busydetect = conf->chan.busydetect; 08902 tmp->busycount = conf->chan.busycount; 08903 tmp->busycompare = conf->chan.busycompare; 08904 tmp->busytonelength = conf->chan.busytonelength; 08905 tmp->busyquietlength = conf->chan.busyquietlength; 08906 tmp->busyfuzziness = conf->chan.busyfuzziness; 08907 tmp->silencethreshold = conf->chan.silencethreshold; 08908 tmp->callprogress = conf->chan.callprogress; 08909 tmp->cancallforward = conf->chan.cancallforward; 08910 tmp->dtmfrelax = conf->chan.dtmfrelax; 08911 tmp->callwaiting = tmp->permcallwaiting; 08912 tmp->hidecallerid = tmp->permhidecallerid; 08913 tmp->channel = channel; 08914 tmp->stripmsd = conf->chan.stripmsd; 08915 tmp->use_callerid = conf->chan.use_callerid; 08916 tmp->cid_signalling = conf->chan.cid_signalling; 08917 tmp->cid_start = conf->chan.cid_start; 08918 tmp->dahditrcallerid = conf->chan.dahditrcallerid; 08919 tmp->restrictcid = conf->chan.restrictcid; 08920 tmp->use_callingpres = conf->chan.use_callingpres; 08921 tmp->priindication_oob = conf->chan.priindication_oob; 08922 tmp->priexclusive = conf->chan.priexclusive; 08923 if (tmp->usedistinctiveringdetection) { 08924 if (!tmp->use_callerid) { 08925 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n"); 08926 tmp->use_callerid = 1; 08927 } 08928 } 08929 08930 if (tmp->cid_signalling == CID_SIG_SMDI) { 08931 if (!tmp->use_smdi) { 08932 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n"); 08933 tmp->use_smdi = 1; 08934 } 08935 } 08936 if (tmp->use_smdi) { 08937 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port); 08938 if (!(tmp->smdi_iface)) { 08939 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n"); 08940 tmp->use_smdi = 0; 08941 } 08942 } 08943 08944 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode)); 08945 tmp->amaflags = conf->chan.amaflags; 08946 if (!here) { 08947 tmp->confno = -1; 08948 tmp->propconfno = -1; 08949 } 08950 tmp->canpark = conf->chan.canpark; 08951 tmp->transfer = conf->chan.transfer; 08952 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext)); 08953 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language)); 08954 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret)); 08955 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest)); 08956 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context)); 08957 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num)); 08958 tmp->cid_ton = 0; 08959 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name)); 08960 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox)); 08961 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) { 08962 char *mailbox, *context; 08963 mailbox = context = ast_strdupa(tmp->mailbox); 08964 strsep(&context, "@"); 08965 if (ast_strlen_zero(context)) 08966 context = "default"; 08967 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL, 08968 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 08969 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 08970 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, 08971 AST_EVENT_IE_END); 08972 } 08973 tmp->msgstate = -1; 08974 tmp->group = conf->chan.group; 08975 tmp->callgroup = conf->chan.callgroup; 08976 tmp->pickupgroup= conf->chan.pickupgroup; 08977 if (conf->chan.vars) { 08978 tmp->vars = conf->chan.vars; 08979 } 08980 tmp->cid_rxgain = conf->chan.cid_rxgain; 08981 tmp->rxgain = conf->chan.rxgain; 08982 tmp->txgain = conf->chan.txgain; 08983 tmp->tonezone = conf->chan.tonezone; 08984 tmp->onhooktime = time(NULL); 08985 if (tmp->subs[SUB_REAL].dfd > -1) { 08986 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law); 08987 if (tmp->dsp) 08988 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax); 08989 update_conf(tmp); 08990 if (!here) { 08991 if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI) && (chan_sig != SIG_SS7)) 08992 /* Hang it up to be sure it's good */ 08993 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08994 } 08995 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone); 08996 #ifdef HAVE_PRI 08997 /* the dchannel is down so put the channel in alarm */ 08998 if (tmp->pri && !pri_is_up(tmp->pri)) 08999 tmp->inalarm = 1; 09000 #endif 09001 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) { 09002 tmp->inalarm = 1; 09003 handle_alarms(tmp, res); 09004 } 09005 } 09006 09007 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 09008 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 09009 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 09010 tmp->sendcalleridafter = conf->chan.sendcalleridafter; 09011 if (!here) { 09012 tmp->locallyblocked = tmp->remotelyblocked = 0; 09013 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7)) 09014 tmp->inservice = 0; 09015 else /* We default to in service on protocols that don't have a reset */ 09016 tmp->inservice = 1; 09017 } 09018 } 09019 if (tmp && !here) { 09020 /* nothing on the iflist */ 09021 if (!*wlist) { 09022 *wlist = tmp; 09023 tmp->prev = NULL; 09024 tmp->next = NULL; 09025 *wend = tmp; 09026 } else { 09027 /* at least one member on the iflist */ 09028 struct dahdi_pvt *working = *wlist; 09029 09030 /* check if we maybe have to put it on the begining */ 09031 if (working->channel > tmp->channel) { 09032 tmp->next = *wlist; 09033 tmp->prev = NULL; 09034 (*wlist)->prev = tmp; 09035 *wlist = tmp; 09036 } else { 09037 /* go through all the members and put the member in the right place */ 09038 while (working) { 09039 /* in the middle */ 09040 if (working->next) { 09041 if (working->channel < tmp->channel && working->next->channel > tmp->channel) { 09042 tmp->next = working->next; 09043 tmp->prev = working; 09044 working->next->prev = tmp; 09045 working->next = tmp; 09046 break; 09047 } 09048 } else { 09049 /* the last */ 09050 if (working->channel < tmp->channel) { 09051 working->next = tmp; 09052 tmp->next = NULL; 09053 tmp->prev = working; 09054 *wend = tmp; 09055 break; 09056 } 09057 } 09058 working = working->next; 09059 } 09060 } 09061 } 09062 } 09063 return tmp; 09064 }
static void mwi_event_cb | ( | const struct ast_event * | event, | |
void * | userdata | |||
) | [static] |
Definition at line 288 of file chan_dahdi.c.
Referenced by add_peer_mwi_subs(), build_device(), build_gateway(), and build_peer().
00289 { 00290 /* This module does not handle MWI in an event-based manner. However, it 00291 * subscribes to MWI for each mailbox that is configured so that the core 00292 * knows that we care about it. Then, chan_dahdi will get the MWI from the 00293 * event cache instead of checking the mailbox directly. */ 00294 }
static void* mwi_thread | ( | void * | data | ) | [static] |
Definition at line 7731 of file chan_dahdi.c.
References ast_hangup(), AST_LAW, ast_log(), ast_pthread_create_detached, AST_STATE_RING, mwi_thread_data::buf, bump_gains(), calc_energy(), callerid_feed(), callerid_free(), callerid_new(), chan, dahdi_pvt::channel, dahdi_pvt::cid_signalling, dahdi_get_event(), dahdi_new(), errno, event2str(), EVENT_FLAG_SYSTEM, callerid_state::flags, get_alarms(), handle_alarms(), dahdi_pvt::inalarm, mwi_thread_data::len, LOG_NOTICE, manager_event, dahdi_pvt::mwimonitoractive, name, mwi_thread_data::pvt, quit, restore_gains(), dahdi_pvt::ringt, dahdi_pvt::ringt_base, ss_thread(), SUB_REAL, and dahdi_pvt::subs.
07732 { 07733 struct mwi_thread_data *mtd = data; 07734 struct callerid_state *cs; 07735 pthread_t threadid; 07736 int samples = 0; 07737 char *name, *number; 07738 int flags; 07739 int i, res; 07740 unsigned int spill_done = 0; 07741 int spill_result = -1; 07742 07743 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) { 07744 mtd->pvt->mwimonitoractive = 0; 07745 07746 return NULL; 07747 } 07748 07749 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt)); 07750 07751 bump_gains(mtd->pvt); 07752 07753 for (;;) { 07754 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07755 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) { 07756 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07757 goto quit; 07758 } 07759 07760 if (i & DAHDI_IOMUX_SIGEVENT) { 07761 struct ast_channel *chan; 07762 07763 /* If we get an event, screen out events that we do not act on. 07764 * Otherwise, cancel and go to the simple switch to let it deal with it. 07765 */ 07766 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd); 07767 07768 switch (res) { 07769 case DAHDI_EVENT_NEONMWI_ACTIVE: 07770 case DAHDI_EVENT_NEONMWI_INACTIVE: 07771 case DAHDI_EVENT_NONE: 07772 case DAHDI_EVENT_BITSCHANGED: 07773 break; 07774 case DAHDI_EVENT_NOALARM: 07775 mtd->pvt->inalarm = 0; 07776 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel); 07777 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 07778 "Channel: %d\r\n", mtd->pvt->channel); 07779 break; 07780 case DAHDI_EVENT_ALARM: 07781 mtd->pvt->inalarm = 1; 07782 res = get_alarms(mtd->pvt); 07783 handle_alarms(mtd->pvt, res); 07784 break; /* What to do on channel alarm ???? -- fall thru intentionally?? */ 07785 default: 07786 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to ss_thread\n", res, event2str(res)); 07787 callerid_free(cs); 07788 07789 restore_gains(mtd->pvt); 07790 mtd->pvt->ringt = mtd->pvt->ringt_base; 07791 07792 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) { 07793 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 07794 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel); 07795 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07796 if (res < 0) 07797 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel); 07798 ast_hangup(chan); 07799 goto quit; 07800 } 07801 goto quit_no_clean; 07802 07803 } else { 07804 ast_log(LOG_WARNING, "Could not create channel to handle call\n"); 07805 } 07806 } 07807 } else if (i & DAHDI_IOMUX_READ) { 07808 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) { 07809 if (errno != ELAST) { 07810 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07811 goto quit; 07812 } 07813 break; 07814 } 07815 samples += res; 07816 if (!spill_done) { 07817 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) { 07818 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno)); 07819 break; 07820 } else if (spill_result) { 07821 spill_done = 1; 07822 } 07823 } else { 07824 /* keep reading data until the energy level drops below the threshold 07825 so we don't get another 'trigger' on the remaining carrier signal 07826 */ 07827 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel) 07828 break; 07829 } 07830 if (samples > (8000 * 4)) /*Termination case - time to give up*/ 07831 break; 07832 } 07833 } 07834 07835 if (spill_result == 1) { 07836 callerid_get(cs, &name, &number, &flags); 07837 if (flags & CID_MSGWAITING) { 07838 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel); 07839 notify_message(mtd->pvt->mailbox, 1); 07840 } else if (flags & CID_NOMSGWAITING) { 07841 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel); 07842 notify_message(mtd->pvt->mailbox, 0); 07843 } else { 07844 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel); 07845 } 07846 } 07847 07848 07849 quit: 07850 callerid_free(cs); 07851 07852 restore_gains(mtd->pvt); 07853 07854 quit_no_clean: 07855 mtd->pvt->mwimonitoractive = 0; 07856 07857 ast_free(mtd); 07858 07859 return NULL; 07860 }
static int my_dahdi_write | ( | struct dahdi_pvt * | p, | |
unsigned char * | buf, | |||
int | len, | |||
int | index, | |||
int | linear | |||
) | [static] |
Definition at line 5939 of file chan_dahdi.c.
References ast_debug, dahdi_pvt::channel, dahdi_subchannel::dfd, errno, READ_SIZE, and dahdi_pvt::subs.
Referenced by dahdi_write().
05940 { 05941 int sent=0; 05942 int size; 05943 int res; 05944 int fd; 05945 fd = p->subs[index].dfd; 05946 while (len) { 05947 size = len; 05948 if (size > (linear ? READ_SIZE * 2 : READ_SIZE)) 05949 size = (linear ? READ_SIZE * 2 : READ_SIZE); 05950 res = write(fd, buf, size); 05951 if (res != size) { 05952 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 05953 return sent; 05954 } 05955 len -= size; 05956 buf += size; 05957 } 05958 return sent; 05959 }
static int my_getsigstr | ( | struct ast_channel * | chan, | |
char * | str, | |||
const char * | term, | |||
int | ms | |||
) | [static] |
Definition at line 6462 of file chan_dahdi.c.
References ast_waitfordigit(), and chan.
Referenced by ss_thread().
06463 { 06464 char c; 06465 06466 *str = 0; /* start with empty output buffer */ 06467 for (;;) 06468 { 06469 /* Wait for the first digit (up to specified ms). */ 06470 c = ast_waitfordigit(chan, ms); 06471 /* if timeout, hangup or error, return as such */ 06472 if (c < 1) 06473 return c; 06474 *str++ = c; 06475 *str = 0; 06476 if (strchr(term, c)) 06477 return 1; 06478 } 06479 }
static void notify_message | ( | char * | mailbox_full, | |
int | thereornot | |||
) | [static] |
Send MWI state change.
1) It generates an internal Asterisk event notifying any other module that cares about MWI that the state of a mailbox has changed.
2) It runs the script specified by the mwimonitornotify option to allow some custom handling of the state change.
Definition at line 2285 of file chan_dahdi.c.
References AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI, ast_event_new(), ast_event_queue_and_cache(), ast_safe_system(), ast_strdupa, ast_strlen_zero(), context, mailbox, s, and strsep().
Referenced by handle_init_event().
02286 { 02287 char s[sizeof(mwimonitornotify) + 80]; 02288 struct ast_event *event; 02289 char *mailbox, *context; 02290 02291 /* Strip off @default */ 02292 context = mailbox = ast_strdupa(mailbox_full); 02293 strsep(&context, "@"); 02294 if (ast_strlen_zero(context)) 02295 context = "default"; 02296 02297 if (!(event = ast_event_new(AST_EVENT_MWI, 02298 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 02299 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 02300 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 02301 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 02302 AST_EVENT_IE_END))) { 02303 return; 02304 } 02305 02306 ast_event_queue_and_cache(event, 02307 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, 02308 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, 02309 AST_EVENT_IE_END); 02310 02311 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) { 02312 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot); 02313 ast_safe_system(s); 02314 } 02315 }
static int pri_active_dchan_fd | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3337 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().
03338 { 03339 int x = -1; 03340 03341 for (x = 0; x < NUM_DCHANS; x++) { 03342 if ((pri->dchans[x] == pri->pri)) 03343 break; 03344 } 03345 03346 return pri->fds[x]; 03347 }
static int pri_assign_bearer | ( | struct dahdi_pvt * | crv, | |
struct dahdi_pri * | pri, | |||
struct dahdi_pvt * | bearer | |||
) | [static] |
Definition at line 3307 of file chan_dahdi.c.
References ast_channel_set_fd(), dahdi_pvt::bearer, dahdi_pvt::call, dahdi_subchannel::dfd, inuse, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::realcall, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_request().
03308 { 03309 bearer->owner = &inuse; 03310 bearer->realcall = crv; 03311 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd; 03312 if (crv->subs[SUB_REAL].owner) 03313 ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd); 03314 crv->bearer = bearer; 03315 crv->call = bearer->call; 03316 crv->pri = pri; 03317 return 0; 03318 }
static int pri_check_restart | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 10575 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().
10576 { 10577 do { 10578 pri->resetpos++; 10579 } while ((pri->resetpos < pri->numchans) && 10580 (!pri->pvts[pri->resetpos] || 10581 pri->pvts[pri->resetpos]->call || 10582 pri->pvts[pri->resetpos]->resetting)); 10583 if (pri->resetpos < pri->numchans) { 10584 /* Mark the channel as resetting and restart it */ 10585 pri->pvts[pri->resetpos]->resetting = 1; 10586 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos])); 10587 } else { 10588 pri->resetting = 0; 10589 time(&pri->lastreset); 10590 } 10591 return 0; 10592 }
static int pri_create_spanmap | ( | int | span, | |
int | trunkgroup, | |||
int | logicalspan | |||
) | [static] |
Definition at line 8457 of file chan_dahdi.c.
References ast_log(), dahdi_pri::mastertrunkgroup, dahdi_pri::prilogicalspan, and pris.
Referenced by setup_dahdi().
08458 { 08459 if (pris[span].mastertrunkgroup) { 08460 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); 08461 return -1; 08462 } 08463 pris[span].mastertrunkgroup = trunkgroup; 08464 pris[span].prilogicalspan = logicalspan; 08465 return 0; 08466 }
static int pri_create_trunkgroup | ( | int | trunkgroup, | |
int * | channels | |||
) | [static] |
Definition at line 8394 of file chan_dahdi.c.
References ast_log(), DCHAN_PROVISIONED, dahdi_pri::dchanavail, dahdi_pri::dchannels, errno, NUM_DCHANS, NUM_SPANS, dahdi_pri::offset, pris, pvts, dahdi_pri::span, and dahdi_pri::trunkgroup.
Referenced by setup_dahdi().
08395 { 08396 struct dahdi_spaninfo si; 08397 struct dahdi_params p; 08398 int fd; 08399 int span; 08400 int ospan=0; 08401 int x,y; 08402 for (x = 0; x < NUM_SPANS; x++) { 08403 if (pris[x].trunkgroup == trunkgroup) { 08404 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]); 08405 return -1; 08406 } 08407 } 08408 for (y = 0; y < NUM_DCHANS; y++) { 08409 if (!channels[y]) 08410 break; 08411 memset(&si, 0, sizeof(si)); 08412 memset(&p, 0, sizeof(p)); 08413 fd = open("/dev/dahdi/channel", O_RDWR); 08414 if (fd < 0) { 08415 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno)); 08416 return -1; 08417 } 08418 x = channels[y]; 08419 if (ioctl(fd, DAHDI_SPECIFY, &x)) { 08420 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno)); 08421 close(fd); 08422 return -1; 08423 } 08424 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) { 08425 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno)); 08426 return -1; 08427 } 08428 if (ioctl(fd, DAHDI_SPANSTAT, &si)) { 08429 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno)); 08430 close(fd); 08431 return -1; 08432 } 08433 span = p.spanno - 1; 08434 if (pris[span].trunkgroup) { 08435 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup); 08436 close(fd); 08437 return -1; 08438 } 08439 if (pris[span].pvts[0]) { 08440 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1); 08441 close(fd); 08442 return -1; 08443 } 08444 if (!y) { 08445 pris[span].trunkgroup = trunkgroup; 08446 pris[span].offset = channels[y] - p.chanpos; 08447 ospan = span; 08448 } 08449 pris[ospan].dchannels[y] = channels[y]; 08450 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED; 08451 pris[span].span = span + 1; 08452 close(fd); 08453 } 08454 return 0; 08455 }
static void* pri_dchannel | ( | void * | vpri | ) | [static] |
Definition at line 10669 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_hangup(), dahdi_request(), dahdi_pri::dchannels, dahdi_pri::dchans, do_idle_thread(), dahdi_pri::fds, dahdi_pri::idlecontext, dahdi_pri::idledial, dahdi_pri::idleext, dahdi_pvt::isidlecall, dahdi_pri::lastreset, dahdi_pri::lock, dahdi_pri::minidle, dahdi_pri::minunused, ast_channel::name, dahdi_pri::numchans, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pri::pri, pri_check_restart(), pri_is_up(), dahdi_pri::pvts, dahdi_pri::resetinterval, dahdi_pri::resetpos, dahdi_pvt::resetting, dahdi_pri::resetting, and dahdi_pri::switchtype.
10670 { 10671 struct dahdi_pri *pri = vpri; 10672 pri_event *e; 10673 struct pollfd fds[NUM_DCHANS]; 10674 int res; 10675 int chanpos = 0; 10676 int x; 10677 int haveidles; 10678 int activeidles; 10679 int nextidle = -1; 10680 struct ast_channel *c; 10681 struct timeval tv, lowest, *next; 10682 struct timeval lastidle = ast_tvnow(); 10683 int doidling=0; 10684 char *cc; 10685 char idlen[80]; 10686 struct ast_channel *idle; 10687 pthread_t p; 10688 time_t t; 10689 int i, which=-1; 10690 int numdchans; 10691 int cause=0; 10692 struct dahdi_pvt *crv; 10693 pthread_t threadid; 10694 char ani2str[6]; 10695 char plancallingnum[256]; 10696 char plancallingani[256]; 10697 char calledtonstr[10]; 10698 10699 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 10700 10701 gettimeofday(&lastidle, NULL); 10702 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) { 10703 /* Need to do idle dialing, check to be sure though */ 10704 cc = strchr(pri->idleext, '@'); 10705 if (cc) { 10706 *cc = '\0'; 10707 cc++; 10708 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext)); 10709 #if 0 10710 /* Extensions may not be loaded yet */ 10711 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL)) 10712 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext); 10713 else 10714 #endif 10715 doidling = 1; 10716 } else 10717 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext); 10718 } 10719 for (;;) { 10720 for (i = 0; i < NUM_DCHANS; i++) { 10721 if (!pri->dchannels[i]) 10722 break; 10723 fds[i].fd = pri->fds[i]; 10724 fds[i].events = POLLIN | POLLPRI; 10725 fds[i].revents = 0; 10726 } 10727 numdchans = i; 10728 time(&t); 10729 ast_mutex_lock(&pri->lock); 10730 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) { 10731 if (pri->resetting && pri_is_up(pri)) { 10732 if (pri->resetpos < 0) 10733 pri_check_restart(pri); 10734 } else { 10735 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) { 10736 pri->resetting = 1; 10737 pri->resetpos = -1; 10738 } 10739 } 10740 } 10741 /* Look for any idle channels if appropriate */ 10742 if (doidling && pri_is_up(pri)) { 10743 nextidle = -1; 10744 haveidles = 0; 10745 activeidles = 0; 10746 for (x = pri->numchans; x >= 0; x--) { 10747 if (pri->pvts[x] && !pri->pvts[x]->owner && 10748 !pri->pvts[x]->call) { 10749 if (haveidles < pri->minunused) { 10750 haveidles++; 10751 } else if (!pri->pvts[x]->resetting) { 10752 nextidle = x; 10753 break; 10754 } 10755 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) 10756 activeidles++; 10757 } 10758 if (nextidle > -1) { 10759 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) { 10760 /* Don't create a new idle call more than once per second */ 10761 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial); 10762 idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause); 10763 if (idle) { 10764 pri->pvts[nextidle]->isidlecall = 1; 10765 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) { 10766 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name); 10767 dahdi_hangup(idle); 10768 } 10769 } else 10770 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen); 10771 lastidle = ast_tvnow(); 10772 } 10773 } else if ((haveidles < pri->minunused) && 10774 (activeidles > pri->minidle)) { 10775 /* Mark something for hangup if there is something 10776 that can be hungup */ 10777 for (x = pri->numchans; x >= 0; x--) { 10778 /* find a candidate channel */ 10779 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) { 10780 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10781 haveidles++; 10782 /* Stop if we have enough idle channels or 10783 can't spare any more active idle ones */ 10784 if ((haveidles >= pri->minunused) || 10785 (activeidles <= pri->minidle)) 10786 break; 10787 } 10788 } 10789 } 10790 } 10791 /* Start with reasonable max */ 10792 lowest = ast_tv(60, 0); 10793 for (i = 0; i < NUM_DCHANS; i++) { 10794 /* Find lowest available d-channel */ 10795 if (!pri->dchannels[i]) 10796 break; 10797 if ((next = pri_schedule_next(pri->dchans[i]))) { 10798 /* We need relative time here */ 10799 tv = ast_tvsub(*next, ast_tvnow()); 10800 if (tv.tv_sec < 0) { 10801 tv = ast_tv(0,0); 10802 } 10803 if (doidling || pri->resetting) { 10804 if (tv.tv_sec > 1) { 10805 tv = ast_tv(1, 0); 10806 } 10807 } else { 10808 if (tv.tv_sec > 60) { 10809 tv = ast_tv(60, 0); 10810 } 10811 } 10812 } else if (doidling || pri->resetting) { 10813 /* Make sure we stop at least once per second if we're 10814 monitoring idle channels */ 10815 tv = ast_tv(1,0); 10816 } else { 10817 /* Don't poll for more than 60 seconds */ 10818 tv = ast_tv(60, 0); 10819 } 10820 if (!i || ast_tvcmp(tv, lowest) < 0) { 10821 lowest = tv; 10822 } 10823 } 10824 ast_mutex_unlock(&pri->lock); 10825 10826 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 10827 pthread_testcancel(); 10828 e = NULL; 10829 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000); 10830 pthread_testcancel(); 10831 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 10832 10833 ast_mutex_lock(&pri->lock); 10834 if (!res) { 10835 for (which = 0; which < NUM_DCHANS; which++) { 10836 if (!pri->dchans[which]) 10837 break; 10838 /* Just a timeout, run the scheduler */ 10839 e = pri_schedule_run(pri->dchans[which]); 10840 if (e) 10841 break; 10842 } 10843 } else if (res > -1) { 10844 for (which = 0; which < NUM_DCHANS; which++) { 10845 if (!pri->dchans[which]) 10846 break; 10847 if (fds[which].revents & POLLPRI) { 10848 /* Check for an event */ 10849 x = 0; 10850 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x); 10851 if (x) { 10852 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); 10853 manager_event(EVENT_FLAG_SYSTEM, "PRIEvent", 10854 "PRIEvent: %s\r\n" 10855 "PRIEventCode: %d\r\n" 10856 "D-channel: %s\r\n" 10857 "Span: %d\r\n", 10858 event2str(x), 10859 x, 10860 pri_order(which), 10861 pri->span 10862 ); 10863 } 10864 /* Keep track of alarm state */ 10865 if (x == DAHDI_EVENT_ALARM) { 10866 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP); 10867 pri_find_dchan(pri); 10868 } else if (x == DAHDI_EVENT_NOALARM) { 10869 pri->dchanavail[which] |= DCHAN_NOTINALARM; 10870 pri_restart(pri->dchans[which]); 10871 } 10872 10873 ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span); 10874 } else if (fds[which].revents & POLLIN) { 10875 e = pri_check_event(pri->dchans[which]); 10876 } 10877 if (e) 10878 break; 10879 } 10880 } else if (errno != EINTR) 10881 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno)); 10882 10883 if (e) { 10884 if (pri->debug) 10885 pri_dump_event(pri->dchans[which], e); 10886 10887 if (e->e != PRI_EVENT_DCHAN_DOWN) { 10888 if (!(pri->dchanavail[which] & DCHAN_UP)) { 10889 ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span); 10890 } 10891 pri->dchanavail[which] |= DCHAN_UP; 10892 } else if (pri->sig != SIG_BRI_PTMP) { 10893 if (pri->dchanavail[which] & DCHAN_UP) { 10894 ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span); 10895 } 10896 pri->dchanavail[which] &= ~DCHAN_UP; 10897 } 10898 10899 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which])) 10900 /* Must be an NFAS group that has the secondary dchan active */ 10901 pri->pri = pri->dchans[which]; 10902 10903 switch (e->e) { 10904 case PRI_EVENT_DCHAN_UP: 10905 if (!pri->pri) pri_find_dchan(pri); 10906 10907 /* Note presense of D-channel */ 10908 time(&pri->lastreset); 10909 10910 /* Restart in 5 seconds */ 10911 if (pri->resetinterval > -1) { 10912 pri->lastreset -= pri->resetinterval; 10913 pri->lastreset += 5; 10914 } 10915 pri->resetting = 0; 10916 /* Take the channels from inalarm condition */ 10917 for (i = 0; i < pri->numchans; i++) 10918 if (pri->pvts[i]) { 10919 pri->pvts[i]->inalarm = 0; 10920 } 10921 break; 10922 case PRI_EVENT_DCHAN_DOWN: 10923 pri_find_dchan(pri); 10924 if (!pri_is_up(pri)) { 10925 pri->resetting = 0; 10926 /* Hangup active channels and put them in alarm mode */ 10927 for (i = 0; i < pri->numchans; i++) { 10928 struct dahdi_pvt *p = pri->pvts[i]; 10929 if (p) { 10930 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 10931 /* T309 is not enabled : hangup calls when alarm occurs */ 10932 if (p->call) { 10933 if (p->pri && p->pri->pri) { 10934 pri_hangup(p->pri->pri, p->call, -1); 10935 pri_destroycall(p->pri->pri, p->call); 10936 p->call = NULL; 10937 } else 10938 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n"); 10939 } 10940 if (p->realcall) { 10941 pri_hangup_all(p->realcall, pri); 10942 } else if (p->owner) 10943 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10944 } 10945 /* For PTMP connections with non persistent layer 2 we want 10946 * to *not* declare inalarm unless there actually is an alarm */ 10947 if (p->sig != SIG_BRI_PTMP) { 10948 p->inalarm = 1; 10949 } 10950 } 10951 } 10952 } 10953 break; 10954 case PRI_EVENT_RESTART: 10955 if (e->restart.channel > -1) { 10956 chanpos = pri_find_principle(pri, e->restart.channel); 10957 if (chanpos < 0) 10958 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 10959 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 10960 else { 10961 ast_verb(3, "B-channel %d/%d restarted on span %d\n", 10962 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 10963 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10964 if (pri->pvts[chanpos]->call) { 10965 pri_destroycall(pri->pri, pri->pvts[chanpos]->call); 10966 pri->pvts[chanpos]->call = NULL; 10967 } 10968 /* Force soft hangup if appropriate */ 10969 if (pri->pvts[chanpos]->realcall) 10970 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 10971 else if (pri->pvts[chanpos]->owner) 10972 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10973 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10974 } 10975 } else { 10976 ast_verb(3, "Restart on requested on entire span %d\n", pri->span); 10977 for (x = 0; x < pri->numchans; x++) 10978 if (pri->pvts[x]) { 10979 ast_mutex_lock(&pri->pvts[x]->lock); 10980 if (pri->pvts[x]->call) { 10981 pri_destroycall(pri->pri, pri->pvts[x]->call); 10982 pri->pvts[x]->call = NULL; 10983 } 10984 if (pri->pvts[chanpos]->realcall) 10985 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 10986 else if (pri->pvts[x]->owner) 10987 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10988 ast_mutex_unlock(&pri->pvts[x]->lock); 10989 } 10990 } 10991 break; 10992 case PRI_EVENT_KEYPAD_DIGIT: 10993 chanpos = pri_find_principle(pri, e->digit.channel); 10994 if (chanpos < 0) { 10995 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 10996 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span); 10997 } else { 10998 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call); 10999 if (chanpos > -1) { 11000 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11001 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */ 11002 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) { 11003 /* how to do that */ 11004 int digitlen = strlen(e->digit.digits); 11005 char digit; 11006 int i; 11007 for (i = 0; i < digitlen; i++) { 11008 digit = e->digit.digits[i]; 11009 { 11010 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 11011 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11012 } 11013 } 11014 } 11015 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11016 } 11017 } 11018 break; 11019 11020 case PRI_EVENT_INFO_RECEIVED: 11021 chanpos = pri_find_principle(pri, e->ring.channel); 11022 if (chanpos < 0) { 11023 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 11024 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11025 } else { 11026 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call); 11027 if (chanpos > -1) { 11028 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11029 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */ 11030 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) { 11031 /* how to do that */ 11032 int digitlen = strlen(e->ring.callednum); 11033 char digit; 11034 int i; 11035 for (i = 0; i < digitlen; i++) { 11036 digit = e->ring.callednum[i]; 11037 { 11038 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 11039 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11040 } 11041 } 11042 } 11043 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11044 } 11045 } 11046 break; 11047 case PRI_EVENT_RING: 11048 crv = NULL; 11049 if (e->ring.channel == -1) 11050 chanpos = pri_find_empty_chan(pri, 1); 11051 else 11052 chanpos = pri_find_principle(pri, e->ring.channel); 11053 /* if no channel specified find one empty */ 11054 if (chanpos < 0) { 11055 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 11056 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11057 } else { 11058 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11059 if (pri->pvts[chanpos]->owner) { 11060 if (pri->pvts[chanpos]->call == e->ring.call) { 11061 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 11062 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11063 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11064 break; 11065 } else { 11066 /* This is where we handle initial glare */ 11067 ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n", 11068 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11069 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11070 chanpos = -1; 11071 } 11072 } 11073 if (chanpos > -1) 11074 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11075 } 11076 if ((chanpos < 0) && (e->ring.flexible)) 11077 chanpos = pri_find_empty_chan(pri, 1); 11078 if (chanpos > -1) { 11079 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11080 if (pri->switchtype == PRI_SWITCH_GR303_TMC) { 11081 /* Should be safe to lock CRV AFAIK while bearer is still locked */ 11082 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL)); 11083 if (crv) 11084 ast_mutex_lock(&crv->lock); 11085 if (!crv || crv->owner) { 11086 pri->pvts[chanpos]->call = NULL; 11087 if (crv) { 11088 if (crv->owner) 11089 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11090 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); 11091 } else 11092 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); 11093 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE); 11094 if (crv) 11095 ast_mutex_unlock(&crv->lock); 11096 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11097 break; 11098 } 11099 } 11100 pri->pvts[chanpos]->call = e->ring.call; 11101 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan); 11102 if (pri->pvts[chanpos]->use_callerid) { 11103 ast_shrink_phone_number(plancallingnum); 11104 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num)); 11105 #ifdef PRI_ANI 11106 if (!ast_strlen_zero(e->ring.callingani)) { 11107 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani); 11108 ast_shrink_phone_number(plancallingani); 11109 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani)); 11110 } else { 11111 pri->pvts[chanpos]->cid_ani[0] = '\0'; 11112 } 11113 #endif 11114 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name)); 11115 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */ 11116 } else { 11117 pri->pvts[chanpos]->cid_num[0] = '\0'; 11118 pri->pvts[chanpos]->cid_ani[0] = '\0'; 11119 pri->pvts[chanpos]->cid_name[0] = '\0'; 11120 pri->pvts[chanpos]->cid_ton = 0; 11121 } 11122 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri, 11123 e->ring.redirectingnum, e->ring.callingplanrdnis); 11124 /* If immediate=yes go to s|1 */ 11125 if (pri->pvts[chanpos]->immediate) { 11126 ast_verb(3, "Going to extension s|1 because of immediate=yes\n"); 11127 pri->pvts[chanpos]->exten[0] = 's'; 11128 pri->pvts[chanpos]->exten[1] = '\0'; 11129 } 11130 /* Get called number */ 11131 else if (!ast_strlen_zero(e->ring.callednum)) { 11132 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten)); 11133 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 11134 } else if (pri->overlapdial) 11135 pri->pvts[chanpos]->exten[0] = '\0'; 11136 else { 11137 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */ 11138 pri->pvts[chanpos]->exten[0] = 's'; 11139 pri->pvts[chanpos]->exten[1] = '\0'; 11140 } 11141 /* Set DNID on all incoming calls -- even immediate */ 11142 if (!ast_strlen_zero(e->ring.callednum)) 11143 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 11144 /* No number yet, but received "sending complete"? */ 11145 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) { 11146 ast_verb(3, "Going to extension s|1 because of Complete received\n"); 11147 pri->pvts[chanpos]->exten[0] = 's'; 11148 pri->pvts[chanpos]->exten[1] = '\0'; 11149 } 11150 /* Make sure extension exists (or in overlap dial mode, can exist) */ 11151 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) || 11152 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 11153 /* Setup law */ 11154 int law; 11155 if (pri->switchtype != PRI_SWITCH_GR303_TMC) { 11156 /* Set to audio mode at this point */ 11157 law = 1; 11158 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1) 11159 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno)); 11160 } 11161 if (e->ring.layer1 == PRI_LAYER_1_ALAW) 11162 law = DAHDI_LAW_ALAW; 11163 else 11164 law = DAHDI_LAW_MULAW; 11165 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law); 11166 if (res < 0) 11167 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel); 11168 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law); 11169 if (res < 0) 11170 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel); 11171 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 11172 /* Just announce proceeding */ 11173 pri->pvts[chanpos]->proceeding = 1; 11174 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0); 11175 } else { 11176 if (pri->switchtype != PRI_SWITCH_GR303_TMC) 11177 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 11178 else 11179 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 11180 } 11181 /* Get the use_callingpres state */ 11182 pri->pvts[chanpos]->callingpres = e->ring.callingpres; 11183 11184 /* Start PBX */ 11185 if (!e->ring.complete && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 11186 /* Release the PRI lock while we create the channel */ 11187 ast_mutex_unlock(&pri->lock); 11188 if (crv) { 11189 /* Set bearer and such */ 11190 pri_assign_bearer(crv, pri, pri->pvts[chanpos]); 11191 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 11192 pri->pvts[chanpos]->owner = &inuse; 11193 ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel); 11194 } else { 11195 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 11196 } 11197 11198 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11199 11200 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 11201 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 11202 } 11203 if (e->ring.ani2 >= 0) { 11204 snprintf(ani2str, 5, "%.2d", e->ring.ani2); 11205 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 11206 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2; 11207 } 11208 11209 #ifdef SUPPORT_USERUSER 11210 if (!ast_strlen_zero(e->ring.useruserinfo)) { 11211 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 11212 } 11213 #endif 11214 11215 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 11216 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 11217 if (e->ring.redirectingreason >= 0) 11218 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 11219 11220 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11221 ast_mutex_lock(&pri->lock); 11222 if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) { 11223 ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n", 11224 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"), 11225 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11226 } else { 11227 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 11228 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11229 if (c) 11230 ast_hangup(c); 11231 else { 11232 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 11233 pri->pvts[chanpos]->call = NULL; 11234 } 11235 } 11236 } else { 11237 ast_mutex_unlock(&pri->lock); 11238 /* Release PRI lock while we create the channel */ 11239 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype); 11240 if (c) { 11241 char calledtonstr[10]; 11242 11243 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11244 11245 if (e->ring.ani2 >= 0) { 11246 snprintf(ani2str, 5, "%d", e->ring.ani2); 11247 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 11248 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2; 11249 } 11250 11251 #ifdef SUPPORT_USERUSER 11252 if (!ast_strlen_zero(e->ring.useruserinfo)) { 11253 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 11254 } 11255 #endif 11256 11257 if (e->ring.redirectingreason >= 0) 11258 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 11259 11260 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 11261 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 11262 11263 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11264 ast_mutex_lock(&pri->lock); 11265 11266 ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n", 11267 plancallingnum, pri->pvts[chanpos]->exten, 11268 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11269 11270 dahdi_enable_ec(pri->pvts[chanpos]); 11271 } else { 11272 11273 ast_mutex_lock(&pri->lock); 11274 11275 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 11276 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11277 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 11278 pri->pvts[chanpos]->call = NULL; 11279 } 11280 } 11281 } else { 11282 ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n", 11283 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 11284 pri->pvts[chanpos]->prioffset, pri->span); 11285 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED); 11286 pri->pvts[chanpos]->call = NULL; 11287 pri->pvts[chanpos]->exten[0] = '\0'; 11288 } 11289 if (crv) 11290 ast_mutex_unlock(&crv->lock); 11291 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11292 } else { 11293 if (e->ring.flexible) 11294 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION); 11295 else 11296 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL); 11297 } 11298 break; 11299 case PRI_EVENT_RINGING: 11300 chanpos = pri_find_principle(pri, e->ringing.channel); 11301 if (chanpos < 0) { 11302 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 11303 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 11304 } else { 11305 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call); 11306 if (chanpos < 0) { 11307 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 11308 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 11309 } else { 11310 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11311 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 11312 dahdi_enable_ec(pri->pvts[chanpos]); 11313 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1; 11314 pri->pvts[chanpos]->alerting = 1; 11315 } else 11316 ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n"); 11317 11318 #ifdef PRI_PROGRESS_MASK 11319 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) { 11320 #else 11321 if (e->ringing.progress == 8) { 11322 #endif 11323 /* Now we can do call progress detection */ 11324 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11325 /* RINGING detection isn't required because we got ALERTING signal */ 11326 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING); 11327 pri->pvts[chanpos]->dsp_features = 0; 11328 } 11329 } 11330 11331 #ifdef SUPPORT_USERUSER 11332 if (!ast_strlen_zero(e->ringing.useruserinfo)) { 11333 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11334 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11335 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo); 11336 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11337 } 11338 #endif 11339 11340 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11341 } 11342 } 11343 break; 11344 case PRI_EVENT_PROGRESS: 11345 /* Get chan value if e->e is not PRI_EVNT_RINGING */ 11346 chanpos = pri_find_principle(pri, e->proceeding.channel); 11347 if (chanpos > -1) { 11348 #ifdef PRI_PROGRESS_MASK 11349 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) { 11350 #else 11351 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) { 11352 #endif 11353 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, }; 11354 11355 if (e->proceeding.cause > -1) { 11356 ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause); 11357 11358 /* Work around broken, out of spec USER_BUSY cause in a progress message */ 11359 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) { 11360 if (pri->pvts[chanpos]->owner) { 11361 ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n"); 11362 11363 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause; 11364 f.subclass = AST_CONTROL_BUSY; 11365 } 11366 } 11367 } 11368 11369 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11370 ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n", 11371 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 11372 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11373 #ifdef PRI_PROGRESS_MASK 11374 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 11375 #else 11376 if (e->proceeding.progress == 8) { 11377 #endif 11378 /* Now we can do call progress detection */ 11379 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11380 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 11381 pri->pvts[chanpos]->dsp_features = 0; 11382 } 11383 /* Bring voice path up */ 11384 f.subclass = AST_CONTROL_PROGRESS; 11385 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11386 } 11387 pri->pvts[chanpos]->progress = 1; 11388 pri->pvts[chanpos]->dialing = 0; 11389 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11390 } 11391 } 11392 break; 11393 case PRI_EVENT_PROCEEDING: 11394 chanpos = pri_find_principle(pri, e->proceeding.channel); 11395 if (chanpos > -1) { 11396 if (!pri->pvts[chanpos]->proceeding) { 11397 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, }; 11398 11399 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11400 ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n", 11401 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 11402 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11403 #ifdef PRI_PROGRESS_MASK 11404 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 11405 #else 11406 if (e->proceeding.progress == 8) { 11407 #endif 11408 /* Now we can do call progress detection */ 11409 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11410 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 11411 pri->pvts[chanpos]->dsp_features = 0; 11412 } 11413 /* Bring voice path up */ 11414 f.subclass = AST_CONTROL_PROGRESS; 11415 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11416 } 11417 pri->pvts[chanpos]->proceeding = 1; 11418 pri->pvts[chanpos]->dialing = 0; 11419 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11420 } 11421 } 11422 break; 11423 case PRI_EVENT_FACNAME: 11424 chanpos = pri_find_principle(pri, e->facname.channel); 11425 if (chanpos < 0) { 11426 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 11427 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 11428 } else { 11429 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call); 11430 if (chanpos < 0) { 11431 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 11432 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 11433 } else { 11434 /* Re-use *69 field for PRI */ 11435 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11436 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num)); 11437 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name)); 11438 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1; 11439 dahdi_enable_ec(pri->pvts[chanpos]); 11440 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11441 } 11442 } 11443 break; 11444 case PRI_EVENT_ANSWER: 11445 chanpos = pri_find_principle(pri, e->answer.channel); 11446 if (chanpos < 0) { 11447 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 11448 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 11449 } else { 11450 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call); 11451 if (chanpos < 0) { 11452 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 11453 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 11454 } else { 11455 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11456 /* Now we can do call progress detection */ 11457 11458 /* We changed this so it turns on the DSP no matter what... progress or no progress. 11459 * By this time, we need DTMF detection and other features that were previously disabled 11460 * -- Matt F */ 11461 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11462 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 11463 pri->pvts[chanpos]->dsp_features = 0; 11464 } 11465 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) { 11466 ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n"); 11467 x = DAHDI_START; 11468 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 11469 if (res < 0) { 11470 if (errno != EINPROGRESS) { 11471 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 11472 } 11473 } 11474 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 11475 pri->pvts[chanpos]->dialing = 1; 11476 /* Send any "w" waited stuff */ 11477 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop); 11478 if (res < 0) { 11479 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno)); 11480 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 11481 } else 11482 ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr); 11483 11484 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 11485 } else if (pri->pvts[chanpos]->confirmanswer) { 11486 ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel); 11487 } else { 11488 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1; 11489 /* Enable echo cancellation if it's not on already */ 11490 dahdi_enable_ec(pri->pvts[chanpos]); 11491 } 11492 11493 #ifdef SUPPORT_USERUSER 11494 if (!ast_strlen_zero(e->answer.useruserinfo)) { 11495 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11496 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11497 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo); 11498 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11499 } 11500 #endif 11501 11502 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11503 } 11504 } 11505 break; 11506 case PRI_EVENT_HANGUP: 11507 chanpos = pri_find_principle(pri, e->hangup.channel); 11508 if (chanpos < 0) { 11509 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 11510 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11511 } else { 11512 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 11513 if (chanpos > -1) { 11514 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11515 if (!pri->pvts[chanpos]->alreadyhungup) { 11516 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */ 11517 pri->pvts[chanpos]->alreadyhungup = 1; 11518 if (pri->pvts[chanpos]->realcall) 11519 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11520 else if (pri->pvts[chanpos]->owner) { 11521 /* Queue a BUSY instead of a hangup if our cause is appropriate */ 11522 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 11523 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP) 11524 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11525 else { 11526 switch (e->hangup.cause) { 11527 case PRI_CAUSE_USER_BUSY: 11528 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 11529 break; 11530 case PRI_CAUSE_CALL_REJECTED: 11531 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 11532 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 11533 case PRI_CAUSE_SWITCH_CONGESTION: 11534 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 11535 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 11536 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 11537 break; 11538 default: 11539 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11540 } 11541 } 11542 } 11543 ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n", 11544 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause); 11545 } else { 11546 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 11547 pri->pvts[chanpos]->call = NULL; 11548 } 11549 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 11550 ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 11551 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11552 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 11553 pri->pvts[chanpos]->resetting = 1; 11554 } 11555 if (e->hangup.aoc_units > -1) 11556 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 11557 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 11558 11559 #ifdef SUPPORT_USERUSER 11560 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) { 11561 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11562 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11563 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 11564 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11565 } 11566 #endif 11567 11568 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11569 } else { 11570 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 11571 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11572 } 11573 } 11574 break; 11575 #ifndef PRI_EVENT_HANGUP_REQ 11576 #error please update libpri 11577 #endif 11578 case PRI_EVENT_HANGUP_REQ: 11579 chanpos = pri_find_principle(pri, e->hangup.channel); 11580 if (chanpos < 0) { 11581 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 11582 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11583 } else { 11584 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 11585 if (chanpos > -1) { 11586 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11587 if (pri->pvts[chanpos]->realcall) 11588 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11589 else if (pri->pvts[chanpos]->owner) { 11590 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 11591 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP) 11592 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11593 else { 11594 switch (e->hangup.cause) { 11595 case PRI_CAUSE_USER_BUSY: 11596 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 11597 break; 11598 case PRI_CAUSE_CALL_REJECTED: 11599 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 11600 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 11601 case PRI_CAUSE_SWITCH_CONGESTION: 11602 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 11603 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 11604 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 11605 break; 11606 default: 11607 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11608 } 11609 } 11610 ast_verb(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); 11611 if (e->hangup.aoc_units > -1) 11612 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 11613 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 11614 } else { 11615 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 11616 pri->pvts[chanpos]->call = NULL; 11617 } 11618 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 11619 ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n", 11620 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11621 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 11622 pri->pvts[chanpos]->resetting = 1; 11623 } 11624 11625 #ifdef SUPPORT_USERUSER 11626 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 11627 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11628 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11629 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 11630 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11631 } 11632 #endif 11633 11634 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11635 } else { 11636 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); 11637 } 11638 } 11639 break; 11640 case PRI_EVENT_HANGUP_ACK: 11641 chanpos = pri_find_principle(pri, e->hangup.channel); 11642 if (chanpos < 0) { 11643 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 11644 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11645 } else { 11646 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 11647 if (chanpos > -1) { 11648 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11649 pri->pvts[chanpos]->call = NULL; 11650 pri->pvts[chanpos]->resetting = 0; 11651 if (pri->pvts[chanpos]->owner) { 11652 ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11653 } 11654 11655 #ifdef SUPPORT_USERUSER 11656 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 11657 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11658 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11659 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 11660 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11661 } 11662 #endif 11663 11664 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11665 } 11666 } 11667 break; 11668 case PRI_EVENT_CONFIG_ERR: 11669 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err); 11670 break; 11671 case PRI_EVENT_RESTART_ACK: 11672 chanpos = pri_find_principle(pri, e->restartack.channel); 11673 if (chanpos < 0) { 11674 /* Sometime switches (e.g. I421 / British Telecom) don't give us the 11675 channel number, so we have to figure it out... This must be why 11676 everybody resets exactly a channel at a time. */ 11677 for (x = 0; x < pri->numchans; x++) { 11678 if (pri->pvts[x] && pri->pvts[x]->resetting) { 11679 chanpos = x; 11680 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11681 ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 11682 pri->pvts[chanpos]->prioffset, pri->span); 11683 if (pri->pvts[chanpos]->realcall) 11684 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11685 else if (pri->pvts[chanpos]->owner) { 11686 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 11687 pri->pvts[chanpos]->prioffset, pri->span); 11688 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11689 } 11690 pri->pvts[chanpos]->resetting = 0; 11691 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 11692 pri->pvts[chanpos]->prioffset, pri->span); 11693 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11694 if (pri->resetting) 11695 pri_check_restart(pri); 11696 break; 11697 } 11698 } 11699 if (chanpos < 0) { 11700 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 11701 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 11702 } 11703 } else { 11704 if (pri->pvts[chanpos]) { 11705 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11706 if (pri->pvts[chanpos]->realcall) 11707 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11708 else if (pri->pvts[chanpos]->owner) { 11709 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n", 11710 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 11711 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11712 } 11713 pri->pvts[chanpos]->resetting = 0; 11714 pri->pvts[chanpos]->inservice = 1; 11715 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 11716 pri->pvts[chanpos]->prioffset, pri->span); 11717 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11718 if (pri->resetting) 11719 pri_check_restart(pri); 11720 } 11721 } 11722 break; 11723 case PRI_EVENT_SETUP_ACK: 11724 chanpos = pri_find_principle(pri, e->setup_ack.channel); 11725 if (chanpos < 0) { 11726 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 11727 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span); 11728 } else { 11729 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call); 11730 if (chanpos > -1) { 11731 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11732 pri->pvts[chanpos]->setup_ack = 1; 11733 /* Send any queued digits */ 11734 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) { 11735 ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]); 11736 pri_information(pri->pri, pri->pvts[chanpos]->call, 11737 pri->pvts[chanpos]->dialdest[x]); 11738 } 11739 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11740 } else 11741 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel); 11742 } 11743 break; 11744 case PRI_EVENT_NOTIFY: 11745 chanpos = pri_find_principle(pri, e->notify.channel); 11746 if (chanpos < 0) { 11747 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n", 11748 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span); 11749 } else { 11750 struct ast_frame f = { AST_FRAME_CONTROL, }; 11751 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11752 switch (e->notify.info) { 11753 case PRI_NOTIFY_REMOTE_HOLD: 11754 f.subclass = AST_CONTROL_HOLD; 11755 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11756 break; 11757 case PRI_NOTIFY_REMOTE_RETRIEVAL: 11758 f.subclass = AST_CONTROL_UNHOLD; 11759 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11760 break; 11761 } 11762 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11763 } 11764 break; 11765 default: 11766 ast_debug(1, "Event: %d\n", e->e); 11767 } 11768 } 11769 ast_mutex_unlock(&pri->lock); 11770 } 11771 /* Never reached */ 11772 return NULL; 11773 }
Definition at line 10322 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pri::crvs, dahdi_pvt::next, and dahdi_pvt::pri.
10323 { 10324 struct dahdi_pvt *p; 10325 p = pri->crvs; 10326 while (p) { 10327 if (p->channel == crv) 10328 return p; 10329 p = p->next; 10330 } 10331 return NULL; 10332 }
static int pri_find_dchan | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3349 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, dahdi_pri::dchans, NUM_DCHANS, and dahdi_pri::pri.
03350 { 03351 int oldslot = -1; 03352 struct pri *old; 03353 int newslot = -1; 03354 int x; 03355 old = pri->pri; 03356 for (x = 0; x < NUM_DCHANS; x++) { 03357 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0)) 03358 newslot = x; 03359 if (pri->dchans[x] == old) { 03360 oldslot = x; 03361 } 03362 } 03363 if (newslot < 0) { 03364 newslot = 0; 03365 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n", 03366 pri->dchannels[newslot]); 03367 } 03368 if (old && (oldslot != newslot)) 03369 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n", 03370 pri->dchannels[oldslot], pri->dchannels[newslot]); 03371 pri->pri = pri->dchans[newslot]; 03372 return 0; 03373 }
static int pri_find_empty_chan | ( | struct dahdi_pri * | pri, | |
int | backwards | |||
) | [static] |
Definition at line 9222 of file chan_dahdi.c.
References ast_debug, dahdi_pvt::inalarm, dahdi_pvt::logicalspan, dahdi_pri::numchans, dahdi_pvt::owner, dahdi_pvt::prioffset, and dahdi_pri::pvts.
Referenced by dahdi_request().
09223 { 09224 int x; 09225 if (backwards) 09226 x = pri->numchans; 09227 else 09228 x = 0; 09229 for (;;) { 09230 if (backwards && (x < 0)) 09231 break; 09232 if (!backwards && (x >= pri->numchans)) 09233 break; 09234 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) { 09235 ast_debug(1, "Found empty available channel %d/%d\n", 09236 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset); 09237 return x; 09238 } 09239 if (backwards) 09240 x--; 09241 else 09242 x++; 09243 } 09244 return -1; 09245 }
static int pri_find_principle | ( | struct dahdi_pri * | pri, | |
int | channel | |||
) | [static] |
Definition at line 10335 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.
10336 { 10337 int x; 10338 int span = PRI_SPAN(channel); 10339 int spanfd; 10340 struct dahdi_params param; 10341 int principle = -1; 10342 int explicit = PRI_EXPLICIT(channel); 10343 channel = PRI_CHANNEL(channel); 10344 10345 if (!explicit) { 10346 spanfd = pri_active_dchan_fd(pri); 10347 memset(¶m, 0, sizeof(param)); 10348 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m)) 10349 return -1; 10350 span = pris[param.spanno - 1].prilogicalspan; 10351 } 10352 10353 for (x = 0; x < pri->numchans; x++) { 10354 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) { 10355 principle = x; 10356 break; 10357 } 10358 } 10359 10360 return principle; 10361 }
static int pri_fixup_principle | ( | struct dahdi_pri * | pri, | |
int | principle, | |||
q931_call * | c | |||
) | [static] |
Definition at line 10363 of file chan_dahdi.c.
References ast_channel_set_fd(), ast_log(), ast_string_field_build, ast_verb, dahdi_pvt::call, name, dahdi_pri::numchans, dahdi_pvt::pri, dahdi_pri::pvts, SUB_REAL, and dahdi_pri::trunkgroup.
10364 { 10365 int x; 10366 struct dahdi_pvt *crv; 10367 if (!c) { 10368 if (principle < 0) 10369 return -1; 10370 return principle; 10371 } 10372 if ((principle > -1) && 10373 (principle < pri->numchans) && 10374 (pri->pvts[principle]) && 10375 (pri->pvts[principle]->call == c)) 10376 return principle; 10377 /* First, check for other bearers */ 10378 for (x = 0; x < pri->numchans; x++) { 10379 if (!pri->pvts[x]) 10380 continue; 10381 if (pri->pvts[x]->call == c) { 10382 /* Found our call */ 10383 if (principle != x) { 10384 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x]; 10385 10386 ast_verb(3, "Moving call from channel %d to channel %d\n", 10387 old->channel, new->channel); 10388 if (new->owner) { 10389 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n", 10390 old->channel, new->channel, new->channel); 10391 return -1; 10392 } 10393 /* Fix it all up now */ 10394 new->owner = old->owner; 10395 old->owner = NULL; 10396 if (new->owner) { 10397 ast_string_field_build(new->owner, name, 10398 "DAHDI/%d:%d-%d", pri->trunkgroup, 10399 new->channel, 1); 10400 new->owner->tech_pvt = new; 10401 ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd); 10402 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner; 10403 old->subs[SUB_REAL].owner = NULL; 10404 } else 10405 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); 10406 new->call = old->call; 10407 old->call = NULL; 10408 10409 /* Copy any DSP that may be present */ 10410 new->dsp = old->dsp; 10411 new->dsp_features = old->dsp_features; 10412 old->dsp = NULL; 10413 old->dsp_features = 0; 10414 } 10415 return principle; 10416 } 10417 } 10418 /* Now check for a CRV with no bearer */ 10419 crv = pri->crvs; 10420 while (crv) { 10421 if (crv->call == c) { 10422 /* This is our match... Perform some basic checks */ 10423 if (crv->bearer) 10424 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n"); 10425 else if (pri->pvts[principle]->owner) 10426 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n"); 10427 else { 10428 /* Looks good. Drop the pseudo channel now, clear up the assignment, and 10429 wakeup the potential sleeper */ 10430 dahdi_close_sub(crv, SUB_REAL); 10431 pri->pvts[principle]->call = crv->call; 10432 pri_assign_bearer(crv, pri, pri->pvts[principle]); 10433 ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n", 10434 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset, 10435 pri->trunkgroup, crv->channel); 10436 wakeup_sub(crv, SUB_REAL, pri); 10437 } 10438 return principle; 10439 } 10440 crv = crv->next; 10441 } 10442 ast_log(LOG_WARNING, "Call specified, but not found?\n"); 10443 return -1; 10444 }
Definition at line 1228 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_send_keypad_facility_exec(), and dahdi_write().
01229 { 01230 int res; 01231 /* Grab the lock first */ 01232 do { 01233 res = ast_mutex_trylock(&pri->lock); 01234 if (res) { 01235 DEADLOCK_AVOIDANCE(&pvt->lock); 01236 } 01237 } while (res); 01238 /* Then break the poll */ 01239 if (pri->master != AST_PTHREADT_NULL) 01240 pthread_kill(pri->master, SIGURG); 01241 return 0; 01242 }
Definition at line 10594 of file chan_dahdi.c.
References ast_channel_trylock, ast_channel_unlock, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_hangup(), DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_pri::lock, dahdi_subchannel::owner, and dahdi_pvt::subs.
10595 { 10596 int x; 10597 int redo; 10598 ast_mutex_unlock(&pri->lock); 10599 ast_mutex_lock(&p->lock); 10600 do { 10601 redo = 0; 10602 for (x = 0; x < 3; x++) { 10603 while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) { 10604 redo++; 10605 DEADLOCK_AVOIDANCE(&p->lock); 10606 } 10607 if (p->subs[x].owner) { 10608 ast_queue_hangup(p->subs[x].owner); 10609 ast_channel_unlock(p->subs[x].owner); 10610 } 10611 } 10612 } while (redo); 10613 ast_mutex_unlock(&p->lock); 10614 ast_mutex_lock(&pri->lock); 10615 return 0; 10616 }
static int pri_is_up | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3297 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, NUM_DCHANS, and dahdi_pvt::pri.
Referenced by pri_dchannel().
03298 { 03299 int x; 03300 for (x = 0; x < NUM_DCHANS; x++) { 03301 if (pri->dchanavail[x] == DCHAN_AVAILABLE) 03302 return 1; 03303 } 03304 return 0; 03305 }
static char* pri_order | ( | int | level | ) | [static] |
Definition at line 3320 of file chan_dahdi.c.
Referenced by handle_pri_show_span().
03321 { 03322 switch (level) { 03323 case 0: 03324 return "Primary"; 03325 case 1: 03326 return "Secondary"; 03327 case 2: 03328 return "Tertiary"; 03329 case 3: 03330 return "Quaternary"; 03331 default: 03332 return "<Unknown>"; 03333 } 03334 }
static void pri_rel | ( | struct dahdi_pri * | pri | ) | [inline, static] |
Definition at line 449 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_send_keypad_facility_exec(), and dahdi_write().
00450 { 00451 ast_mutex_unlock(&pri->lock); 00452 }
static int pri_resolve_span | ( | int * | span, | |
int | channel, | |||
int | offset, | |||
struct dahdi_spaninfo * | si | |||
) | [static] |
Definition at line 8348 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().
08349 { 08350 int x; 08351 int trunkgroup; 08352 /* Get appropriate trunk group if there is one */ 08353 trunkgroup = pris[*span].mastertrunkgroup; 08354 if (trunkgroup) { 08355 /* Select a specific trunk group */ 08356 for (x = 0; x < NUM_SPANS; x++) { 08357 if (pris[x].trunkgroup == trunkgroup) { 08358 *span = x; 08359 return 0; 08360 } 08361 } 08362 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup); 08363 *span = -1; 08364 } else { 08365 if (pris[*span].trunkgroup) { 08366 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup); 08367 *span = -1; 08368 } else if (pris[*span].mastertrunkgroup) { 08369 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup); 08370 *span = -1; 08371 } else { 08372 if (si->totalchans == 31) { 08373 /* E1 */ 08374 pris[*span].dchannels[0] = 16 + offset; 08375 } else if (si->totalchans == 24) { 08376 /* T1 or J1 */ 08377 pris[*span].dchannels[0] = 24 + offset; 08378 } else if (si->totalchans == 3) { 08379 /* BRI */ 08380 pris[*span].dchannels[0] = 3 + offset; 08381 } else { 08382 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); 08383 *span = -1; 08384 return 0; 08385 } 08386 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED; 08387 pris[*span].offset = offset; 08388 pris[*span].span = *span + 1; 08389 } 08390 } 08391 return 0; 08392 }
static int process_dahdi | ( | struct dahdi_chan_conf * | confp, | |
struct ast_variable * | v, | |||
int | reload, | |||
int | skipchannels | |||
) | [static] |
Definition at line 13996 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_strdupa, ast_true(), ast_variable_new(), ast_verb, 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, CALLPROGRESS_FAX, CALLPROGRESS_FAX_INCOMING, CALLPROGRESS_FAX_OUTGOING, CALLPROGRESS_PROGRESS, 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, dahdi_pvt::cid_rxgain, 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_POLARITY_IN, CID_START_RING, dahdi_pvt::context, ringContextData::contextData, DAHDI_OVERLAPDIAL_BOTH, DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_NONE, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_pvt::dahditrcallerid, dahdi_pri::dialplan, dahdi_pvt::drings, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, 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_chan_conf::is_sig_auto, 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, dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitor_neon, ast_variable::name, dahdi_pri::nationalprefix, ast_variable::next, dahdi_pri::nodetype, dahdi_pri::nsf, NUM_SPANS, 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, process_echocancel(), dahdi_pvt::pulse, dahdi_pvt::radio, distRingData::range, 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_BRI, SIG_BRI_PTMP, 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, SIG_SS7, dahdi_pvt::silencethreshold, dahdi_chan_conf::smdi_port, dahdi_pvt::stripmsd, strsep(), dahdi_pri::switchtype, dahdi_pvt::threewaycalling, 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, ast_variable::value, and dahdi_pvt::vars.
Referenced by setup_dahdi().
13997 { 13998 struct dahdi_pvt *tmp; 13999 int y; 14000 int found_pseudo = 0; 14001 char dahdichan[MAX_CHANLIST_LEN] = {}; 14002 14003 for (; v; v = v->next) { 14004 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 14005 continue; 14006 14007 /* Create the interface list */ 14008 if (!strcasecmp(v->name, "channel") 14009 #ifdef HAVE_PRI 14010 || !strcasecmp(v->name, "crv") 14011 #endif 14012 ) { 14013 int iscrv; 14014 if (skipchannels) 14015 continue; 14016 iscrv = !strcasecmp(v->name, "crv"); 14017 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo)) 14018 return -1; 14019 } else if (!strcasecmp(v->name, "buffers")) { 14020 int res; 14021 char policy[21] = ""; 14022 14023 res = sscanf(v->value, "%d,%20s", &confp->chan.buf_no, policy); 14024 if (res != 2) { 14025 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n"); 14026 confp->chan.buf_no = numbufs; 14027 continue; 14028 } 14029 if (confp->chan.buf_no < 0) 14030 confp->chan.buf_no = numbufs; 14031 if (!strcasecmp(policy, "full")) { 14032 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL; 14033 } else if (!strcasecmp(policy, "immediate")) { 14034 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE; 14035 } else { 14036 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy); 14037 } 14038 } else if (!strcasecmp(v->name, "dahdichan")) { 14039 ast_copy_string(dahdichan, v->value, sizeof(dahdichan)); 14040 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) { 14041 usedistinctiveringdetection = ast_true(v->value); 14042 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) { 14043 distinctiveringaftercid = ast_true(v->value); 14044 } else if (!strcasecmp(v->name, "dring1context")) { 14045 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData)); 14046 } else if (!strcasecmp(v->name, "dring2context")) { 14047 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData)); 14048 } else if (!strcasecmp(v->name, "dring3context")) { 14049 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData)); 14050 } else if (!strcasecmp(v->name, "dring1range")) { 14051 confp->chan.drings.ringnum[0].range = atoi(v->value); 14052 } else if (!strcasecmp(v->name, "dring2range")) { 14053 confp->chan.drings.ringnum[1].range = atoi(v->value); 14054 } else if (!strcasecmp(v->name, "dring3range")) { 14055 confp->chan.drings.ringnum[2].range = atoi(v->value); 14056 } else if (!strcasecmp(v->name, "dring1")) { 14057 sscanf(v->value, "%d,%d,%d", &confp->chan.drings.ringnum[0].ring[0], &confp->chan.drings.ringnum[0].ring[1], &confp->chan.drings.ringnum[0].ring[2]); 14058 } else if (!strcasecmp(v->name, "dring2")) { 14059 sscanf(v->value,"%d,%d,%d", &confp->chan.drings.ringnum[1].ring[0], &confp->chan.drings.ringnum[1].ring[1], &confp->chan.drings.ringnum[1].ring[2]); 14060 } else if (!strcasecmp(v->name, "dring3")) { 14061 sscanf(v->value, "%d,%d,%d", &confp->chan.drings.ringnum[2].ring[0], &confp->chan.drings.ringnum[2].ring[1], &confp->chan.drings.ringnum[2].ring[2]); 14062 } else if (!strcasecmp(v->name, "usecallerid")) { 14063 confp->chan.use_callerid = ast_true(v->value); 14064 } else if (!strcasecmp(v->name, "cidsignalling")) { 14065 if (!strcasecmp(v->value, "bell")) 14066 confp->chan.cid_signalling = CID_SIG_BELL; 14067 else if (!strcasecmp(v->value, "v23")) 14068 confp->chan.cid_signalling = CID_SIG_V23; 14069 else if (!strcasecmp(v->value, "dtmf")) 14070 confp->chan.cid_signalling = CID_SIG_DTMF; 14071 else if (!strcasecmp(v->value, "smdi")) 14072 confp->chan.cid_signalling = CID_SIG_SMDI; 14073 else if (!strcasecmp(v->value, "v23_jp")) 14074 confp->chan.cid_signalling = CID_SIG_V23_JP; 14075 else if (ast_true(v->value)) 14076 confp->chan.cid_signalling = CID_SIG_BELL; 14077 } else if (!strcasecmp(v->name, "cidstart")) { 14078 if (!strcasecmp(v->value, "ring")) 14079 confp->chan.cid_start = CID_START_RING; 14080 else if (!strcasecmp(v->value, "polarity_in")) 14081 confp->chan.cid_start = CID_START_POLARITY_IN; 14082 else if (!strcasecmp(v->value, "polarity")) 14083 confp->chan.cid_start = CID_START_POLARITY; 14084 else if (ast_true(v->value)) 14085 confp->chan.cid_start = CID_START_RING; 14086 } else if (!strcasecmp(v->name, "threewaycalling")) { 14087 confp->chan.threewaycalling = ast_true(v->value); 14088 } else if (!strcasecmp(v->name, "cancallforward")) { 14089 confp->chan.cancallforward = ast_true(v->value); 14090 } else if (!strcasecmp(v->name, "relaxdtmf")) { 14091 if (ast_true(v->value)) 14092 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 14093 else 14094 confp->chan.dtmfrelax = 0; 14095 } else if (!strcasecmp(v->name, "mailbox")) { 14096 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox)); 14097 } else if (!strcasecmp(v->name, "adsi")) { 14098 confp->chan.adsi = ast_true(v->value); 14099 } else if (!strcasecmp(v->name, "usesmdi")) { 14100 confp->chan.use_smdi = ast_true(v->value); 14101 } else if (!strcasecmp(v->name, "smdiport")) { 14102 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port)); 14103 } else if (!strcasecmp(v->name, "transfer")) { 14104 confp->chan.transfer = ast_true(v->value); 14105 } else if (!strcasecmp(v->name, "canpark")) { 14106 confp->chan.canpark = ast_true(v->value); 14107 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) { 14108 confp->chan.echocanbridged = ast_true(v->value); 14109 } else if (!strcasecmp(v->name, "busydetect")) { 14110 confp->chan.busydetect = ast_true(v->value); 14111 } else if (!strcasecmp(v->name, "busycount")) { 14112 confp->chan.busycount = atoi(v->value); 14113 } else if (!strcasecmp(v->name, "silencethreshold")) { 14114 confp->chan.silencethreshold = atoi(v->value); 14115 } else if (!strcasecmp(v->name, "busycompare")) { 14116 confp->chan.busycompare = ast_true(v->value); 14117 } else if (!strcasecmp(v->name, "busypattern")) { 14118 if (sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) { 14119 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno); 14120 } 14121 int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength); 14122 if (count == 1) 14123 confp->chan.busyquietlength = 0; 14124 else if (count < 1) 14125 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno); 14126 } else if (!strcasecmp(v->name, "busyfuzziness")) { 14127 confp->chan.busyfuzziness = atoi(v->value); 14128 } else if (!strcasecmp(v->name, "callprogress")) { 14129 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS; 14130 if (ast_true(v->value)) 14131 confp->chan.callprogress |= CALLPROGRESS_PROGRESS; 14132 } else if (!strcasecmp(v->name, "faxdetect")) { 14133 confp->chan.callprogress &= ~CALLPROGRESS_FAX; 14134 if (!strcasecmp(v->value, "incoming")) { 14135 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING; 14136 } else if (!strcasecmp(v->value, "outgoing")) { 14137 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING; 14138 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) 14139 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING; 14140 } else if (!strcasecmp(v->name, "echocancel")) { 14141 process_echocancel(confp, v->value, v->lineno); 14142 } else if (!strcasecmp(v->name, "echotraining")) { 14143 if (sscanf(v->value, "%d", &y) == 1) { 14144 if ((y < 10) || (y > 4000)) { 14145 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno); 14146 } else { 14147 confp->chan.echotraining = y; 14148 } 14149 } else if (ast_true(v->value)) { 14150 confp->chan.echotraining = 400; 14151 } else 14152 confp->chan.echotraining = 0; 14153 } else if (!strcasecmp(v->name, "hidecallerid")) { 14154 confp->chan.hidecallerid = ast_true(v->value); 14155 } else if (!strcasecmp(v->name, "hidecalleridname")) { 14156 confp->chan.hidecalleridname = ast_true(v->value); 14157 } else if (!strcasecmp(v->name, "pulsedial")) { 14158 confp->chan.pulse = ast_true(v->value); 14159 } else if (!strcasecmp(v->name, "callreturn")) { 14160 confp->chan.callreturn = ast_true(v->value); 14161 } else if (!strcasecmp(v->name, "callwaiting")) { 14162 confp->chan.callwaiting = ast_true(v->value); 14163 } else if (!strcasecmp(v->name, "callwaitingcallerid")) { 14164 confp->chan.callwaitingcallerid = ast_true(v->value); 14165 } else if (!strcasecmp(v->name, "context")) { 14166 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context)); 14167 } else if (!strcasecmp(v->name, "language")) { 14168 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language)); 14169 } else if (!strcasecmp(v->name, "progzone")) { 14170 ast_copy_string(progzone, v->value, sizeof(progzone)); 14171 } else if (!strcasecmp(v->name, "mohinterpret") 14172 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) { 14173 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret)); 14174 } else if (!strcasecmp(v->name, "mohsuggest")) { 14175 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest)); 14176 } else if (!strcasecmp(v->name, "stripmsd")) { 14177 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name); 14178 confp->chan.stripmsd = atoi(v->value); 14179 } else if (!strcasecmp(v->name, "jitterbuffers")) { 14180 numbufs = atoi(v->value); 14181 } else if (!strcasecmp(v->name, "group")) { 14182 confp->chan.group = ast_get_group(v->value); 14183 } else if (!strcasecmp(v->name, "callgroup")) { 14184 if (!strcasecmp(v->value, "none")) 14185 confp->chan.callgroup = 0; 14186 else 14187 confp->chan.callgroup = ast_get_group(v->value); 14188 } else if (!strcasecmp(v->name, "pickupgroup")) { 14189 if (!strcasecmp(v->value, "none")) 14190 confp->chan.pickupgroup = 0; 14191 else 14192 confp->chan.pickupgroup = ast_get_group(v->value); 14193 } else if (!strcasecmp(v->name, "setvar")) { 14194 char *varname = ast_strdupa(v->value), *varval = NULL; 14195 struct ast_variable *tmpvar; 14196 if (varname && (varval = strchr(varname, '='))) { 14197 *varval++ = '\0'; 14198 if ((tmpvar = ast_variable_new(varname, varval, ""))) { 14199 tmpvar->next = confp->chan.vars; 14200 confp->chan.vars = tmpvar; 14201 } 14202 } 14203 } else if (!strcasecmp(v->name, "immediate")) { 14204 confp->chan.immediate = ast_true(v->value); 14205 } else if (!strcasecmp(v->name, "transfertobusy")) { 14206 confp->chan.transfertobusy = ast_true(v->value); 14207 } else if (!strcasecmp(v->name, "mwimonitor")) { 14208 if (!strcasecmp(v->value, "neon")) { 14209 confp->chan.mwimonitor_neon = 1; 14210 confp->chan.mwimonitor_fsk = 0; 14211 } else { 14212 confp->chan.mwimonitor_neon = 0; 14213 if (!strcasecmp(v->value, "fsk")) 14214 confp->chan.mwimonitor_fsk = 1; 14215 else 14216 confp->chan.mwimonitor_fsk = ast_true(v->value) ? 1 : 0; 14217 } 14218 } else if (!strcasecmp(v->name, "cid_rxgain")) { 14219 if (sscanf(v->value, "%f", &confp->chan.cid_rxgain) != 1) { 14220 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno); 14221 } 14222 } else if (!strcasecmp(v->name, "rxgain")) { 14223 if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) { 14224 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno); 14225 } 14226 } else if (!strcasecmp(v->name, "txgain")) { 14227 if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) { 14228 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno); 14229 } 14230 } else if (!strcasecmp(v->name, "tonezone")) { 14231 if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) { 14232 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno); 14233 } 14234 } else if (!strcasecmp(v->name, "callerid")) { 14235 if (!strcasecmp(v->value, "asreceived")) { 14236 confp->chan.cid_num[0] = '\0'; 14237 confp->chan.cid_name[0] = '\0'; 14238 } else { 14239 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num)); 14240 } 14241 } else if (!strcasecmp(v->name, "fullname")) { 14242 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name)); 14243 } else if (!strcasecmp(v->name, "cid_number")) { 14244 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num)); 14245 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) { 14246 confp->chan.dahditrcallerid = ast_true(v->value); 14247 } else if (!strcasecmp(v->name, "restrictcid")) { 14248 confp->chan.restrictcid = ast_true(v->value); 14249 } else if (!strcasecmp(v->name, "usecallingpres")) { 14250 confp->chan.use_callingpres = ast_true(v->value); 14251 } else if (!strcasecmp(v->name, "accountcode")) { 14252 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode)); 14253 } else if (!strcasecmp(v->name, "amaflags")) { 14254 y = ast_cdr_amaflags2int(v->value); 14255 if (y < 0) 14256 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno); 14257 else 14258 confp->chan.amaflags = y; 14259 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) { 14260 confp->chan.polarityonanswerdelay = atoi(v->value); 14261 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) { 14262 confp->chan.answeronpolarityswitch = ast_true(v->value); 14263 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) { 14264 confp->chan.hanguponpolarityswitch = ast_true(v->value); 14265 } else if (!strcasecmp(v->name, "sendcalleridafter")) { 14266 confp->chan.sendcalleridafter = atoi(v->value); 14267 } else if (!strcasecmp(v->name, "mwimonitornotify")) { 14268 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify)); 14269 } else if (reload != 1) { 14270 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) { 14271 int orig_radio = confp->chan.radio; 14272 int orig_outsigmod = confp->chan.outsigmod; 14273 int orig_auto = confp->is_sig_auto; 14274 14275 confp->chan.radio = 0; 14276 confp->chan.outsigmod = -1; 14277 confp->is_sig_auto = 0; 14278 if (!strcasecmp(v->value, "em")) { 14279 confp->chan.sig = SIG_EM; 14280 } else if (!strcasecmp(v->value, "em_e1")) { 14281 confp->chan.sig = SIG_EM_E1; 14282 } else if (!strcasecmp(v->value, "em_w")) { 14283 confp->chan.sig = SIG_EMWINK; 14284 } else if (!strcasecmp(v->value, "fxs_ls")) { 14285 confp->chan.sig = SIG_FXSLS; 14286 } else if (!strcasecmp(v->value, "fxs_gs")) { 14287 confp->chan.sig = SIG_FXSGS; 14288 } else if (!strcasecmp(v->value, "fxs_ks")) { 14289 confp->chan.sig = SIG_FXSKS; 14290 } else if (!strcasecmp(v->value, "fxo_ls")) { 14291 confp->chan.sig = SIG_FXOLS; 14292 } else if (!strcasecmp(v->value, "fxo_gs")) { 14293 confp->chan.sig = SIG_FXOGS; 14294 } else if (!strcasecmp(v->value, "fxo_ks")) { 14295 confp->chan.sig = SIG_FXOKS; 14296 } else if (!strcasecmp(v->value, "fxs_rx")) { 14297 confp->chan.sig = SIG_FXSKS; 14298 confp->chan.radio = 1; 14299 } else if (!strcasecmp(v->value, "fxo_rx")) { 14300 confp->chan.sig = SIG_FXOLS; 14301 confp->chan.radio = 1; 14302 } else if (!strcasecmp(v->value, "fxs_tx")) { 14303 confp->chan.sig = SIG_FXSLS; 14304 confp->chan.radio = 1; 14305 } else if (!strcasecmp(v->value, "fxo_tx")) { 14306 confp->chan.sig = SIG_FXOGS; 14307 confp->chan.radio = 1; 14308 } else if (!strcasecmp(v->value, "em_rx")) { 14309 confp->chan.sig = SIG_EM; 14310 confp->chan.radio = 1; 14311 } else if (!strcasecmp(v->value, "em_tx")) { 14312 confp->chan.sig = SIG_EM; 14313 confp->chan.radio = 1; 14314 } else if (!strcasecmp(v->value, "em_rxtx")) { 14315 confp->chan.sig = SIG_EM; 14316 confp->chan.radio = 2; 14317 } else if (!strcasecmp(v->value, "em_txrx")) { 14318 confp->chan.sig = SIG_EM; 14319 confp->chan.radio = 2; 14320 } else if (!strcasecmp(v->value, "sf")) { 14321 confp->chan.sig = SIG_SF; 14322 } else if (!strcasecmp(v->value, "sf_w")) { 14323 confp->chan.sig = SIG_SFWINK; 14324 } else if (!strcasecmp(v->value, "sf_featd")) { 14325 confp->chan.sig = SIG_FEATD; 14326 } else if (!strcasecmp(v->value, "sf_featdmf")) { 14327 confp->chan.sig = SIG_FEATDMF; 14328 } else if (!strcasecmp(v->value, "sf_featb")) { 14329 confp->chan.sig = SIG_SF_FEATB; 14330 } else if (!strcasecmp(v->value, "sf")) { 14331 confp->chan.sig = SIG_SF; 14332 } else if (!strcasecmp(v->value, "sf_rx")) { 14333 confp->chan.sig = SIG_SF; 14334 confp->chan.radio = 1; 14335 } else if (!strcasecmp(v->value, "sf_tx")) { 14336 confp->chan.sig = SIG_SF; 14337 confp->chan.radio = 1; 14338 } else if (!strcasecmp(v->value, "sf_rxtx")) { 14339 confp->chan.sig = SIG_SF; 14340 confp->chan.radio = 2; 14341 } else if (!strcasecmp(v->value, "sf_txrx")) { 14342 confp->chan.sig = SIG_SF; 14343 confp->chan.radio = 2; 14344 } else if (!strcasecmp(v->value, "featd")) { 14345 confp->chan.sig = SIG_FEATD; 14346 } else if (!strcasecmp(v->value, "featdmf")) { 14347 confp->chan.sig = SIG_FEATDMF; 14348 } else if (!strcasecmp(v->value, "featdmf_ta")) { 14349 confp->chan.sig = SIG_FEATDMF_TA; 14350 } else if (!strcasecmp(v->value, "e911")) { 14351 confp->chan.sig = SIG_E911; 14352 } else if (!strcasecmp(v->value, "fgccama")) { 14353 confp->chan.sig = SIG_FGC_CAMA; 14354 } else if (!strcasecmp(v->value, "fgccamamf")) { 14355 confp->chan.sig = SIG_FGC_CAMAMF; 14356 } else if (!strcasecmp(v->value, "featb")) { 14357 confp->chan.sig = SIG_FEATB; 14358 #ifdef HAVE_PRI 14359 } else if (!strcasecmp(v->value, "pri_net")) { 14360 confp->chan.sig = SIG_PRI; 14361 confp->pri.nodetype = PRI_NETWORK; 14362 } else if (!strcasecmp(v->value, "pri_cpe")) { 14363 confp->chan.sig = SIG_PRI; 14364 confp->pri.nodetype = PRI_CPE; 14365 } else if (!strcasecmp(v->value, "bri_cpe")) { 14366 confp->chan.sig = SIG_BRI; 14367 confp->pri.nodetype = PRI_CPE; 14368 } else if (!strcasecmp(v->value, "bri_net")) { 14369 confp->chan.sig = SIG_BRI; 14370 confp->pri.nodetype = PRI_NETWORK; 14371 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) { 14372 confp->chan.sig = SIG_BRI_PTMP; 14373 confp->pri.nodetype = PRI_CPE; 14374 } else if (!strcasecmp(v->value, "bri_net_ptmp")) { 14375 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno); 14376 } else if (!strcasecmp(v->value, "gr303fxoks_net")) { 14377 confp->chan.sig = SIG_GR303FXOKS; 14378 confp->pri.nodetype = PRI_NETWORK; 14379 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) { 14380 confp->chan.sig = SIG_GR303FXSKS; 14381 confp->pri.nodetype = PRI_CPE; 14382 #endif 14383 #ifdef HAVE_SS7 14384 } else if (!strcasecmp(v->value, "ss7")) { 14385 confp->chan.sig = SIG_SS7; 14386 #endif 14387 } else if (!strcasecmp(v->value, "auto")) { 14388 confp->is_sig_auto = 1; 14389 } else { 14390 confp->chan.outsigmod = orig_outsigmod; 14391 confp->chan.radio = orig_radio; 14392 confp->is_sig_auto = orig_auto; 14393 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 14394 } 14395 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) { 14396 if (!strcasecmp(v->value, "em")) { 14397 confp->chan.outsigmod = SIG_EM; 14398 } else if (!strcasecmp(v->value, "em_e1")) { 14399 confp->chan.outsigmod = SIG_EM_E1; 14400 } else if (!strcasecmp(v->value, "em_w")) { 14401 confp->chan.outsigmod = SIG_EMWINK; 14402 } else if (!strcasecmp(v->value, "sf")) { 14403 confp->chan.outsigmod = SIG_SF; 14404 } else if (!strcasecmp(v->value, "sf_w")) { 14405 confp->chan.outsigmod = SIG_SFWINK; 14406 } else if (!strcasecmp(v->value, "sf_featd")) { 14407 confp->chan.outsigmod = SIG_FEATD; 14408 } else if (!strcasecmp(v->value, "sf_featdmf")) { 14409 confp->chan.outsigmod = SIG_FEATDMF; 14410 } else if (!strcasecmp(v->value, "sf_featb")) { 14411 confp->chan.outsigmod = SIG_SF_FEATB; 14412 } else if (!strcasecmp(v->value, "sf")) { 14413 confp->chan.outsigmod = SIG_SF; 14414 } else if (!strcasecmp(v->value, "featd")) { 14415 confp->chan.outsigmod = SIG_FEATD; 14416 } else if (!strcasecmp(v->value, "featdmf")) { 14417 confp->chan.outsigmod = SIG_FEATDMF; 14418 } else if (!strcasecmp(v->value, "featdmf_ta")) { 14419 confp->chan.outsigmod = SIG_FEATDMF_TA; 14420 } else if (!strcasecmp(v->value, "e911")) { 14421 confp->chan.outsigmod = SIG_E911; 14422 } else if (!strcasecmp(v->value, "fgccama")) { 14423 confp->chan.outsigmod = SIG_FGC_CAMA; 14424 } else if (!strcasecmp(v->value, "fgccamamf")) { 14425 confp->chan.outsigmod = SIG_FGC_CAMAMF; 14426 } else if (!strcasecmp(v->value, "featb")) { 14427 confp->chan.outsigmod = SIG_FEATB; 14428 } else { 14429 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 14430 } 14431 #ifdef HAVE_PRI 14432 } else if (!strcasecmp(v->name, "pridialplan")) { 14433 if (!strcasecmp(v->value, "national")) { 14434 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1; 14435 } else if (!strcasecmp(v->value, "unknown")) { 14436 confp->pri.dialplan = PRI_UNKNOWN + 1; 14437 } else if (!strcasecmp(v->value, "private")) { 14438 confp->pri.dialplan = PRI_PRIVATE + 1; 14439 } else if (!strcasecmp(v->value, "international")) { 14440 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1; 14441 } else if (!strcasecmp(v->value, "local")) { 14442 confp->pri.dialplan = PRI_LOCAL_ISDN + 1; 14443 } else if (!strcasecmp(v->value, "dynamic")) { 14444 confp->pri.dialplan = -1; 14445 } else if (!strcasecmp(v->value, "redundant")) { 14446 confp->pri.dialplan = -2; 14447 } else { 14448 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 14449 } 14450 } else if (!strcasecmp(v->name, "prilocaldialplan")) { 14451 if (!strcasecmp(v->value, "national")) { 14452 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1; 14453 } else if (!strcasecmp(v->value, "unknown")) { 14454 confp->pri.localdialplan = PRI_UNKNOWN + 1; 14455 } else if (!strcasecmp(v->value, "private")) { 14456 confp->pri.localdialplan = PRI_PRIVATE + 1; 14457 } else if (!strcasecmp(v->value, "international")) { 14458 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1; 14459 } else if (!strcasecmp(v->value, "local")) { 14460 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1; 14461 } else if (!strcasecmp(v->value, "dynamic")) { 14462 confp->pri.localdialplan = -1; 14463 } else if (!strcasecmp(v->value, "redundant")) { 14464 confp->pri.localdialplan = -2; 14465 } else { 14466 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno); 14467 } 14468 } else if (!strcasecmp(v->name, "switchtype")) { 14469 if (!strcasecmp(v->value, "national")) 14470 confp->pri.switchtype = PRI_SWITCH_NI2; 14471 else if (!strcasecmp(v->value, "ni1")) 14472 confp->pri.switchtype = PRI_SWITCH_NI1; 14473 else if (!strcasecmp(v->value, "dms100")) 14474 confp->pri.switchtype = PRI_SWITCH_DMS100; 14475 else if (!strcasecmp(v->value, "4ess")) 14476 confp->pri.switchtype = PRI_SWITCH_ATT4ESS; 14477 else if (!strcasecmp(v->value, "5ess")) 14478 confp->pri.switchtype = PRI_SWITCH_LUCENT5E; 14479 else if (!strcasecmp(v->value, "euroisdn")) 14480 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1; 14481 else if (!strcasecmp(v->value, "qsig")) 14482 confp->pri.switchtype = PRI_SWITCH_QSIG; 14483 else { 14484 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno); 14485 return -1; 14486 } 14487 } else if (!strcasecmp(v->name, "nsf")) { 14488 if (!strcasecmp(v->value, "sdn")) 14489 confp->pri.nsf = PRI_NSF_SDN; 14490 else if (!strcasecmp(v->value, "megacom")) 14491 confp->pri.nsf = PRI_NSF_MEGACOM; 14492 else if (!strcasecmp(v->value, "tollfreemegacom")) 14493 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM; 14494 else if (!strcasecmp(v->value, "accunet")) 14495 confp->pri.nsf = PRI_NSF_ACCUNET; 14496 else if (!strcasecmp(v->value, "none")) 14497 confp->pri.nsf = PRI_NSF_NONE; 14498 else { 14499 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno); 14500 confp->pri.nsf = PRI_NSF_NONE; 14501 } 14502 } else if (!strcasecmp(v->name, "priindication")) { 14503 if (!strcasecmp(v->value, "outofband")) 14504 confp->chan.priindication_oob = 1; 14505 else if (!strcasecmp(v->value, "inband")) 14506 confp->chan.priindication_oob = 0; 14507 else 14508 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n", 14509 v->value, v->lineno); 14510 } else if (!strcasecmp(v->name, "priexclusive")) { 14511 confp->chan.priexclusive = ast_true(v->value); 14512 } else if (!strcasecmp(v->name, "internationalprefix")) { 14513 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix)); 14514 } else if (!strcasecmp(v->name, "nationalprefix")) { 14515 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix)); 14516 } else if (!strcasecmp(v->name, "localprefix")) { 14517 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix)); 14518 } else if (!strcasecmp(v->name, "privateprefix")) { 14519 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix)); 14520 } else if (!strcasecmp(v->name, "unknownprefix")) { 14521 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix)); 14522 } else if (!strcasecmp(v->name, "resetinterval")) { 14523 if (!strcasecmp(v->value, "never")) 14524 confp->pri.resetinterval = -1; 14525 else if (atoi(v->value) >= 60) 14526 confp->pri.resetinterval = atoi(v->value); 14527 else 14528 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n", 14529 v->value, v->lineno); 14530 } else if (!strcasecmp(v->name, "minunused")) { 14531 confp->pri.minunused = atoi(v->value); 14532 } else if (!strcasecmp(v->name, "minidle")) { 14533 confp->pri.minidle = atoi(v->value); 14534 } else if (!strcasecmp(v->name, "idleext")) { 14535 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext)); 14536 } else if (!strcasecmp(v->name, "idledial")) { 14537 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial)); 14538 } else if (!strcasecmp(v->name, "overlapdial")) { 14539 if (ast_true(v->value)) { 14540 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 14541 } else if (!strcasecmp(v->value, "incoming")) { 14542 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING; 14543 } else if (!strcasecmp(v->value, "outgoing")) { 14544 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING; 14545 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) { 14546 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 14547 } else { 14548 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE; 14549 } 14550 #ifdef HAVE_PRI_INBANDDISCONNECT 14551 } else if (!strcasecmp(v->name, "inbanddisconnect")) { 14552 confp->pri.inbanddisconnect = ast_true(v->value); 14553 #endif 14554 } else if (!strcasecmp(v->name, "pritimer")) { 14555 #ifdef PRI_GETSET_TIMERS 14556 char tmp[20], *timerc, *c = tmp; 14557 int timer, timeridx; 14558 ast_copy_string(tmp, v->value, sizeof(tmp)); 14559 timerc = strsep(&c, ","); 14560 if (timerc) { 14561 timer = atoi(c); 14562 if (!timer) 14563 ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer at line %d.\n", timerc, v->lineno); 14564 else { 14565 if ((timeridx = pri_timer2idx(timerc)) >= 0) 14566 pritimers[timeridx] = timer; 14567 else 14568 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer at line %d.\n", timerc, v->lineno); 14569 } 14570 } else 14571 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string at line %d.\n", v->value, v->lineno); 14572 14573 } else if (!strcasecmp(v->name, "facilityenable")) { 14574 confp->pri.facilityenable = ast_true(v->value); 14575 #endif /* PRI_GETSET_TIMERS */ 14576 #endif /* HAVE_PRI */ 14577 #ifdef HAVE_SS7 14578 } else if (!strcasecmp(v->name, "ss7type")) { 14579 if (!strcasecmp(v->value, "itu")) { 14580 cur_ss7type = SS7_ITU; 14581 } else if (!strcasecmp(v->value, "ansi")) { 14582 cur_ss7type = SS7_ANSI; 14583 } else 14584 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno); 14585 } else if (!strcasecmp(v->name, "linkset")) { 14586 cur_linkset = atoi(v->value); 14587 } else if (!strcasecmp(v->name, "pointcode")) { 14588 cur_pointcode = parse_pointcode(v->value); 14589 } else if (!strcasecmp(v->name, "adjpointcode")) { 14590 cur_adjpointcode = parse_pointcode(v->value); 14591 } else if (!strcasecmp(v->name, "defaultdpc")) { 14592 cur_defaultdpc = parse_pointcode(v->value); 14593 } else if (!strcasecmp(v->name, "cicbeginswith")) { 14594 cur_cicbeginswith = atoi(v->value); 14595 } else if (!strcasecmp(v->name, "networkindicator")) { 14596 if (!strcasecmp(v->value, "national")) 14597 cur_networkindicator = SS7_NI_NAT; 14598 else if (!strcasecmp(v->value, "national_spare")) 14599 cur_networkindicator = SS7_NI_NAT_SPARE; 14600 else if (!strcasecmp(v->value, "international")) 14601 cur_networkindicator = SS7_NI_INT; 14602 else if (!strcasecmp(v->value, "international_spare")) 14603 cur_networkindicator = SS7_NI_INT_SPARE; 14604 else 14605 cur_networkindicator = -1; 14606 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) { 14607 ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix)); 14608 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) { 14609 ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix)); 14610 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) { 14611 ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix)); 14612 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) { 14613 ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix)); 14614 } else if (!strcasecmp(v->name, "ss7_called_nai")) { 14615 if (!strcasecmp(v->value, "national")) { 14616 confp->ss7.called_nai = SS7_NAI_NATIONAL; 14617 } else if (!strcasecmp(v->value, "international")) { 14618 confp->ss7.called_nai = SS7_NAI_INTERNATIONAL; 14619 } else if (!strcasecmp(v->value, "subscriber")) { 14620 confp->ss7.called_nai = SS7_NAI_SUBSCRIBER; 14621 } else if (!strcasecmp(v->value, "dynamic")) { 14622 confp->ss7.called_nai = SS7_NAI_DYNAMIC; 14623 } else { 14624 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno); 14625 } 14626 } else if (!strcasecmp(v->name, "ss7_calling_nai")) { 14627 if (!strcasecmp(v->value, "national")) { 14628 confp->ss7.calling_nai = SS7_NAI_NATIONAL; 14629 } else if (!strcasecmp(v->value, "international")) { 14630 confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL; 14631 } else if (!strcasecmp(v->value, "subscriber")) { 14632 confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER; 14633 } else if (!strcasecmp(v->value, "dynamic")) { 14634 confp->ss7.calling_nai = SS7_NAI_DYNAMIC; 14635 } else { 14636 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno); 14637 } 14638 } else if (!strcasecmp(v->name, "sigchan")) { 14639 int sigchan, res; 14640 sigchan = atoi(v->value); 14641 res = linkset_addsigchan(sigchan); 14642 if (res < 0) 14643 return -1; 14644 14645 } else if (!strcasecmp(v->name, "ss7_explicitacm")) { 14646 struct dahdi_ss7 *link; 14647 link = ss7_resolve_linkset(cur_linkset); 14648 if (!link) { 14649 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1); 14650 return -1; 14651 } 14652 if (ast_true(v->value)) 14653 link->flags |= LINKSET_FLAG_EXPLICITACM; 14654 14655 #endif /* HAVE_SS7 */ 14656 } else if (!strcasecmp(v->name, "cadence")) { 14657 /* setup to scan our argument */ 14658 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 14659 int i; 14660 struct dahdi_ring_cadence new_cadence; 14661 int cid_location = -1; 14662 int firstcadencepos = 0; 14663 char original_args[80]; 14664 int cadence_is_ok = 1; 14665 14666 ast_copy_string(original_args, v->value, sizeof(original_args)); 14667 /* 16 cadences allowed (8 pairs) */ 14668 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]); 14669 14670 /* Cadence must be even (on/off) */ 14671 if (element_count % 2 == 1) { 14672 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno); 14673 cadence_is_ok = 0; 14674 } 14675 14676 /* Ring cadences cannot be negative */ 14677 for (i = 0; i < element_count; i++) { 14678 if (c[i] == 0) { 14679 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno); 14680 cadence_is_ok = 0; 14681 break; 14682 } else if (c[i] < 0) { 14683 if (i % 2 == 1) { 14684 /* Silence duration, negative possibly okay */ 14685 if (cid_location == -1) { 14686 cid_location = i; 14687 c[i] *= -1; 14688 } else { 14689 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno); 14690 cadence_is_ok = 0; 14691 break; 14692 } 14693 } else { 14694 if (firstcadencepos == 0) { 14695 firstcadencepos = i; /* only recorded to avoid duplicate specification */ 14696 /* duration will be passed negative to the DAHDI driver */ 14697 } else { 14698 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno); 14699 cadence_is_ok = 0; 14700 break; 14701 } 14702 } 14703 } 14704 } 14705 14706 /* Substitute our scanned cadence */ 14707 for (i = 0; i < 16; i++) { 14708 new_cadence.ringcadence[i] = c[i]; 14709 } 14710 14711 if (cadence_is_ok) { 14712 /* ---we scanned it without getting annoyed; now some sanity checks--- */ 14713 if (element_count < 2) { 14714 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno); 14715 } else { 14716 if (cid_location == -1) { 14717 /* user didn't say; default to first pause */ 14718 cid_location = 1; 14719 } else { 14720 /* convert element_index to cidrings value */ 14721 cid_location = (cid_location + 1) / 2; 14722 } 14723 /* ---we like their cadence; try to install it--- */ 14724 if (!user_has_defined_cadences++) 14725 /* this is the first user-defined cadence; clear the default user cadences */ 14726 num_cadence = 0; 14727 if ((num_cadence+1) >= NUM_CADENCE_MAX) 14728 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno); 14729 else { 14730 cadences[num_cadence] = new_cadence; 14731 cidrings[num_cadence++] = cid_location; 14732 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args); 14733 } 14734 } 14735 } 14736 } else if (!strcasecmp(v->name, "ringtimeout")) { 14737 ringt_base = (atoi(v->value) * 8) / READ_SIZE; 14738 } else if (!strcasecmp(v->name, "prewink")) { 14739 confp->timing.prewinktime = atoi(v->value); 14740 } else if (!strcasecmp(v->name, "preflash")) { 14741 confp->timing.preflashtime = atoi(v->value); 14742 } else if (!strcasecmp(v->name, "wink")) { 14743 confp->timing.winktime = atoi(v->value); 14744 } else if (!strcasecmp(v->name, "flash")) { 14745 confp->timing.flashtime = atoi(v->value); 14746 } else if (!strcasecmp(v->name, "start")) { 14747 confp->timing.starttime = atoi(v->value); 14748 } else if (!strcasecmp(v->name, "rxwink")) { 14749 confp->timing.rxwinktime = atoi(v->value); 14750 } else if (!strcasecmp(v->name, "rxflash")) { 14751 confp->timing.rxflashtime = atoi(v->value); 14752 } else if (!strcasecmp(v->name, "debounce")) { 14753 confp->timing.debouncetime = atoi(v->value); 14754 } else if (!strcasecmp(v->name, "toneduration")) { 14755 int toneduration; 14756 int ctlfd; 14757 int res; 14758 struct dahdi_dialparams dps; 14759 14760 ctlfd = open("/dev/dahdi/ctl", O_RDWR); 14761 if (ctlfd == -1) { 14762 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno); 14763 return -1; 14764 } 14765 14766 toneduration = atoi(v->value); 14767 if (toneduration > -1) { 14768 memset(&dps, 0, sizeof(dps)); 14769 14770 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration; 14771 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps); 14772 if (res < 0) { 14773 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno)); 14774 return -1; 14775 } 14776 } 14777 close(ctlfd); 14778 } else if (!strcasecmp(v->name, "defaultcic")) { 14779 ast_copy_string(defaultcic, v->value, sizeof(defaultcic)); 14780 } else if (!strcasecmp(v->name, "defaultozz")) { 14781 ast_copy_string(defaultozz, v->value, sizeof(defaultozz)); 14782 } else if (!strcasecmp(v->name, "mwilevel")) { 14783 mwilevel = atoi(v->value); 14784 } 14785 } else if (!skipchannels) 14786 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno); 14787 } 14788 if (dahdichan[0]) { 14789 /* The user has set 'dahdichan' */ 14790 /*< \todo pass proper line number instead of 0 */ 14791 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) { 14792 return -1; 14793 } 14794 } 14795 /*< \todo why check for the pseudo in the per-channel section. 14796 * Any actual use for manual setup of the pseudo channel? */ 14797 if (!found_pseudo && reload == 0) { 14798 /* Make sure pseudo isn't a member of any groups if 14799 we're automatically making it. */ 14800 14801 confp->chan.group = 0; 14802 confp->chan.callgroup = 0; 14803 confp->chan.pickupgroup = 0; 14804 14805 tmp = mkintf(CHAN_PSEUDO, confp, NULL, reload); 14806 14807 if (tmp) { 14808 ast_verb(3, "Automatically generated pseudo channel\n"); 14809 } else { 14810 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n"); 14811 } 14812 } 14813 return 0; 14814 }
static void process_echocancel | ( | struct dahdi_chan_conf * | confp, | |
const char * | data, | |||
unsigned int | line | |||
) | [static] |
Definition at line 13944 of file chan_dahdi.c.
References ARRAY_LEN, ast_app_separate_args(), ast_log(), ast_strdupa, ast_strlen_zero(), ast_true(), dahdi_chan_conf::chan, dahdi_pvt::echocancel, dahdi_pvt::head, name, dahdi_pvt::params, and parse().
Referenced by process_dahdi().
13945 { 13946 char *parse = ast_strdupa(data); 13947 char *params[DAHDI_MAX_ECHOCANPARAMS + 1]; 13948 unsigned int param_count; 13949 unsigned int x; 13950 13951 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params)))) 13952 return; 13953 13954 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel)); 13955 13956 /* first parameter is tap length, process it here */ 13957 13958 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]); 13959 13960 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024)) 13961 confp->chan.echocancel.head.tap_length = x; 13962 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0]))) 13963 confp->chan.echocancel.head.tap_length = 128; 13964 13965 /* now process any remaining parameters */ 13966 13967 for (x = 1; x < param_count; x++) { 13968 struct { 13969 char *name; 13970 char *value; 13971 } param; 13972 13973 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) { 13974 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]); 13975 continue; 13976 } 13977 13978 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) { 13979 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name); 13980 continue; 13981 } 13982 13983 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name); 13984 13985 if (param.value) { 13986 if (sscanf(param.value, "%d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) { 13987 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value); 13988 continue; 13989 } 13990 } 13991 confp->chan.echocancel.head.param_count++; 13992 } 13993 }
static char* redirectingreason2str | ( | int | redirectingreason | ) | [static] |
Definition at line 10618 of file chan_dahdi.c.
Referenced by __oh323_new().
10619 { 10620 switch (redirectingreason) { 10621 case 0: 10622 return "UNKNOWN"; 10623 case 1: 10624 return "BUSY"; 10625 case 2: 10626 return "NO_REPLY"; 10627 case 0xF: 10628 return "UNCONDITIONAL"; 10629 default: 10630 return "NOREDIRECT"; 10631 } 10632 }
static int reload | ( | void | ) | [static] |
Definition at line 15143 of file chan_dahdi.c.
References ast_log(), and setup_dahdi().
15144 { 15145 int res = 0; 15146 15147 res = setup_dahdi(1); 15148 if (res) { 15149 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n"); 15150 return -1; 15151 } 15152 return 0; 15153 }
static int reset_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1935 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().
01936 { 01937 p->confno = -1; 01938 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf)); 01939 if (p->subs[SUB_REAL].dfd > -1) { 01940 struct dahdi_confinfo zi; 01941 01942 memset(&zi, 0, sizeof(zi)); 01943 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi)) 01944 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno)); 01945 } 01946 return 0; 01947 }
static int restart_monitor | ( | void | ) | [static] |
Definition at line 8321 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(), skinny_request(), unistim_reload(), and unistim_request().
08322 { 08323 /* If we're supposed to be stopped -- stay stopped */ 08324 if (monitor_thread == AST_PTHREADT_STOP) 08325 return 0; 08326 ast_mutex_lock(&monlock); 08327 if (monitor_thread == pthread_self()) { 08328 ast_mutex_unlock(&monlock); 08329 ast_log(LOG_WARNING, "Cannot kill myself\n"); 08330 return -1; 08331 } 08332 if (monitor_thread != AST_PTHREADT_NULL) { 08333 /* Wake up the thread */ 08334 pthread_kill(monitor_thread, SIGURG); 08335 } else { 08336 /* Start a new monitor */ 08337 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 08338 ast_mutex_unlock(&monlock); 08339 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 08340 return -1; 08341 } 08342 } 08343 ast_mutex_unlock(&monlock); 08344 return 0; 08345 }
static int restore_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2317 of file chan_dahdi.c.
References ast_debug, ast_log(), errno, LOG_WARNING, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_handle_event(), dahdi_read(), and send_callerid().
02318 { 02319 int res; 02320 if (p->saveconf.confmode) { 02321 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf); 02322 p->saveconf.confmode = 0; 02323 if (res) { 02324 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno)); 02325 return -1; 02326 } 02327 } 02328 ast_debug(1, "Restored conferencing\n"); 02329 return 0; 02330 }
static int restore_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2195 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(), mwi_thread(), and ss_thread().
02196 { 02197 int res; 02198 02199 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02200 if (res) { 02201 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno)); 02202 return -1; 02203 } 02204 02205 return 0; 02206 }
static int save_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2241 of file chan_dahdi.c.
References ast_debug, ast_log(), errno, LOG_WARNING, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_callwait(), and dahdi_handle_event().
02242 { 02243 struct dahdi_confinfo c; 02244 int res; 02245 if (p->saveconf.confmode) { 02246 ast_log(LOG_WARNING, "Can't save conference -- already in use\n"); 02247 return -1; 02248 } 02249 p->saveconf.chan = 0; 02250 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf); 02251 if (res) { 02252 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno)); 02253 p->saveconf.confmode = 0; 02254 return -1; 02255 } 02256 memset(&c, 0, sizeof(c)); 02257 c.confmode = DAHDI_CONF_NORMAL; 02258 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c); 02259 if (res) { 02260 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno)); 02261 return -1; 02262 } 02263 ast_debug(1, "Disabled conferencing\n"); 02264 return 0; 02265 }
static int send_callerid | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2375 of file chan_dahdi.c.
References ast_free, ast_log(), dahdi_pvt::callwaitcas, CIDCW_EXPIRE_SAMPLES, dahdi_pvt::cidcwexpire, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_setlinear(), errno, dahdi_subchannel::linear, LOG_WARNING, restore_conference(), SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_call(), dahdi_callwait(), dahdi_read(), and send_cwcidspill().
02376 { 02377 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */ 02378 int res; 02379 /* Take out of linear mode if necessary */ 02380 if (p->subs[SUB_REAL].linear) { 02381 p->subs[SUB_REAL].linear = 0; 02382 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 02383 } 02384 while (p->cidpos < p->cidlen) { 02385 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos); 02386 if (res < 0) { 02387 if (errno == EAGAIN) 02388 return 0; 02389 else { 02390 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 02391 return -1; 02392 } 02393 } 02394 if (!res) 02395 return 0; 02396 p->cidpos += res; 02397 } 02398 ast_free(p->cidspill); 02399 p->cidspill = NULL; 02400 if (p->callwaitcas) { 02401 /* Wait for CID/CW to expire */ 02402 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES; 02403 } else 02404 restore_conference(p); 02405 return 0; 02406 }
static int send_cwcidspill | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2334 of file chan_dahdi.c.
References ast_callerid_callwaiting_generate(), AST_LAW, ast_malloc, ast_verb, 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, READ_SIZE, and send_callerid().
Referenced by dahdi_handle_dtmfup().
02335 { 02336 p->callwaitcas = 0; 02337 p->cidcwexpire = 0; 02338 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) 02339 return -1; 02340 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p)); 02341 /* Make sure we account for the end */ 02342 p->cidlen += READ_SIZE * 4; 02343 p->cidpos = 0; 02344 send_callerid(p); 02345 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num); 02346 return 0; 02347 }
static int set_actual_gain | ( | int | fd, | |
int | chan, | |||
float | rxgain, | |||
float | txgain, | |||
int | law | |||
) | [static] |
Definition at line 2176 of file chan_dahdi.c.
References set_actual_rxgain(), and set_actual_txgain().
Referenced by bump_gains(), dahdi_call(), and restore_gains().
02177 { 02178 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law); 02179 }
static int set_actual_rxgain | ( | int | fd, | |
int | chan, | |||
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2158 of file chan_dahdi.c.
References ast_debug, errno, and fill_rxgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
02159 { 02160 struct dahdi_gains g; 02161 int res; 02162 02163 memset(&g, 0, sizeof(g)); 02164 g.chan = chan; 02165 res = ioctl(fd, DAHDI_GETGAINS, &g); 02166 if (res) { 02167 ast_debug(1, "Failed to read gains: %s\n", strerror(errno)); 02168 return res; 02169 } 02170 02171 fill_rxgain(&g, gain, law); 02172 02173 return ioctl(fd, DAHDI_SETGAINS, &g); 02174 }
static int set_actual_txgain | ( | int | fd, | |
int | chan, | |||
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2140 of file chan_dahdi.c.
References ast_debug, errno, and fill_txgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
02141 { 02142 struct dahdi_gains g; 02143 int res; 02144 02145 memset(&g, 0, sizeof(g)); 02146 g.chan = chan; 02147 res = ioctl(fd, DAHDI_GETGAINS, &g); 02148 if (res) { 02149 ast_debug(1, "Failed to read gains: %s\n", strerror(errno)); 02150 return res; 02151 } 02152 02153 fill_txgain(&g, gain, law); 02154 02155 return ioctl(fd, DAHDI_SETGAINS, &g); 02156 }
static int setup_dahdi | ( | int | reload | ) | [static] |
Definition at line 14816 of file chan_dahdi.c.
References ast_category_browse(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEUNCHANGED, dahdi_chan_conf_default(), default_jbconf, global_jbconf, iflock, ast_variable::lineno, LOG_ERROR, ast_variable::name, ast_variable::next, NUM_SPANS, pri_create_spanmap(), pri_create_trunkgroup(), pris, process_dahdi(), pvts, restart_monitor(), start_pri(), and ast_variable::value.
Referenced by dahdi_restart(), load_module(), and reload().
14817 { 14818 struct ast_config *cfg, *ucfg; 14819 struct ast_variable *v; 14820 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default(); 14821 struct dahdi_chan_conf conf; 14822 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 14823 int res; 14824 14825 #ifdef HAVE_PRI 14826 char *c; 14827 int spanno; 14828 int i; 14829 int logicalspan; 14830 int trunkgroup; 14831 int dchannels[NUM_DCHANS]; 14832 #endif 14833 14834 cfg = ast_config_load(config, config_flags); 14835 14836 /* Error if we have no config file */ 14837 if (!cfg) { 14838 ast_log(LOG_ERROR, "Unable to load config %s\n", config); 14839 return 0; 14840 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 14841 ucfg = ast_config_load("users.conf", config_flags); 14842 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) 14843 return 0; 14844 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 14845 cfg = ast_config_load(config, config_flags); 14846 } else { 14847 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 14848 ucfg = ast_config_load("users.conf", config_flags); 14849 } 14850 14851 /* It's a little silly to lock it, but we mind as well just to be sure */ 14852 ast_mutex_lock(&iflock); 14853 #ifdef HAVE_PRI 14854 if (reload != 1) { 14855 /* Process trunkgroups first */ 14856 v = ast_variable_browse(cfg, "trunkgroups"); 14857 while (v) { 14858 if (!strcasecmp(v->name, "trunkgroup")) { 14859 trunkgroup = atoi(v->value); 14860 if (trunkgroup > 0) { 14861 if ((c = strchr(v->value, ','))) { 14862 i = 0; 14863 memset(dchannels, 0, sizeof(dchannels)); 14864 while (c && (i < NUM_DCHANS)) { 14865 dchannels[i] = atoi(c + 1); 14866 if (dchannels[i] < 0) { 14867 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); 14868 } else 14869 i++; 14870 c = strchr(c + 1, ','); 14871 } 14872 if (i) { 14873 if (pri_create_trunkgroup(trunkgroup, dchannels)) { 14874 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); 14875 } else 14876 ast_verb(2, "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s"); 14877 } else 14878 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 14879 } else 14880 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 14881 } else 14882 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno); 14883 } else if (!strcasecmp(v->name, "spanmap")) { 14884 spanno = atoi(v->value); 14885 if (spanno > 0) { 14886 if ((c = strchr(v->value, ','))) { 14887 trunkgroup = atoi(c + 1); 14888 if (trunkgroup > 0) { 14889 if ((c = strchr(c + 1, ','))) 14890 logicalspan = atoi(c + 1); 14891 else 14892 logicalspan = 0; 14893 if (logicalspan >= 0) { 14894 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { 14895 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 14896 } else 14897 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 14898 } else 14899 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); 14900 } else 14901 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno); 14902 } else 14903 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno); 14904 } else 14905 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno); 14906 } else { 14907 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); 14908 } 14909 v = v->next; 14910 } 14911 } 14912 #endif 14913 14914 /* Copy the default jb config over global_jbconf */ 14915 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 14916 14917 mwimonitornotify[0] = '\0'; 14918 14919 v = ast_variable_browse(cfg, "channels"); 14920 res = process_dahdi(&base_conf, v, reload, 0); 14921 ast_mutex_unlock(&iflock); 14922 ast_config_destroy(cfg); 14923 if (res) 14924 return res; 14925 if (ucfg) { 14926 char *cat; 14927 const char *chans; 14928 process_dahdi(&base_conf, ast_variable_browse(ucfg, "general"), 1, 1); 14929 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) { 14930 if (!strcasecmp(cat, "general")) 14931 continue; 14932 chans = ast_variable_retrieve(ucfg, cat, "dahdichan"); 14933 if (!ast_strlen_zero(chans)) { 14934 if (memcpy(&conf, &base_conf, sizeof(conf)) == NULL) { 14935 ast_log(LOG_ERROR, "Not enough memory for conf copy\n"); 14936 ast_config_destroy(ucfg); 14937 return -1; 14938 } 14939 process_dahdi(&conf, ast_variable_browse(ucfg, cat), reload, 0); 14940 } 14941 } 14942 ast_config_destroy(ucfg); 14943 } 14944 #ifdef HAVE_PRI 14945 if (reload != 1) { 14946 int x; 14947 for (x = 0; x < NUM_SPANS; x++) { 14948 if (pris[x].pvts[0]) { 14949 if (start_pri(pris + x)) { 14950 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1); 14951 return -1; 14952 } else 14953 ast_verb(2, "Starting D-Channel on span %d\n", x + 1); 14954 } 14955 } 14956 } 14957 #endif 14958 #ifdef HAVE_SS7 14959 if (reload != 1) { 14960 int x; 14961 for (x = 0; x < NUM_SPANS; x++) { 14962 if (linksets[x].ss7) { 14963 if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) { 14964 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1); 14965 return -1; 14966 } else 14967 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1); 14968 } 14969 } 14970 } 14971 #endif 14972 /* And start the monitor for the first time */ 14973 restart_monitor(); 14974 return 0; 14975 }
static int sigtype_to_signalling | ( | int | sigtype | ) | [static] |
static void * ss_thread | ( | void * | data | ) | [static] |
Definition at line 6521 of file chan_dahdi.c.
References ast_channel::_state, alloc_sub(), ARRAY_LEN, ast_bridged_channel(), ast_canmatch_extension(), AST_CAUSE_UNALLOCATED, AST_CONTROL_RING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_db_put(), ast_debug, ast_dsp_digitmode(), ast_dsp_digitreset(), ast_dsp_free(), ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_free, 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_verb, ast_waitfor(), ast_waitfordigit(), ast_waitstream(), buf, 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, 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, CID_START_POLARITY_IN, dahdi_pvt::context, ast_channel::context, ringContextData::contextData, dahdi_dnd(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index(), dahdi_set_hook(), dahdi_setlinear(), dahdi_tech, dahdi_wait_event(), dahdi_wink(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, dahdi_pvt::dop, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, errno, event2str(), ast_channel::exten, dahdi_pvt::exten, exten, f, 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_NOTICE, my_getsigstr(), ast_channel::name, name, NEED_MFDETECT, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::pri, quit, distRingData::range, restore_gains(), distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, 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, strsep(), 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, and dahdi_pvt::usedistinctiveringdetection.
Referenced by dahdi_handle_event(), handle_init_event(), and mwi_thread().
06522 { 06523 struct ast_channel *chan = data; 06524 struct dahdi_pvt *p = chan->tech_pvt; 06525 char exten[AST_MAX_EXTENSION] = ""; 06526 char exten2[AST_MAX_EXTENSION] = ""; 06527 unsigned char buf[256]; 06528 char dtmfcid[300]; 06529 char dtmfbuf[300]; 06530 struct callerid_state *cs = NULL; 06531 char *name = NULL, *number = NULL; 06532 int distMatches; 06533 int curRingData[3]; 06534 int receivedRingT; 06535 int counter1; 06536 int counter; 06537 int samples = 0; 06538 struct ast_smdi_md_message *smdi_msg = NULL; 06539 int flags; 06540 int i; 06541 int timeout; 06542 int getforward = 0; 06543 char *s1, *s2; 06544 int len = 0; 06545 int res; 06546 int index; 06547 06548 ast_mutex_lock(&ss_thread_lock); 06549 ss_thread_count++; 06550 ast_mutex_unlock(&ss_thread_lock); 06551 /* in the bizarre case where the channel has become a zombie before we 06552 even get started here, abort safely 06553 */ 06554 if (!p) { 06555 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name); 06556 ast_hangup(chan); 06557 goto quit; 06558 } 06559 ast_verb(3, "Starting simple switch on '%s'\n", chan->name); 06560 index = dahdi_get_index(chan, p, 1); 06561 if (index < 0) { 06562 ast_log(LOG_WARNING, "Huh?\n"); 06563 ast_hangup(chan); 06564 goto quit; 06565 } 06566 if (p->dsp) 06567 ast_dsp_digitreset(p->dsp); 06568 switch (p->sig) { 06569 #ifdef HAVE_PRI 06570 case SIG_PRI: 06571 case SIG_BRI: 06572 case SIG_BRI_PTMP: 06573 /* Now loop looking for an extension */ 06574 ast_copy_string(exten, p->exten, sizeof(exten)); 06575 len = strlen(exten); 06576 res = 0; 06577 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 06578 if (len && !ast_ignore_pattern(chan->context, exten)) 06579 tone_zone_play_tone(p->subs[index].dfd, -1); 06580 else 06581 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 06582 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) 06583 timeout = matchdigittimeout; 06584 else 06585 timeout = gendigittimeout; 06586 res = ast_waitfordigit(chan, timeout); 06587 if (res < 0) { 06588 ast_debug(1, "waitfordigit returned < 0...\n"); 06589 ast_hangup(chan); 06590 goto quit; 06591 } else if (res) { 06592 exten[len++] = res; 06593 exten[len] = '\0'; 06594 } else 06595 break; 06596 } 06597 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */ 06598 if (ast_strlen_zero(exten)) { 06599 ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n"); 06600 exten[0] = 's'; 06601 exten[1] = '\0'; 06602 } 06603 tone_zone_play_tone(p->subs[index].dfd, -1); 06604 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) { 06605 /* Start the real PBX */ 06606 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06607 if (p->dsp) ast_dsp_digitreset(p->dsp); 06608 dahdi_enable_ec(p); 06609 ast_setstate(chan, AST_STATE_RING); 06610 res = ast_pbx_run(chan); 06611 if (res) { 06612 ast_log(LOG_WARNING, "PBX exited non-zero!\n"); 06613 } 06614 } else { 06615 ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context); 06616 chan->hangupcause = AST_CAUSE_UNALLOCATED; 06617 ast_hangup(chan); 06618 p->exten[0] = '\0'; 06619 /* Since we send release complete here, we won't get one */ 06620 p->call = NULL; 06621 } 06622 goto quit; 06623 break; 06624 #endif 06625 case SIG_FEATD: 06626 case SIG_FEATDMF: 06627 case SIG_FEATDMF_TA: 06628 case SIG_E911: 06629 case SIG_FGC_CAMAMF: 06630 case SIG_FEATB: 06631 case SIG_EMWINK: 06632 case SIG_SF_FEATD: 06633 case SIG_SF_FEATDMF: 06634 case SIG_SF_FEATB: 06635 case SIG_SFWINK: 06636 if (dahdi_wink(p, index)) 06637 goto quit; 06638 /* Fall through */ 06639 case SIG_EM: 06640 case SIG_EM_E1: 06641 case SIG_SF: 06642 case SIG_FGC_CAMA: 06643 res = tone_zone_play_tone(p->subs[index].dfd, -1); 06644 if (p->dsp) 06645 ast_dsp_digitreset(p->dsp); 06646 /* set digit mode appropriately */ 06647 if (p->dsp) { 06648 if (NEED_MFDETECT(p)) 06649 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 06650 else 06651 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 06652 } 06653 memset(dtmfbuf, 0, sizeof(dtmfbuf)); 06654 /* Wait for the first digit only if immediate=no */ 06655 if (!p->immediate) 06656 /* Wait for the first digit (up to 5 seconds). */ 06657 res = ast_waitfordigit(chan, 5000); 06658 else 06659 res = 0; 06660 if (res > 0) { 06661 /* save first char */ 06662 dtmfbuf[0] = res; 06663 switch (p->sig) { 06664 case SIG_FEATD: 06665 case SIG_SF_FEATD: 06666 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06667 if (res > 0) 06668 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06669 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06670 break; 06671 case SIG_FEATDMF_TA: 06672 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06673 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06674 if (dahdi_wink(p, index)) return NULL; 06675 dtmfbuf[0] = 0; 06676 /* Wait for the first digit (up to 5 seconds). */ 06677 res = ast_waitfordigit(chan, 5000); 06678 if (res <= 0) break; 06679 dtmfbuf[0] = res; 06680 /* fall through intentionally */ 06681 case SIG_FEATDMF: 06682 case SIG_E911: 06683 case SIG_FGC_CAMAMF: 06684 case SIG_SF_FEATDMF: 06685 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06686 /* if international caca, do it again to get real ANO */ 06687 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14)) 06688 { 06689 if (dahdi_wink(p, index)) return NULL; 06690 dtmfbuf[0] = 0; 06691 /* Wait for the first digit (up to 5 seconds). */ 06692 res = ast_waitfordigit(chan, 5000); 06693 if (res <= 0) break; 06694 dtmfbuf[0] = res; 06695 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06696 } 06697 if (res > 0) { 06698 /* if E911, take off hook */ 06699 if (p->sig == SIG_E911) 06700 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06701 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000); 06702 } 06703 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06704 break; 06705 case SIG_FEATB: 06706 case SIG_SF_FEATB: 06707 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06708 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06709 break; 06710 case SIG_EMWINK: 06711 /* if we received a '*', we are actually receiving Feature Group D 06712 dial syntax, so use that mode; otherwise, fall through to normal 06713 mode 06714 */ 06715 if (res == '*') { 06716 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06717 if (res > 0) 06718 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06719 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06720 break; 06721 } 06722 default: 06723 /* If we got the first digit, get the rest */ 06724 len = 1; 06725 dtmfbuf[len] = '\0'; 06726 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06727 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06728 timeout = matchdigittimeout; 06729 } else { 06730 timeout = gendigittimeout; 06731 } 06732 res = ast_waitfordigit(chan, timeout); 06733 if (res < 0) { 06734 ast_debug(1, "waitfordigit returned < 0...\n"); 06735 ast_hangup(chan); 06736 goto quit; 06737 } else if (res) { 06738 dtmfbuf[len++] = res; 06739 dtmfbuf[len] = '\0'; 06740 } else { 06741 break; 06742 } 06743 } 06744 break; 06745 } 06746 } 06747 if (res == -1) { 06748 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno)); 06749 ast_hangup(chan); 06750 goto quit; 06751 } else if (res < 0) { 06752 ast_debug(1, "Got hung up before digits finished\n"); 06753 ast_hangup(chan); 06754 goto quit; 06755 } 06756 06757 if (p->sig == SIG_FGC_CAMA) { 06758 char anibuf[100]; 06759 06760 if (ast_safe_sleep(chan,1000) == -1) { 06761 ast_hangup(chan); 06762 goto quit; 06763 } 06764 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06765 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 06766 res = my_getsigstr(chan, anibuf, "#", 10000); 06767 if ((res > 0) && (strlen(anibuf) > 2)) { 06768 if (anibuf[strlen(anibuf) - 1] == '#') 06769 anibuf[strlen(anibuf) - 1] = 0; 06770 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2); 06771 } 06772 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 06773 } 06774 06775 ast_copy_string(exten, dtmfbuf, sizeof(exten)); 06776 if (ast_strlen_zero(exten)) 06777 ast_copy_string(exten, "s", sizeof(exten)); 06778 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) { 06779 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */ 06780 if (exten[0] == '*') { 06781 char *stringp=NULL; 06782 ast_copy_string(exten2, exten, sizeof(exten2)); 06783 /* Parse out extension and callerid */ 06784 stringp=exten2 +1; 06785 s1 = strsep(&stringp, "*"); 06786 s2 = strsep(&stringp, "*"); 06787 if (s2) { 06788 if (!ast_strlen_zero(p->cid_num)) 06789 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 06790 else 06791 ast_set_callerid(chan, s1, NULL, s1); 06792 ast_copy_string(exten, s2, sizeof(exten)); 06793 } else 06794 ast_copy_string(exten, s1, sizeof(exten)); 06795 } else if (p->sig == SIG_FEATD) 06796 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 06797 } 06798 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 06799 if (exten[0] == '*') { 06800 char *stringp=NULL; 06801 ast_copy_string(exten2, exten, sizeof(exten2)); 06802 /* Parse out extension and callerid */ 06803 stringp=exten2 +1; 06804 s1 = strsep(&stringp, "#"); 06805 s2 = strsep(&stringp, "#"); 06806 if (s2) { 06807 if (!ast_strlen_zero(p->cid_num)) 06808 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 06809 else 06810 if (*(s1 + 2)) 06811 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2); 06812 ast_copy_string(exten, s2 + 1, sizeof(exten)); 06813 } else 06814 ast_copy_string(exten, s1 + 2, sizeof(exten)); 06815 } else 06816 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 06817 } 06818 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) { 06819 if (exten[0] == '*') { 06820 char *stringp=NULL; 06821 ast_copy_string(exten2, exten, sizeof(exten2)); 06822 /* Parse out extension and callerid */ 06823 stringp=exten2 +1; 06824 s1 = strsep(&stringp, "#"); 06825 s2 = strsep(&stringp, "#"); 06826 if (s2 && (*(s2 + 1) == '0')) { 06827 if (*(s2 + 2)) 06828 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2); 06829 } 06830 if (s1) ast_copy_string(exten, s1, sizeof(exten)); 06831 else ast_copy_string(exten, "911", sizeof(exten)); 06832 } else 06833 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel); 06834 } 06835 if (p->sig == SIG_FEATB) { 06836 if (exten[0] == '*') { 06837 char *stringp=NULL; 06838 ast_copy_string(exten2, exten, sizeof(exten2)); 06839 /* Parse out extension and callerid */ 06840 stringp=exten2 +1; 06841 s1 = strsep(&stringp, "#"); 06842 ast_copy_string(exten, exten2 + 1, sizeof(exten)); 06843 } else 06844 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel); 06845 } 06846 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 06847 dahdi_wink(p, index); 06848 /* some switches require a minimum guard time between 06849 the last FGD wink and something that answers 06850 immediately. This ensures it */ 06851 if (ast_safe_sleep(chan,100)) goto quit; 06852 } 06853 dahdi_enable_ec(p); 06854 if (NEED_MFDETECT(p)) { 06855 if (p->dsp) { 06856 if (!p->hardwaredtmf) 06857 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 06858 else { 06859 ast_dsp_free(p->dsp); 06860 p->dsp = NULL; 06861 } 06862 } 06863 } 06864 06865 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) { 06866 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06867 if (p->dsp) ast_dsp_digitreset(p->dsp); 06868 res = ast_pbx_run(chan); 06869 if (res) { 06870 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 06871 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06872 } 06873 goto quit; 06874 } else { 06875 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context); 06876 sleep(2); 06877 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO); 06878 if (res < 0) 06879 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel); 06880 else 06881 sleep(1); 06882 res = ast_streamfile(chan, "ss-noservice", chan->language); 06883 if (res >= 0) 06884 ast_waitstream(chan, ""); 06885 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06886 ast_hangup(chan); 06887 goto quit; 06888 } 06889 break; 06890 case SIG_FXOLS: 06891 case SIG_FXOGS: 06892 case SIG_FXOKS: 06893 /* Read the first digit */ 06894 timeout = firstdigittimeout; 06895 /* If starting a threeway call, never timeout on the first digit so someone 06896 can use flash-hook as a "hold" feature */ 06897 if (p->subs[SUB_THREEWAY].owner) 06898 timeout = 999999; 06899 while (len < AST_MAX_EXTENSION-1) { 06900 /* Read digit unless it's supposed to be immediate, in which case the 06901 only answer is 's' */ 06902 if (p->immediate) 06903 res = 's'; 06904 else 06905 res = ast_waitfordigit(chan, timeout); 06906 timeout = 0; 06907 if (res < 0) { 06908 ast_debug(1, "waitfordigit returned < 0...\n"); 06909 res = tone_zone_play_tone(p->subs[index].dfd, -1); 06910 ast_hangup(chan); 06911 goto quit; 06912 } else if (res) { 06913 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout); 06914 exten[len++]=res; 06915 exten[len] = '\0'; 06916 } 06917 if (!ast_ignore_pattern(chan->context, exten)) 06918 tone_zone_play_tone(p->subs[index].dfd, -1); 06919 else 06920 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 06921 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) { 06922 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 06923 if (getforward) { 06924 /* Record this as the forwarding extension */ 06925 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 06926 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel); 06927 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06928 if (res) 06929 break; 06930 usleep(500000); 06931 res = tone_zone_play_tone(p->subs[index].dfd, -1); 06932 sleep(1); 06933 memset(exten, 0, sizeof(exten)); 06934 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 06935 len = 0; 06936 getforward = 0; 06937 } else { 06938 res = tone_zone_play_tone(p->subs[index].dfd, -1); 06939 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06940 if (!ast_strlen_zero(p->cid_num)) { 06941 if (!p->hidecallerid) 06942 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 06943 else 06944 ast_set_callerid(chan, NULL, NULL, p->cid_num); 06945 } 06946 if (!ast_strlen_zero(p->cid_name)) { 06947 if (!p->hidecallerid) 06948 ast_set_callerid(chan, NULL, p->cid_name, NULL); 06949 } 06950 ast_setstate(chan, AST_STATE_RING); 06951 dahdi_enable_ec(p); 06952 res = ast_pbx_run(chan); 06953 if (res) { 06954 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 06955 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06956 } 06957 goto quit; 06958 } 06959 } else { 06960 /* It's a match, but they just typed a digit, and there is an ambiguous match, 06961 so just set the timeout to matchdigittimeout and wait some more */ 06962 timeout = matchdigittimeout; 06963 } 06964 } else if (res == 0) { 06965 ast_debug(1, "not enough digits (and no ambiguous match)...\n"); 06966 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06967 dahdi_wait_event(p->subs[index].dfd); 06968 ast_hangup(chan); 06969 goto quit; 06970 } else if (p->callwaiting && !strcmp(exten, "*70")) { 06971 ast_verb(3, "Disabling call waiting on %s\n", chan->name); 06972 /* Disable call waiting if enabled */ 06973 p->callwaiting = 0; 06974 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06975 if (res) { 06976 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 06977 chan->name, strerror(errno)); 06978 } 06979 len = 0; 06980 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len); 06981 memset(exten, 0, sizeof(exten)); 06982 timeout = firstdigittimeout; 06983 06984 } else if (!strcmp(exten,ast_pickup_ext())) { 06985 /* Scan all channels and see if there are any 06986 * ringing channels that have call groups 06987 * that equal this channels pickup group 06988 */ 06989 if (index == SUB_REAL) { 06990 /* Switch us from Third call to Call Wait */ 06991 if (p->subs[SUB_THREEWAY].owner) { 06992 /* If you make a threeway call and the *8# a call, it should actually 06993 look like a callwait */ 06994 alloc_sub(p, SUB_CALLWAIT); 06995 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 06996 unalloc_sub(p, SUB_THREEWAY); 06997 } 06998 dahdi_enable_ec(p); 06999 if (ast_pickup_call(chan)) { 07000 ast_debug(1, "No call pickup possible...\n"); 07001 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07002 dahdi_wait_event(p->subs[index].dfd); 07003 } 07004 ast_hangup(chan); 07005 goto quit; 07006 } else { 07007 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n"); 07008 ast_hangup(chan); 07009 goto quit; 07010 } 07011 07012 } else if (!p->hidecallerid && !strcmp(exten, "*67")) { 07013 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name); 07014 /* Disable Caller*ID if enabled */ 07015 p->hidecallerid = 1; 07016 if (chan->cid.cid_num) 07017 ast_free(chan->cid.cid_num); 07018 chan->cid.cid_num = NULL; 07019 if (chan->cid.cid_name) 07020 ast_free(chan->cid.cid_name); 07021 chan->cid.cid_name = NULL; 07022 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07023 if (res) { 07024 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07025 chan->name, strerror(errno)); 07026 } 07027 len = 0; 07028 memset(exten, 0, sizeof(exten)); 07029 timeout = firstdigittimeout; 07030 } else if (p->callreturn && !strcmp(exten, "*69")) { 07031 res = 0; 07032 if (!ast_strlen_zero(p->lastcid_num)) { 07033 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language); 07034 } 07035 if (!res) 07036 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07037 break; 07038 } else if (!strcmp(exten, "*78")) { 07039 dahdi_dnd(p, 1); 07040 /* Do not disturb */ 07041 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07042 getforward = 0; 07043 memset(exten, 0, sizeof(exten)); 07044 len = 0; 07045 } else if (!strcmp(exten, "*79")) { 07046 dahdi_dnd(p, 0); 07047 /* Do not disturb */ 07048 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07049 getforward = 0; 07050 memset(exten, 0, sizeof(exten)); 07051 len = 0; 07052 } else if (p->cancallforward && !strcmp(exten, "*72")) { 07053 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07054 getforward = 1; 07055 memset(exten, 0, sizeof(exten)); 07056 len = 0; 07057 } else if (p->cancallforward && !strcmp(exten, "*73")) { 07058 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel); 07059 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07060 memset(p->call_forward, 0, sizeof(p->call_forward)); 07061 getforward = 0; 07062 memset(exten, 0, sizeof(exten)); 07063 len = 0; 07064 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 07065 p->subs[SUB_THREEWAY].owner && 07066 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 07067 /* This is a three way call, the main call being a real channel, 07068 and we're parking the first call. */ 07069 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL); 07070 ast_verb(3, "Parking call to '%s'\n", chan->name); 07071 break; 07072 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) { 07073 ast_verb(3, "Blacklisting number %s\n", p->lastcid_num); 07074 res = ast_db_put("blacklist", p->lastcid_num, "1"); 07075 if (!res) { 07076 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07077 memset(exten, 0, sizeof(exten)); 07078 len = 0; 07079 } 07080 } else if (p->hidecallerid && !strcmp(exten, "*82")) { 07081 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name); 07082 /* Enable Caller*ID if enabled */ 07083 p->hidecallerid = 0; 07084 if (chan->cid.cid_num) 07085 ast_free(chan->cid.cid_num); 07086 chan->cid.cid_num = NULL; 07087 if (chan->cid.cid_name) 07088 ast_free(chan->cid.cid_name); 07089 chan->cid.cid_name = NULL; 07090 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 07091 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07092 if (res) { 07093 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07094 chan->name, strerror(errno)); 07095 } 07096 len = 0; 07097 memset(exten, 0, sizeof(exten)); 07098 timeout = firstdigittimeout; 07099 } else if (!strcmp(exten, "*0")) { 07100 struct ast_channel *nbridge = 07101 p->subs[SUB_THREEWAY].owner; 07102 struct dahdi_pvt *pbridge = NULL; 07103 /* set up the private struct of the bridged one, if any */ 07104 if (nbridge && ast_bridged_channel(nbridge)) 07105 pbridge = ast_bridged_channel(nbridge)->tech_pvt; 07106 if (nbridge && pbridge && 07107 (nbridge->tech == &dahdi_tech) && 07108 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) && 07109 ISTRUNK(pbridge)) { 07110 int func = DAHDI_FLASH; 07111 /* Clear out the dial buffer */ 07112 p->dop.dialstr[0] = '\0'; 07113 /* flash hookswitch */ 07114 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 07115 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 07116 nbridge->name, strerror(errno)); 07117 } 07118 swap_subs(p, SUB_REAL, SUB_THREEWAY); 07119 unalloc_sub(p, SUB_THREEWAY); 07120 p->owner = p->subs[SUB_REAL].owner; 07121 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 07122 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 07123 ast_hangup(chan); 07124 goto quit; 07125 } else { 07126 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07127 dahdi_wait_event(p->subs[index].dfd); 07128 tone_zone_play_tone(p->subs[index].dfd, -1); 07129 swap_subs(p, SUB_REAL, SUB_THREEWAY); 07130 unalloc_sub(p, SUB_THREEWAY); 07131 p->owner = p->subs[SUB_REAL].owner; 07132 ast_hangup(chan); 07133 goto quit; 07134 } 07135 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) && 07136 ((exten[0] != '*') || (strlen(exten) > 2))) { 07137 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context); 07138 break; 07139 } 07140 if (!timeout) 07141 timeout = gendigittimeout; 07142 if (len && !ast_ignore_pattern(chan->context, exten)) 07143 tone_zone_play_tone(p->subs[index].dfd, -1); 07144 } 07145 break; 07146 case SIG_FXSLS: 07147 case SIG_FXSGS: 07148 case SIG_FXSKS: 07149 #ifdef HAVE_PRI 07150 if (p->pri) { 07151 /* This is a GR-303 trunk actually. Wait for the first ring... */ 07152 struct ast_frame *f; 07153 int res; 07154 time_t start; 07155 07156 time(&start); 07157 ast_setstate(chan, AST_STATE_RING); 07158 while (time(NULL) < start + 3) { 07159 res = ast_waitfor(chan, 1000); 07160 if (res) { 07161 f = ast_read(chan); 07162 if (!f) { 07163 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n"); 07164 ast_hangup(chan); 07165 goto quit; 07166 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) { 07167 res = 1; 07168 } else 07169 res = 0; 07170 ast_frfree(f); 07171 if (res) { 07172 ast_debug(1, "Got ring!\n"); 07173 res = 0; 07174 break; 07175 } 07176 } 07177 } 07178 } 07179 #endif 07180 /* check for SMDI messages */ 07181 if (p->use_smdi && p->smdi_iface) { 07182 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); 07183 07184 if (smdi_msg != NULL) { 07185 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten)); 07186 07187 if (smdi_msg->type == 'B') 07188 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b"); 07189 else if (smdi_msg->type == 'N') 07190 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u"); 07191 07192 ast_debug(1, "Recieved SMDI message on %s\n", chan->name); 07193 } else { 07194 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n"); 07195 } 07196 } 07197 07198 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) { 07199 number = smdi_msg->calling_st; 07200 07201 /* If we want caller id, we're in a prering state due to a polarity reversal 07202 * and we're set to use a polarity reversal to trigger the start of caller id, 07203 * grab the caller id and wait for ringing to start... */ 07204 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) { 07205 /* If set to use DTMF CID signalling, listen for DTMF */ 07206 if (p->cid_signalling == CID_SIG_DTMF) { 07207 int i = 0; 07208 cs = NULL; 07209 ast_debug(1, "Receiving DTMF cid on " 07210 "channel %s\n", chan->name); 07211 dahdi_setlinear(p->subs[index].dfd, 0); 07212 res = 2000; 07213 for (;;) { 07214 struct ast_frame *f; 07215 res = ast_waitfor(chan, res); 07216 if (res <= 0) { 07217 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 07218 "Exiting simple switch\n"); 07219 ast_hangup(chan); 07220 goto quit; 07221 } 07222 f = ast_read(chan); 07223 if (!f) 07224 break; 07225 if (f->frametype == AST_FRAME_DTMF) { 07226 dtmfbuf[i++] = f->subclass; 07227 ast_debug(1, "CID got digit '%c'\n", f->subclass); 07228 res = 2000; 07229 } 07230 ast_frfree(f); 07231 if (chan->_state == AST_STATE_RING || 07232 chan->_state == AST_STATE_RINGING) 07233 break; /* Got ring */ 07234 } 07235 dtmfbuf[i] = '\0'; 07236 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 07237 /* Got cid and ring. */ 07238 ast_debug(1, "CID got string '%s'\n", dtmfbuf); 07239 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 07240 ast_debug(1, "CID is '%s', flags %d\n", 07241 dtmfcid, flags); 07242 /* If first byte is NULL, we have no cid */ 07243 if (!ast_strlen_zero(dtmfcid)) 07244 number = dtmfcid; 07245 else 07246 number = NULL; 07247 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 07248 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { 07249 cs = callerid_new(p->cid_signalling); 07250 if (cs) { 07251 samples = 0; 07252 #if 1 07253 bump_gains(p); 07254 #endif 07255 /* Take out of linear mode for Caller*ID processing */ 07256 dahdi_setlinear(p->subs[index].dfd, 0); 07257 07258 /* First we wait and listen for the Caller*ID */ 07259 for (;;) { 07260 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07261 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 07262 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07263 callerid_free(cs); 07264 ast_hangup(chan); 07265 goto quit; 07266 } 07267 if (i & DAHDI_IOMUX_SIGEVENT) { 07268 res = dahdi_get_event(p->subs[index].dfd); 07269 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07270 07271 if (p->cid_signalling == CID_SIG_V23_JP) { 07272 if (res == DAHDI_EVENT_RINGBEGIN) { 07273 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07274 usleep(1); 07275 } 07276 } else { 07277 res = 0; 07278 break; 07279 } 07280 } else if (i & DAHDI_IOMUX_READ) { 07281 res = read(p->subs[index].dfd, buf, sizeof(buf)); 07282 if (res < 0) { 07283 if (errno != ELAST) { 07284 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07285 callerid_free(cs); 07286 ast_hangup(chan); 07287 goto quit; 07288 } 07289 break; 07290 } 07291 samples += res; 07292 07293 if (p->cid_signalling == CID_SIG_V23_JP) { 07294 res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); 07295 } else { 07296 res = callerid_feed(cs, buf, res, AST_LAW(p)); 07297 } 07298 07299 if (res < 0) { 07300 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name); 07301 break; 07302 } else if (res) 07303 break; 07304 else if (samples > (8000 * 10)) 07305 break; 07306 } 07307 } 07308 if (res == 1) { 07309 callerid_get(cs, &name, &number, &flags); 07310 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 07311 } 07312 07313 if (p->cid_signalling == CID_SIG_V23_JP) { 07314 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 07315 usleep(1); 07316 res = 4000; 07317 } else { 07318 07319 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 07320 res = 2000; 07321 } 07322 07323 for (;;) { 07324 struct ast_frame *f; 07325 res = ast_waitfor(chan, res); 07326 if (res <= 0) { 07327 ast_log(LOG_WARNING, "CID timed out waiting for ring. " 07328 "Exiting simple switch\n"); 07329 ast_hangup(chan); 07330 goto quit; 07331 } 07332 if (!(f = ast_read(chan))) { 07333 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); 07334 ast_hangup(chan); 07335 goto quit; 07336 } 07337 ast_frfree(f); 07338 if (chan->_state == AST_STATE_RING || 07339 chan->_state == AST_STATE_RINGING) 07340 break; /* Got ring */ 07341 } 07342 07343 /* We must have a ring by now, so, if configured, lets try to listen for 07344 * distinctive ringing */ 07345 if (p->usedistinctiveringdetection) { 07346 len = 0; 07347 distMatches = 0; 07348 /* Clear the current ring data array so we dont have old data in it. */ 07349 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 07350 curRingData[receivedRingT] = 0; 07351 receivedRingT = 0; 07352 counter = 0; 07353 counter1 = 0; 07354 /* Check to see if context is what it should be, if not set to be. */ 07355 if (strcmp(p->context,p->defcontext) != 0) { 07356 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 07357 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 07358 } 07359 07360 for (;;) { 07361 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07362 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 07363 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07364 callerid_free(cs); 07365 ast_hangup(chan); 07366 goto quit; 07367 } 07368 if (i & DAHDI_IOMUX_SIGEVENT) { 07369 res = dahdi_get_event(p->subs[index].dfd); 07370 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07371 res = 0; 07372 /* Let us detect distinctive ring */ 07373 07374 curRingData[receivedRingT] = p->ringt; 07375 07376 if (p->ringt < p->ringt_base/2) 07377 break; 07378 /* Increment the ringT counter so we can match it against 07379 values in chan_dahdi.conf for distinctive ring */ 07380 if (++receivedRingT == ARRAY_LEN(curRingData)) 07381 break; 07382 } else if (i & DAHDI_IOMUX_READ) { 07383 res = read(p->subs[index].dfd, buf, sizeof(buf)); 07384 if (res < 0) { 07385 if (errno != ELAST) { 07386 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07387 callerid_free(cs); 07388 ast_hangup(chan); 07389 goto quit; 07390 } 07391 break; 07392 } 07393 if (p->ringt) 07394 p->ringt--; 07395 if (p->ringt == 1) { 07396 res = -1; 07397 break; 07398 } 07399 } 07400 } 07401 /* this only shows up if you have n of the dring patterns filled in */ 07402 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 07403 for (counter = 0; counter < 3; counter++) { 07404 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 07405 channel */ 07406 distMatches = 0; 07407 for (counter1 = 0; counter1 < 3; counter1++) { 07408 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 07409 if (p->drings.ringnum[counter].ring[counter1] == -1) { 07410 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 07411 curRingData[counter1]); 07412 distMatches++; 07413 } 07414 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 07415 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 07416 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 07417 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 07418 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 07419 distMatches++; 07420 } 07421 } 07422 07423 if (distMatches == 3) { 07424 /* The ring matches, set the context to whatever is for distinctive ring.. */ 07425 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 07426 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 07427 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 07428 break; 07429 } 07430 } 07431 } 07432 /* Restore linear mode (if appropriate) for Caller*ID processing */ 07433 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 07434 #if 1 07435 restore_gains(p); 07436 #endif 07437 } else 07438 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 07439 } else { 07440 ast_log(LOG_WARNING, "Channel %s in prering " 07441 "state, but I have nothing to do. " 07442 "Terminating simple switch, should be " 07443 "restarted by the actual ring.\n", 07444 chan->name); 07445 ast_hangup(chan); 07446 goto quit; 07447 } 07448 } else if (p->use_callerid && p->cid_start == CID_START_RING) { 07449 if (p->cid_signalling == CID_SIG_DTMF) { 07450 int i = 0; 07451 cs = NULL; 07452 dahdi_setlinear(p->subs[index].dfd, 0); 07453 res = 2000; 07454 for (;;) { 07455 struct ast_frame *f; 07456 res = ast_waitfor(chan, res); 07457 if (res <= 0) { 07458 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 07459 "Exiting simple switch\n"); 07460 ast_hangup(chan); 07461 return NULL; 07462 } 07463 f = ast_read(chan); 07464 if (f->frametype == AST_FRAME_DTMF) { 07465 dtmfbuf[i++] = f->subclass; 07466 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass); 07467 res = 2000; 07468 } 07469 ast_frfree(f); 07470 07471 if (p->ringt_base == p->ringt) 07472 break; 07473 07474 } 07475 dtmfbuf[i] = '\0'; 07476 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 07477 /* Got cid and ring. */ 07478 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 07479 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 07480 dtmfcid, flags); 07481 /* If first byte is NULL, we have no cid */ 07482 if (!ast_strlen_zero(dtmfcid)) 07483 number = dtmfcid; 07484 else 07485 number = NULL; 07486 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 07487 } else { 07488 /* FSK Bell202 callerID */ 07489 cs = callerid_new(p->cid_signalling); 07490 if (cs) { 07491 #if 1 07492 bump_gains(p); 07493 #endif 07494 samples = 0; 07495 len = 0; 07496 distMatches = 0; 07497 /* Clear the current ring data array so we dont have old data in it. */ 07498 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 07499 curRingData[receivedRingT] = 0; 07500 receivedRingT = 0; 07501 counter = 0; 07502 counter1 = 0; 07503 /* Check to see if context is what it should be, if not set to be. */ 07504 if (strcmp(p->context,p->defcontext) != 0) { 07505 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 07506 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 07507 } 07508 07509 /* Take out of linear mode for Caller*ID processing */ 07510 dahdi_setlinear(p->subs[index].dfd, 0); 07511 for (;;) { 07512 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07513 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 07514 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07515 callerid_free(cs); 07516 ast_hangup(chan); 07517 goto quit; 07518 } 07519 if (i & DAHDI_IOMUX_SIGEVENT) { 07520 res = dahdi_get_event(p->subs[index].dfd); 07521 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07522 /* If we get a PR event, they hung up while processing calerid */ 07523 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { 07524 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); 07525 p->polarity = POLARITY_IDLE; 07526 callerid_free(cs); 07527 ast_hangup(chan); 07528 goto quit; 07529 } 07530 res = 0; 07531 /* Let us detect callerid when the telco uses distinctive ring */ 07532 07533 curRingData[receivedRingT] = p->ringt; 07534 07535 if (p->ringt < p->ringt_base/2) 07536 break; 07537 /* Increment the ringT counter so we can match it against 07538 values in chan_dahdi.conf for distinctive ring */ 07539 if (++receivedRingT == ARRAY_LEN(curRingData)) 07540 break; 07541 } else if (i & DAHDI_IOMUX_READ) { 07542 res = read(p->subs[index].dfd, buf, sizeof(buf)); 07543 if (res < 0) { 07544 if (errno != ELAST) { 07545 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07546 callerid_free(cs); 07547 ast_hangup(chan); 07548 goto quit; 07549 } 07550 break; 07551 } 07552 if (p->ringt) 07553 p->ringt--; 07554 if (p->ringt == 1) { 07555 res = -1; 07556 break; 07557 } 07558 samples += res; 07559 res = callerid_feed(cs, buf, res, AST_LAW(p)); 07560 if (res < 0) { 07561 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno)); 07562 break; 07563 } else if (res) 07564 break; 07565 else if (samples > (8000 * 10)) 07566 break; 07567 } 07568 } 07569 if (res == 1) { 07570 callerid_get(cs, &name, &number, &flags); 07571 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 07572 } 07573 if (distinctiveringaftercid == 1) { 07574 /* Clear the current ring data array so we dont have old data in it. */ 07575 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) { 07576 curRingData[receivedRingT] = 0; 07577 } 07578 receivedRingT = 0; 07579 ast_verb(3, "Detecting post-CID distinctive ring\n"); 07580 for (;;) { 07581 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07582 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 07583 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07584 callerid_free(cs); 07585 ast_hangup(chan); 07586 goto quit; 07587 } 07588 if (i & DAHDI_IOMUX_SIGEVENT) { 07589 res = dahdi_get_event(p->subs[index].dfd); 07590 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07591 res = 0; 07592 /* Let us detect callerid when the telco uses distinctive ring */ 07593 07594 curRingData[receivedRingT] = p->ringt; 07595 07596 if (p->ringt < p->ringt_base/2) 07597 break; 07598 /* Increment the ringT counter so we can match it against 07599 values in chan_dahdi.conf for distinctive ring */ 07600 if (++receivedRingT == ARRAY_LEN(curRingData)) 07601 break; 07602 } else if (i & DAHDI_IOMUX_READ) { 07603 res = read(p->subs[index].dfd, buf, sizeof(buf)); 07604 if (res < 0) { 07605 if (errno != ELAST) { 07606 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07607 callerid_free(cs); 07608 ast_hangup(chan); 07609 goto quit; 07610 } 07611 break; 07612 } 07613 if (p->ringt) 07614 p->ringt--; 07615 if (p->ringt == 1) { 07616 res = -1; 07617 break; 07618 } 07619 } 07620 } 07621 } 07622 if (p->usedistinctiveringdetection) { 07623 /* this only shows up if you have n of the dring patterns filled in */ 07624 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 07625 07626 for (counter = 0; counter < 3; counter++) { 07627 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 07628 channel */ 07629 /* this only shows up if you have n of the dring patterns filled in */ 07630 ast_verb(3, "Checking %d,%d,%d\n", 07631 p->drings.ringnum[counter].ring[0], 07632 p->drings.ringnum[counter].ring[1], 07633 p->drings.ringnum[counter].ring[2]); 07634 distMatches = 0; 07635 for (counter1 = 0; counter1 < 3; counter1++) { 07636 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 07637 if (p->drings.ringnum[counter].ring[counter1] == -1) { 07638 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 07639 curRingData[counter1]); 07640 distMatches++; 07641 } 07642 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 07643 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 07644 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 07645 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 07646 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 07647 distMatches++; 07648 } 07649 } 07650 if (distMatches == 3) { 07651 /* The ring matches, set the context to whatever is for distinctive ring.. */ 07652 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 07653 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 07654 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 07655 break; 07656 } 07657 } 07658 } 07659 /* Restore linear mode (if appropriate) for Caller*ID processing */ 07660 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 07661 #if 1 07662 restore_gains(p); 07663 #endif 07664 if (res < 0) { 07665 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); 07666 } 07667 } else 07668 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 07669 } 07670 } 07671 else 07672 cs = NULL; 07673 07674 if (number) 07675 ast_shrink_phone_number(number); 07676 ast_set_callerid(chan, number, name, number); 07677 07678 if (smdi_msg) 07679 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy); 07680 07681 if (cs) 07682 callerid_free(cs); 07683 07684 ast_setstate(chan, AST_STATE_RING); 07685 chan->rings = 1; 07686 p->ringt = p->ringt_base; 07687 res = ast_pbx_run(chan); 07688 if (res) { 07689 ast_hangup(chan); 07690 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07691 } 07692 goto quit; 07693 default: 07694 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel); 07695 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07696 if (res < 0) 07697 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 07698 } 07699 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07700 if (res < 0) 07701 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 07702 ast_hangup(chan); 07703 quit: 07704 ast_mutex_lock(&ss_thread_lock); 07705 ss_thread_count--; 07706 ast_cond_signal(&ss_thread_complete); 07707 ast_mutex_unlock(&ss_thread_lock); 07708 return NULL; 07709 }
static int start_pri | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 11775 of file chan_dahdi.c.
References ast_log(), dahdi_close_pri_fd(), DAHDI_OVERLAPDIAL_BOTH, DAHDI_OVERLAPDIAL_OUTGOING, DCHAN_NOTINALARM, dahdi_pri::dchanavail, dahdi_pri::dchannels, dahdi_pri::dchans, DEFAULT_PRI_DEBUG, errno, dahdi_pri::fds, dahdi_pri::inbanddisconnect, LOG_ERROR, dahdi_pri::nodetype, dahdi_pri::nsf, dahdi_pri::overlapdial, dahdi_pri::sig, SIG_BRI, SIG_BRI_PTMP, and dahdi_pri::switchtype.
Referenced by setup_dahdi().
11776 { 11777 int res, x; 11778 struct dahdi_params p; 11779 struct dahdi_bufferinfo bi; 11780 struct dahdi_spaninfo si; 11781 int i; 11782 11783 for (i = 0; i < NUM_DCHANS; i++) { 11784 if (!pri->dchannels[i]) 11785 break; 11786 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR); 11787 x = pri->dchannels[i]; 11788 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) { 11789 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno)); 11790 return -1; 11791 } 11792 memset(&p, 0, sizeof(p)); 11793 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p); 11794 if (res) { 11795 dahdi_close_pri_fd(pri, i); 11796 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno)); 11797 return -1; 11798 } 11799 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) { 11800 dahdi_close_pri_fd(pri, i); 11801 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x); 11802 return -1; 11803 } 11804 memset(&si, 0, sizeof(si)); 11805 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si); 11806 if (res) { 11807 dahdi_close_pri_fd(pri, i); 11808 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno)); 11809 } 11810 if (!si.alarms) 11811 pri->dchanavail[i] |= DCHAN_NOTINALARM; 11812 else 11813 pri->dchanavail[i] &= ~DCHAN_NOTINALARM; 11814 memset(&bi, 0, sizeof(bi)); 11815 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 11816 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 11817 bi.numbufs = 32; 11818 bi.bufsize = 1024; 11819 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) { 11820 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno)); 11821 dahdi_close_pri_fd(pri, i); 11822 return -1; 11823 } 11824 switch (pri->sig) { 11825 case SIG_BRI: 11826 pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype); 11827 break; 11828 case SIG_BRI_PTMP: 11829 pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype); 11830 break; 11831 default: 11832 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype); 11833 } 11834 /* Force overlap dial if we're doing GR-303! */ 11835 if (pri->switchtype == PRI_SWITCH_GR303_TMC) 11836 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH; 11837 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0); 11838 #ifdef HAVE_PRI_INBANDDISCONNECT 11839 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect); 11840 #endif 11841 /* Enslave to master if appropriate */ 11842 if (i) 11843 pri_enslave(pri->dchans[0], pri->dchans[i]); 11844 if (!pri->dchans[i]) { 11845 dahdi_close_pri_fd(pri, i); 11846 ast_log(LOG_ERROR, "Unable to create PRI structure\n"); 11847 return -1; 11848 } 11849 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG); 11850 pri_set_nsf(pri->dchans[i], pri->nsf); 11851 #ifdef PRI_GETSET_TIMERS 11852 for (x = 0; x < PRI_MAX_TIMERS; x++) { 11853 if (pritimers[x] != 0) 11854 pri_set_timer(pri->dchans[i], x, pritimers[x]); 11855 } 11856 #endif 11857 } 11858 /* Assume primary is the one we use */ 11859 pri->pri = pri->dchans[0]; 11860 pri->resetpos = -1; 11861 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) { 11862 for (i = 0; i < NUM_DCHANS; i++) { 11863 if (!pri->dchannels[i]) 11864 break; 11865 dahdi_close_pri_fd(pri, i); 11866 } 11867 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno)); 11868 return -1; 11869 } 11870 return 0; 11871 }
static void swap_subs | ( | struct dahdi_pvt * | p, | |
int | a, | |||
int | b | |||
) | [static] |
Definition at line 1409 of file chan_dahdi.c.
References ast_channel_set_fd(), ast_debug, dahdi_subchannel::chan, dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, dahdi_subchannel::owner, dahdi_pvt::subs, and wakeup_sub().
Referenced by attempt_transfer(), dahdi_answer(), dahdi_handle_event(), dahdi_hangup(), HandleCallOutgoing(), ss_thread(), and unistim_hangup().
01410 { 01411 int tchan; 01412 int tinthreeway; 01413 struct ast_channel *towner; 01414 01415 ast_debug(1, "Swapping %d and %d\n", a, b); 01416 01417 tchan = p->subs[a].chan; 01418 towner = p->subs[a].owner; 01419 tinthreeway = p->subs[a].inthreeway; 01420 01421 p->subs[a].chan = p->subs[b].chan; 01422 p->subs[a].owner = p->subs[b].owner; 01423 p->subs[a].inthreeway = p->subs[b].inthreeway; 01424 01425 p->subs[b].chan = tchan; 01426 p->subs[b].owner = towner; 01427 p->subs[b].inthreeway = tinthreeway; 01428 01429 if (p->subs[a].owner) 01430 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd); 01431 if (p->subs[b].owner) 01432 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd); 01433 wakeup_sub(p, a, NULL); 01434 wakeup_sub(p, b, NULL); 01435 }
static int unalloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 1559 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_subchannel::chan, dahdi_pvt::channel, dahdi_subchannel::curconf, dahdi_close_sub(), dahdi_subchannel::inthreeway, dahdi_subchannel::linear, LOG_WARNING, dahdi_subchannel::owner, dahdi_pvt::polarity, POLARITY_IDLE, and dahdi_pvt::subs.
Referenced by attempt_transfer(), dahdi_handle_event(), dahdi_hangup(), ss_thread(), and unistim_hangup().
01560 { 01561 if (!x) { 01562 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel); 01563 return -1; 01564 } 01565 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel); 01566 dahdi_close_sub(p, x); 01567 p->subs[x].linear = 0; 01568 p->subs[x].chan = 0; 01569 p->subs[x].owner = NULL; 01570 p->subs[x].inthreeway = 0; 01571 p->polarity = POLARITY_IDLE; 01572 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf)); 01573 return 0; 01574 }
static int unload_module | ( | void | ) | [static] |
Definition at line 13836 of file chan_dahdi.c.
References __unload_module(), ast_mutex_destroy(), lock, NUM_SPANS, and pris.
13837 { 13838 #if defined(HAVE_PRI) || defined(HAVE_SS7) 13839 int y; 13840 #endif 13841 #ifdef HAVE_PRI 13842 for (y = 0; y < NUM_SPANS; y++) 13843 ast_mutex_destroy(&pris[y].lock); 13844 #endif 13845 #ifdef HAVE_SS7 13846 for (y = 0; y < NUM_SPANS; y++) 13847 ast_mutex_destroy(&linksets[y].lock); 13848 #endif /* HAVE_SS7 */ 13849 return __unload_module(); 13850 }
static int update_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1949 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().
01950 { 01951 int needconf = 0; 01952 int x; 01953 int useslavenative; 01954 struct dahdi_pvt *slave = NULL; 01955 01956 useslavenative = isslavenative(p, &slave); 01957 /* Start with the obvious, general stuff */ 01958 for (x = 0; x < 3; x++) { 01959 /* Look for three way calls */ 01960 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) { 01961 conf_add(p, &p->subs[x], x, 0); 01962 needconf++; 01963 } else { 01964 conf_del(p, &p->subs[x], x); 01965 } 01966 } 01967 /* If we have a slave, add him to our conference now. or DAX 01968 if this is slave native */ 01969 for (x = 0; x < MAX_SLAVES; x++) { 01970 if (p->slaves[x]) { 01971 if (useslavenative) 01972 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 01973 else { 01974 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 01975 needconf++; 01976 } 01977 } 01978 } 01979 /* If we're supposed to be in there, do so now */ 01980 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 01981 if (useslavenative) 01982 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 01983 else { 01984 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 01985 needconf++; 01986 } 01987 } 01988 /* If we have a master, add ourselves to his conference */ 01989 if (p->master) { 01990 if (isslavenative(p->master, NULL)) { 01991 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 01992 } else { 01993 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 01994 } 01995 } 01996 if (!needconf) { 01997 /* Nobody is left (or should be left) in our conference. 01998 Kill it. */ 01999 p->confno = -1; 02000 } 02001 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf); 02002 return 0; 02003 }
Definition at line 1316 of file chan_dahdi.c.
References ast_channel_trylock, ast_channel_unlock, ast_mutex_unlock(), ast_null_frame, ast_queue_frame(), and DEADLOCK_AVOIDANCE.
Referenced by swap_subs().
01320 { 01321 #ifdef HAVE_PRI 01322 if (pri) 01323 ast_mutex_unlock(&pri->lock); 01324 #endif 01325 for (;;) { 01326 if (p->subs[a].owner) { 01327 if (ast_channel_trylock(p->subs[a].owner)) { 01328 DEADLOCK_AVOIDANCE(&p->lock); 01329 } else { 01330 ast_queue_frame(p->subs[a].owner, &ast_null_frame); 01331 ast_channel_unlock(p->subs[a].owner); 01332 break; 01333 } 01334 } else 01335 break; 01336 } 01337 #ifdef HAVE_PRI 01338 if (pri) 01339 ast_mutex_lock(&pri->lock); 01340 #endif 01341 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 15177 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 15177 of file chan_dahdi.c.
struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static] |
Definition at line 1274 of file chan_dahdi.c.
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 1285 of file chan_dahdi.c.
const char config[] = "chan_dahdi.conf" [static] |
Definition at line 168 of file chan_dahdi.c.
struct ast_cli_entry dahdi_cli[] [static] |
struct ast_cli_entry dahdi_pri_cli[] [static] |
char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static] |
Definition at line 3249 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 3253 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static] |
Definition at line 3251 of file chan_dahdi.c.
struct ast_channel_tech dahdi_tech [static] |
Definition at line 1198 of file chan_dahdi.c.
Referenced by __unload_module(), dahdi_new(), load_module(), and ss_thread().
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 118 of file chan_dahdi.c.
char defaultcic[64] = "" [static] |
Definition at line 226 of file chan_dahdi.c.
char defaultozz[64] = "" [static] |
Definition at line 227 of file chan_dahdi.c.
int distinctiveringaftercid = 0 [static] |
Definition at line 235 of file chan_dahdi.c.
char* events[] [static] |
int firstdigittimeout = 16000 [static] |
Wait up to 16 seconds for first digit (FXO logic).
Definition at line 251 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 254 of file chan_dahdi.c.
Referenced by mgcp_ss(), and skinny_ss().
struct ast_jb_conf global_jbconf [static] |
Definition at line 125 of file chan_dahdi.c.
int ifcount = 0 [static] |
Definition at line 263 of file chan_dahdi.c.
Referenced by __oh323_destroy(), __unload_module(), action_dahdishowchannels(), chandup(), dahdi_destroy_channel_bynum(), dahdi_hangup(), dahdi_request(), dahdi_restart(), dahdi_set_dnd(), dahdi_set_hwgain(), dahdi_set_swgain(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), destroy_channel(), do_monitor(), find_call_locked(), find_channel(), load_module(), mkintf(), oh323_alloc(), phone_request(), and unload_module().
ast_mutex_t iflock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Protect the interface list (of dahdi_pvt's).
Definition at line 260 of file chan_dahdi.c.
Referenced by __unload_module(), action_dahdishowchannels(), dahdi_hangup(), dahdi_request(), dahdi_set_dnd(), dahdi_set_hwgain(), dahdi_set_swgain(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), do_monitor(), find_call_locked(), load_module(), oh323_alloc(), oh323_destroy(), phone_request(), restart_monitor(), setup_dahdi(), and unload_module().
struct ast_channel inuse [static] |
Definition at line 242 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().
const char* lbostr[] [static] |
Definition at line 106 of file chan_dahdi.c.
int matchdigittimeout = 3000 [static] |
How long to wait for an extra digit, if there is an ambiguous match.
Definition at line 257 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 275 of file chan_dahdi.c.
Referenced by reload_config(), restart_monitor(), and unload_module().
ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [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 271 of file chan_dahdi.c.
Referenced by __unload_module(), dahdi_restart(), do_monitor(), restart_monitor(), and unload_module().
int mwilevel = 512 [static] |
Definition at line 239 of file chan_dahdi.c.
char mwimonitornotify[PATH_MAX] = "" [static] |
Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled
Definition at line 230 of file chan_dahdi.c.
char* name |
Definition at line 1715 of file chan_dahdi.c.
int num_cadence = 4 [static] |
Definition at line 1271 of file chan_dahdi.c.
int num_restart_pending = 0 [static] |
Definition at line 280 of file chan_dahdi.c.
int numbufs = 4 [static] |
Definition at line 237 of file chan_dahdi.c.
int pridebugfd = -1 [static] |
Definition at line 246 of file chan_dahdi.c.
ast_mutex_t pridebugfdlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 266 of file chan_dahdi.c.
Referenced by dahdi_pri_error(), dahdi_pri_message(), handle_pri_set_debug_file(), handle_pri_show_debug(), and handle_pri_unset_debug_file().
char pridebugfilename[1024] = "" [static] |
Definition at line 247 of file chan_dahdi.c.
Definition at line 441 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 232 of file chan_dahdi.c.
ast_mutex_t restart_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
int ringt_base = DEFAULT_RINGT [static] |
Configured ring timeout base.
Definition at line 335 of file chan_dahdi.c.
struct dahdi_pvt* round_robin[32] |
ast_cond_t ss_thread_complete [static] |
Definition at line 276 of file chan_dahdi.c.
int ss_thread_count = 0 [static] |
Definition at line 279 of file chan_dahdi.c.
ast_mutex_t ss_thread_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
char* subnames[] [static] |
const char tdesc[] [static] |
int usedistinctiveringdetection = 0 [static] |
Definition at line 234 of file chan_dahdi.c.
int user_has_defined_cadences = 0 [static] |
Definition at line 1272 of file chan_dahdi.c.