#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 | PROC_DAHDI_OPT_NOCHAN (1 << 0) |
#define | PROC_DAHDI_OPT_NOWARN (1 << 1) |
#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 |
Enumerations | |
enum | mwisend_states { MWI_SEND_SA, MWI_SEND_SA_WAIT, MWI_SEND_PAUSE, MWI_SEND_SPILL, MWI_SEND_CLEANUP, MWI_SEND_DONE } |
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 alm) |
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 idx, int slavechannel) |
static int | conf_del (struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx) |
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 idx, 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 idx) |
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 alms) |
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 char * | handle_pri_version (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_send_thread (void *data) |
static void * | mwi_thread (void *data) |
static int | my_dahdi_write (struct dahdi_pvt *p, unsigned char *buf, int len, int idx, 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, const char *cat, struct ast_variable *v, int reload, int options) |
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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } |
struct { | |
int alarm | |
char * name | |
} | alarms [] |
static struct dahdi_ring_cadence | AS_RP_cadence = {{250, 10000}} |
static 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 ast_cond_t | mwi_thread_complete |
static int | mwi_thread_count = 0 |
static ast_mutex_t | mwi_thread_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
static int | mwilevel = 512 |
static char | mwimonitornotify [PATH_MAX] = "" |
static int | mwisend_rpas = 0 |
static int | num_cadence = 4 |
static int | num_restart_pending = 0 |
static int | numbufs = 4 |
static char | parkinglot [AST_MAX_EXTENSION] = "" |
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_send_thread(), mwi_thread(), send_cwcidspill(), and ss_thread().
#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) |
300 ms
Definition at line 329 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 511 of file chan_dahdi.c.
#define CONF_USER_THIRDCALL (1 << 1) |
Definition at line 512 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(), and handle_pri_show_span().
#define DAHDI_OVERLAPDIAL_NONE 0 |
Definition at line 215 of file chan_dahdi.c.
#define DAHDI_OVERLAPDIAL_OUTGOING 1 |
#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 333 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 1239 of file chan_dahdi.c.
#define HANGUP 1 |
Definition at line 13317 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 1311 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 326 of file chan_dahdi.c.
#define MASK_INUSE (1 << 1) |
Channel currently in use
Definition at line 327 of file chan_dahdi.c.
#define MAX_CHANLIST_LEN 80 |
The length of the parameters list of 'dahdichan'.
Definition at line 14176 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 1286 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(), setup_dahdi(), and unload_module().
#define POLARITY_IDLE 0 |
Definition at line 470 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_hangup(), and unalloc_sub().
#define POLARITY_REV 1 |
Definition at line 471 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 PROC_DAHDI_OPT_NOCHAN (1 << 0) |
process_dahdi() - ignore keyword 'channel' and similar
Definition at line 14230 of file chan_dahdi.c.
Referenced by process_dahdi(), and setup_dahdi().
#define PROC_DAHDI_OPT_NOWARN (1 << 1) |
process_dahdi() - No warnings on non-existing cofiguration keywords
Definition at line 14232 of file chan_dahdi.c.
Referenced by setup_dahdi().
#define PVT_TO_CHANNEL | ( | p | ) | (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0)) |
Definition at line 390 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 324 of file chan_dahdi.c.
Referenced by dahdi_callwait(), dahdi_open(), dahdi_read(), dahdi_sendtext(), dahdi_setoption(), my_dahdi_write(), and send_cwcidspill().
#define sig2str dahdi_sig2str |
Definition at line 1840 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), 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(), and mkintf().
#define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS) |
Definition at line 196 of file chan_dahdi.c.
Referenced by dahdi_sig2str(), handle_init_event(), and mkintf().
#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(), 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(), 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(), 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(), 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(), and mkintf().
#define SMDI_MD_WAIT_TIMEOUT 1500 |
#define SUB_CALLWAIT 1 |
Call-Waiting call on hold
Definition at line 466 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(), and ss_thread().
#define SUB_REAL 0 |
Active call
Definition at line 465 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(), find_subchannel_by_name(), get_alarms(), handle_init_event(), HandleCallIncoming(), HandleCallOutgoing(), key_call(), key_dial_page(), mkintf(), mwi_send_thread(), 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 467 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(), HandleCallOutgoing(), ss_thread(), TransferCallStep1(), unistim_answer(), and unistim_hangup().
#define tdesc "DAHDI Telephony w/PRI" |
Definition at line 15467 of file chan_dahdi.c.
#define TRAILER_MS 5 |
Referenced by dahdi_sendtext().
#define TRANSFER 0 |
Definition at line 13316 of file chan_dahdi.c.
Referenced by action_transfer(), and dahdi_fake_event().
enum mwisend_states |
MWI_SEND_SA | |
MWI_SEND_SA_WAIT | |
MWI_SEND_PAUSE | |
MWI_SEND_SPILL | |
MWI_SEND_CLEANUP | |
MWI_SEND_DONE |
Definition at line 7892 of file chan_dahdi.c.
07892 { 07893 MWI_SEND_SA, 07894 MWI_SEND_SA_WAIT, 07895 MWI_SEND_PAUSE, 07896 MWI_SEND_SPILL, 07897 MWI_SEND_CLEANUP, 07898 MWI_SEND_DONE 07899 };
static struct ast_frame* __dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5527 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, ast_frame::ptr, 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().
05528 { 05529 struct dahdi_pvt *p = ast->tech_pvt; 05530 int res; 05531 int usedindex=-1; 05532 int idx; 05533 struct ast_frame *f; 05534 05535 05536 idx = dahdi_get_index(ast, p, 1); 05537 05538 p->subs[idx].f.frametype = AST_FRAME_NULL; 05539 p->subs[idx].f.datalen = 0; 05540 p->subs[idx].f.samples = 0; 05541 p->subs[idx].f.mallocd = 0; 05542 p->subs[idx].f.offset = 0; 05543 p->subs[idx].f.subclass = 0; 05544 p->subs[idx].f.delivery = ast_tv(0,0); 05545 p->subs[idx].f.src = "dahdi_exception"; 05546 p->subs[idx].f.data.ptr = NULL; 05547 05548 05549 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) { 05550 /* If nobody owns us, absorb the event appropriately, otherwise 05551 we loop indefinitely. This occurs when, during call waiting, the 05552 other end hangs up our channel so that it no longer exists, but we 05553 have neither FLASH'd nor ONHOOK'd to signify our desire to 05554 change to the other channel. */ 05555 if (p->fake_event) { 05556 res = p->fake_event; 05557 p->fake_event = 0; 05558 } else 05559 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 05560 /* Switch to real if there is one and this isn't something really silly... */ 05561 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) && 05562 (res != DAHDI_EVENT_HOOKCOMPLETE)) { 05563 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res); 05564 p->owner = p->subs[SUB_REAL].owner; 05565 if (p->owner && ast_bridged_channel(p->owner)) 05566 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05567 p->subs[SUB_REAL].needunhold = 1; 05568 } 05569 switch (res) { 05570 case DAHDI_EVENT_ONHOOK: 05571 dahdi_disable_ec(p); 05572 if (p->owner) { 05573 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name); 05574 dahdi_ring_phone(p); 05575 p->callwaitingrepeat = 0; 05576 p->cidcwexpire = 0; 05577 } else 05578 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 05579 update_conf(p); 05580 break; 05581 case DAHDI_EVENT_RINGOFFHOOK: 05582 dahdi_enable_ec(p); 05583 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 05584 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) { 05585 p->subs[SUB_REAL].needanswer = 1; 05586 p->dialing = 0; 05587 } 05588 break; 05589 case DAHDI_EVENT_HOOKCOMPLETE: 05590 case DAHDI_EVENT_RINGERON: 05591 case DAHDI_EVENT_RINGEROFF: 05592 /* Do nothing */ 05593 break; 05594 case DAHDI_EVENT_WINKFLASH: 05595 p->flashtime = ast_tvnow(); 05596 if (p->owner) { 05597 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name); 05598 if (p->owner->_state != AST_STATE_UP) { 05599 /* Answer if necessary */ 05600 usedindex = dahdi_get_index(p->owner, p, 0); 05601 if (usedindex > -1) { 05602 p->subs[usedindex].needanswer = 1; 05603 } 05604 ast_setstate(p->owner, AST_STATE_UP); 05605 } 05606 p->callwaitingrepeat = 0; 05607 p->cidcwexpire = 0; 05608 if (ast_bridged_channel(p->owner)) 05609 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05610 p->subs[SUB_REAL].needunhold = 1; 05611 } else 05612 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 05613 update_conf(p); 05614 break; 05615 default: 05616 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res)); 05617 } 05618 f = &p->subs[idx].f; 05619 return f; 05620 } 05621 if (!(p->radio || (p->oprmode < 0))) 05622 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel); 05623 /* If it's not us, return NULL immediately */ 05624 if (ast != p->owner) { 05625 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name); 05626 f = &p->subs[idx].f; 05627 return f; 05628 } 05629 f = dahdi_handle_event(ast); 05630 return f; 05631 }
static void __reg_module | ( | void | ) | [static] |
Definition at line 15481 of file chan_dahdi.c.
static int __unload_module | ( | void | ) | [static] |
Definition at line 13993 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().
13994 { 13995 struct dahdi_pvt *p; 13996 #if defined(HAVE_PRI) || defined(HAVE_SS7) 13997 int i, j; 13998 #endif 13999 14000 #ifdef HAVE_PRI 14001 for (i = 0; i < NUM_SPANS; i++) { 14002 if (pris[i].master != AST_PTHREADT_NULL) 14003 pthread_cancel(pris[i].master); 14004 } 14005 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 14006 ast_unregister_application(dahdi_send_keypad_facility_app); 14007 #endif 14008 #if defined(HAVE_SS7) 14009 for (i = 0; i < NUM_SPANS; i++) { 14010 if (linksets[i].master != AST_PTHREADT_NULL) 14011 pthread_cancel(linksets[i].master); 14012 } 14013 ast_cli_unregister_multiple(dahdi_ss7_cli, sizeof(dahdi_ss7_cli) / sizeof(struct ast_cli_entry)); 14014 #endif 14015 14016 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 14017 ast_manager_unregister( "DAHDIDialOffhook" ); 14018 ast_manager_unregister( "DAHDIHangup" ); 14019 ast_manager_unregister( "DAHDITransfer" ); 14020 ast_manager_unregister( "DAHDIDNDoff" ); 14021 ast_manager_unregister( "DAHDIDNDon" ); 14022 ast_manager_unregister("DAHDIShowChannels"); 14023 ast_manager_unregister("DAHDIRestart"); 14024 ast_channel_unregister(&dahdi_tech); 14025 ast_mutex_lock(&iflock); 14026 /* Hangup all interfaces if they have an owner */ 14027 p = iflist; 14028 while (p) { 14029 if (p->owner) 14030 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 14031 p = p->next; 14032 } 14033 ast_mutex_unlock(&iflock); 14034 ast_mutex_lock(&monlock); 14035 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 14036 pthread_cancel(monitor_thread); 14037 pthread_kill(monitor_thread, SIGURG); 14038 pthread_join(monitor_thread, NULL); 14039 } 14040 monitor_thread = AST_PTHREADT_STOP; 14041 ast_mutex_unlock(&monlock); 14042 14043 destroy_all_channels(); 14044 14045 #if defined(HAVE_PRI) 14046 for (i = 0; i < NUM_SPANS; i++) { 14047 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) 14048 pthread_join(pris[i].master, NULL); 14049 for (j = 0; j < NUM_DCHANS; j++) { 14050 dahdi_close_pri_fd(&(pris[i]), j); 14051 } 14052 } 14053 #endif 14054 14055 #if defined(HAVE_SS7) 14056 for (i = 0; i < NUM_SPANS; i++) { 14057 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) 14058 pthread_join(linksets[i].master, NULL); 14059 for (j = 0; j < NUM_DCHANS; j++) { 14060 dahdi_close_ss7_fd(&(linksets[i]), j); 14061 } 14062 } 14063 #endif 14064 14065 ast_cond_destroy(&mwi_thread_complete); 14066 ast_cond_destroy(&ss_thread_complete); 14067 return 0; 14068 }
static void __unreg_module | ( | void | ) | [static] |
Definition at line 15481 of file chan_dahdi.c.
static int action_dahdidialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13423 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().
13424 { 13425 struct dahdi_pvt *p = NULL; 13426 const char *channel = astman_get_header(m, "DAHDIChannel"); 13427 const char *number = astman_get_header(m, "Number"); 13428 int i; 13429 13430 if (ast_strlen_zero(channel)) { 13431 astman_send_error(s, m, "No channel specified"); 13432 return 0; 13433 } 13434 if (ast_strlen_zero(number)) { 13435 astman_send_error(s, m, "No number specified"); 13436 return 0; 13437 } 13438 p = find_channel(atoi(channel)); 13439 if (!p) { 13440 astman_send_error(s, m, "No such channel"); 13441 return 0; 13442 } 13443 if (!p->owner) { 13444 astman_send_error(s, m, "Channel does not have it's owner"); 13445 return 0; 13446 } 13447 for (i = 0; i < strlen(number); i++) { 13448 struct ast_frame f = { AST_FRAME_DTMF, number[i] }; 13449 dahdi_queue_frame(p, &f, NULL); 13450 } 13451 astman_send_ack(s, m, "DAHDIDialOffhook"); 13452 return 0; 13453 }
static int action_dahdidndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13366 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().
13367 { 13368 struct dahdi_pvt *p = NULL; 13369 const char *channel = astman_get_header(m, "DAHDIChannel"); 13370 13371 if (ast_strlen_zero(channel)) { 13372 astman_send_error(s, m, "No channel specified"); 13373 return 0; 13374 } 13375 p = find_channel(atoi(channel)); 13376 if (!p) { 13377 astman_send_error(s, m, "No such channel"); 13378 return 0; 13379 } 13380 p->dnd = 0; 13381 astman_send_ack(s, m, "DND Disabled"); 13382 return 0; 13383 }
static int action_dahdidndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13347 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().
13348 { 13349 struct dahdi_pvt *p = NULL; 13350 const char *channel = astman_get_header(m, "DAHDIChannel"); 13351 13352 if (ast_strlen_zero(channel)) { 13353 astman_send_error(s, m, "No channel specified"); 13354 return 0; 13355 } 13356 p = find_channel(atoi(channel)); 13357 if (!p) { 13358 astman_send_error(s, m, "No such channel"); 13359 return 0; 13360 } 13361 p->dnd = 1; 13362 astman_send_ack(s, m, "DND Enabled"); 13363 return 0; 13364 }
static int action_dahdirestart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12621 of file chan_dahdi.c.
References astman_send_ack(), astman_send_error(), dahdi_restart(), and s.
Referenced by load_module().
12622 { 12623 if (dahdi_restart() != 0) { 12624 astman_send_error(s, m, "Failed rereading DAHDI configuration"); 12625 return 1; 12626 } 12627 astman_send_ack(s, m, "DAHDIRestart: Success"); 12628 return 0; 12629 }
static int action_dahdishowchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13455 of file chan_dahdi.c.
References ast_channel::accountcode, 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().
13456 { 13457 struct dahdi_pvt *tmp = NULL; 13458 const char *id = astman_get_header(m, "ActionID"); 13459 const char *dahdichannel = astman_get_header(m, "DAHDIChannel"); 13460 char idText[256] = ""; 13461 int channels = 0; 13462 int dahdichanquery = -1; 13463 if (!ast_strlen_zero(dahdichannel)) { 13464 dahdichanquery = atoi(dahdichannel); 13465 } 13466 13467 astman_send_ack(s, m, "DAHDI channel status will follow"); 13468 if (!ast_strlen_zero(id)) 13469 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 13470 13471 ast_mutex_lock(&iflock); 13472 13473 tmp = iflist; 13474 while (tmp) { 13475 if (tmp->channel > 0) { 13476 int alm = get_alarms(tmp); 13477 13478 /* If a specific channel is queried for, only deliver status for that channel */ 13479 if (dahdichanquery > 0 && tmp->channel != dahdichanquery) 13480 continue; 13481 13482 channels++; 13483 if (tmp->owner) { 13484 /* Add data if we have a current call */ 13485 astman_append(s, 13486 "Event: DAHDIShowChannels\r\n" 13487 "DAHDIChannel: %d\r\n" 13488 "Channel: %s\r\n" 13489 "Uniqueid: %s\r\n" 13490 "AccountCode: %s\r\n" 13491 "Signalling: %s\r\n" 13492 "SignallingCode: %d\r\n" 13493 "Context: %s\r\n" 13494 "DND: %s\r\n" 13495 "Alarm: %s\r\n" 13496 "%s" 13497 "\r\n", 13498 tmp->channel, 13499 tmp->owner->name, 13500 tmp->owner->uniqueid, 13501 tmp->owner->accountcode, 13502 sig2str(tmp->sig), 13503 tmp->sig, 13504 tmp->context, 13505 tmp->dnd ? "Enabled" : "Disabled", 13506 alarm2str(alm), idText); 13507 } else { 13508 astman_append(s, 13509 "Event: DAHDIShowChannels\r\n" 13510 "DAHDIChannel: %d\r\n" 13511 "Signalling: %s\r\n" 13512 "SignallingCode: %d\r\n" 13513 "Context: %s\r\n" 13514 "DND: %s\r\n" 13515 "Alarm: %s\r\n" 13516 "%s" 13517 "\r\n", 13518 tmp->channel, sig2str(tmp->sig), tmp->sig, 13519 tmp->context, 13520 tmp->dnd ? "Enabled" : "Disabled", 13521 alarm2str(alm), idText); 13522 } 13523 } 13524 13525 tmp = tmp->next; 13526 } 13527 13528 ast_mutex_unlock(&iflock); 13529 13530 astman_append(s, 13531 "Event: DAHDIShowChannelsComplete\r\n" 13532 "%s" 13533 "Items: %d\r\n" 13534 "\r\n", 13535 idText, 13536 channels); 13537 return 0; 13538 }
static int action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13385 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().
13386 { 13387 struct dahdi_pvt *p = NULL; 13388 const char *channel = astman_get_header(m, "DAHDIChannel"); 13389 13390 if (ast_strlen_zero(channel)) { 13391 astman_send_error(s, m, "No channel specified"); 13392 return 0; 13393 } 13394 p = find_channel(atoi(channel)); 13395 if (!p) { 13396 astman_send_error(s, m, "No such channel"); 13397 return 0; 13398 } 13399 dahdi_fake_event(p,TRANSFER); 13400 astman_send_ack(s, m, "DAHDITransfer"); 13401 return 0; 13402 }
static int action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13404 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().
13405 { 13406 struct dahdi_pvt *p = NULL; 13407 const char *channel = astman_get_header(m, "DAHDIChannel"); 13408 13409 if (ast_strlen_zero(channel)) { 13410 astman_send_error(s, m, "No channel specified"); 13411 return 0; 13412 } 13413 p = find_channel(atoi(channel)); 13414 if (!p) { 13415 astman_send_error(s, m, "No such channel"); 13416 return 0; 13417 } 13418 dahdi_fake_event(p,HANGUP); 13419 astman_send_ack(s, m, "DAHDIHangup"); 13420 return 0; 13421 }
static char* alarm2str | ( | int | alm | ) | [static] |
Definition at line 1745 of file chan_dahdi.c.
References alarm, alarms, and ARRAY_LEN.
Referenced by action_dahdishowchannels(), and handle_alarms().
01746 { 01747 int x; 01748 for (x = 0; x < ARRAY_LEN(alarms); x++) { 01749 if (alarms[x].alarm & alm) 01750 return alarms[x].name; 01751 } 01752 return alm ? "Unknown Alarm" : "No Alarm"; 01753 }
static int alloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 1541 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().
01542 { 01543 struct dahdi_bufferinfo bi; 01544 int res; 01545 if (p->subs[x].dfd >= 0) { 01546 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel); 01547 return -1; 01548 } 01549 01550 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo"); 01551 if (p->subs[x].dfd <= -1) { 01552 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 01553 return -1; 01554 } 01555 01556 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi); 01557 if (!res) { 01558 bi.txbufpolicy = p->buf_policy; 01559 bi.rxbufpolicy = p->buf_policy; 01560 bi.numbufs = p->buf_no; 01561 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi); 01562 if (res < 0) { 01563 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno)); 01564 } 01565 } else 01566 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno)); 01567 01568 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) { 01569 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno)); 01570 dahdi_close_sub(p, x); 01571 p->subs[x].dfd = -1; 01572 return -1; 01573 } 01574 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan); 01575 return 0; 01576 }
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 10823 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.
10824 { 10825 if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */ 10826 snprintf(buf, size, "%s", number); 10827 return; 10828 } 10829 if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */ 10830 if (size) { 10831 *buf = '\0'; 10832 } 10833 return; 10834 } 10835 switch (plan) { 10836 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */ 10837 snprintf(buf, size, "%s%s", pri->internationalprefix, number); 10838 break; 10839 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */ 10840 snprintf(buf, size, "%s%s", pri->nationalprefix, number); 10841 break; 10842 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */ 10843 snprintf(buf, size, "%s%s", pri->localprefix, number); 10844 break; 10845 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */ 10846 snprintf(buf, size, "%s%s", pri->privateprefix, number); 10847 break; 10848 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */ 10849 snprintf(buf, size, "%s%s", pri->unknownprefix, number); 10850 break; 10851 default: /* other Q.931 dialplan => don't twiddle with callingnum */ 10852 snprintf(buf, size, "%s", number); 10853 break; 10854 } 10855 }
static int attempt_transfer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4509 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_request(), and local_attended_transfer().
04510 { 04511 /* In order to transfer, we need at least one of the channels to 04512 actually be in a call bridge. We can't conference two applications 04513 together (but then, why would we want to?) */ 04514 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 04515 /* The three-way person we're about to transfer to could still be in MOH, so 04516 stop if now if appropriate */ 04517 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) 04518 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD); 04519 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) { 04520 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING); 04521 } 04522 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) { 04523 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 04524 } 04525 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { 04526 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 04527 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name); 04528 return -1; 04529 } 04530 /* Orphan the channel after releasing the lock */ 04531 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04532 unalloc_sub(p, SUB_THREEWAY); 04533 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 04534 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 04535 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) { 04536 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING); 04537 } 04538 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) { 04539 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04540 } 04541 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { 04542 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 04543 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); 04544 return -1; 04545 } 04546 /* Three-way is now the REAL */ 04547 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04548 ast_channel_unlock(p->subs[SUB_REAL].owner); 04549 unalloc_sub(p, SUB_THREEWAY); 04550 /* Tell the caller not to hangup */ 04551 return 1; 04552 } else { 04553 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n", 04554 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name); 04555 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04556 return -1; 04557 } 04558 return 0; 04559 }
static int available | ( | struct dahdi_pvt * | p, | |
int | channelmatch, | |||
ast_group_t | groupmatch, | |||
int * | busy, | |||
int * | channelmatched, | |||
int * | groupmatched | |||
) | [inline, static] |
Definition at line 9259 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().
09260 { 09261 int res; 09262 struct dahdi_params par; 09263 09264 /* First, check group matching */ 09265 if (groupmatch) { 09266 if ((p->group & groupmatch) != groupmatch) 09267 return 0; 09268 *groupmatched = 1; 09269 } 09270 /* Check to see if we have a channel match */ 09271 if (channelmatch != -1) { 09272 if (p->channel != channelmatch) 09273 return 0; 09274 *channelmatched = 1; 09275 } 09276 /* We're at least busy at this point */ 09277 if (busy) { 09278 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS)) 09279 *busy = 1; 09280 } 09281 /* If do not disturb, definitely not */ 09282 if (p->dnd) 09283 return 0; 09284 /* If guard time, definitely not */ 09285 if (p->guardtime && (time(NULL) < p->guardtime)) 09286 return 0; 09287 09288 if (p->locallyblocked || p->remotelyblocked) 09289 return 0; 09290 09291 /* If no owner definitely available */ 09292 if (!p->owner) { 09293 #ifdef HAVE_PRI 09294 /* Trust PRI */ 09295 if (p->pri) { 09296 if (p->resetting || p->call) 09297 return 0; 09298 else 09299 return 1; 09300 } 09301 #endif 09302 #ifdef HAVE_SS7 09303 /* Trust SS7 */ 09304 if (p->ss7) { 09305 if (p->ss7call) 09306 return 0; 09307 else 09308 return 1; 09309 } 09310 #endif 09311 if (!(p->radio || (p->oprmode < 0))) 09312 { 09313 if (!p->sig || (p->sig == SIG_FXSLS)) 09314 return 1; 09315 /* Check hook state */ 09316 if (p->subs[SUB_REAL].dfd > -1) { 09317 memset(&par, 0, sizeof(par)); 09318 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 09319 } else { 09320 /* Assume not off hook on CVRS */ 09321 res = 0; 09322 par.rxisoffhook = 0; 09323 } 09324 if (res) { 09325 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno)); 09326 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) { 09327 /* When "onhook" that means no battery on the line, and thus 09328 it is out of service..., if it's on a TDM card... If it's a channel 09329 bank, there is no telling... */ 09330 if (par.rxbits > -1) 09331 return 1; 09332 if (par.rxisoffhook) 09333 return 1; 09334 else 09335 return 0; 09336 } else if (par.rxisoffhook) { 09337 ast_debug(1, "Channel %d off hook, can't use\n", p->channel); 09338 /* Not available when the other end is off hook */ 09339 #ifdef DAHDI_CHECK_HOOKSTATE 09340 return 0; 09341 #else 09342 return 1; 09343 #endif 09344 } 09345 } 09346 return 1; 09347 } 09348 09349 /* If it's not an FXO, forget about call wait */ 09350 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 09351 return 0; 09352 09353 if (!p->callwaiting) { 09354 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */ 09355 return 0; 09356 } 09357 09358 if (p->subs[SUB_CALLWAIT].dfd > -1) { 09359 /* If there is already a call waiting call, then we can't take a second one */ 09360 return 0; 09361 } 09362 09363 if ((p->owner->_state != AST_STATE_UP) && 09364 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) { 09365 /* If the current call is not up, then don't allow the call */ 09366 return 0; 09367 } 09368 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) { 09369 /* Can't take a call wait when the three way calling hasn't been merged yet. */ 09370 return 0; 09371 } 09372 /* We're cool */ 09373 return 1; 09374 }
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 14086 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().
14087 { 14088 char *c, *chan; 14089 int x, start, finish; 14090 struct dahdi_pvt *tmp; 14091 #ifdef HAVE_PRI 14092 struct dahdi_pri *pri; 14093 int trunkgroup, y; 14094 #endif 14095 14096 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) { 14097 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); 14098 return -1; 14099 } 14100 14101 c = ast_strdupa(value); 14102 14103 #ifdef HAVE_PRI 14104 pri = NULL; 14105 if (iscrv) { 14106 if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) { 14107 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno); 14108 return -1; 14109 } 14110 if (trunkgroup < 1) { 14111 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno); 14112 return -1; 14113 } 14114 c += y; 14115 for (y = 0; y < NUM_SPANS; y++) { 14116 if (pris[y].trunkgroup == trunkgroup) { 14117 pri = pris + y; 14118 break; 14119 } 14120 } 14121 if (!pri) { 14122 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno); 14123 return -1; 14124 } 14125 } 14126 #endif 14127 14128 while ((chan = strsep(&c, ","))) { 14129 if (sscanf(chan, "%d-%d", &start, &finish) == 2) { 14130 /* Range */ 14131 } else if (sscanf(chan, "%d", &start)) { 14132 /* Just one */ 14133 finish = start; 14134 } else if (!strcasecmp(chan, "pseudo")) { 14135 finish = start = CHAN_PSEUDO; 14136 if (found_pseudo) 14137 *found_pseudo = 1; 14138 } else { 14139 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan); 14140 return -1; 14141 } 14142 if (finish < start) { 14143 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); 14144 x = finish; 14145 finish = start; 14146 start = x; 14147 } 14148 14149 for (x = start; x <= finish; x++) { 14150 #ifdef HAVE_PRI 14151 tmp = mkintf(x, conf, pri, reload); 14152 #else 14153 tmp = mkintf(x, conf, NULL, reload); 14154 #endif 14155 14156 if (tmp) { 14157 #ifdef HAVE_PRI 14158 if (pri) 14159 ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig)); 14160 else 14161 #endif 14162 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig)); 14163 } else { 14164 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n", 14165 (reload == 1) ? "reconfigure" : "register", value); 14166 return -1; 14167 } 14168 } 14169 } 14170 14171 return 0; 14172 }
static void build_status | ( | char * | s, | |
size_t | len, | |||
int | status, | |||
int | active | |||
) | [static] |
Definition at line 12252 of file chan_dahdi.c.
References DCHAN_NOTINALARM, and DCHAN_PROVISIONED.
Referenced by handle_pri_show_span(), and handle_pri_show_spans().
12253 { 12254 if (!s || len < 1) { 12255 return; 12256 } 12257 s[0] = '\0'; 12258 if (status & DCHAN_PROVISIONED) 12259 strncat(s, "Provisioned, ", len - strlen(s) - 1); 12260 if (!(status & DCHAN_NOTINALARM)) 12261 strncat(s, "In Alarm, ", len - strlen(s) - 1); 12262 if (status & DCHAN_UP) 12263 strncat(s, "Up", len - strlen(s) - 1); 12264 else 12265 strncat(s, "Down", len - strlen(s) - 1); 12266 if (active) 12267 strncat(s, ", Active", len - strlen(s) - 1); 12268 else 12269 strncat(s, ", Standby", len - strlen(s) - 1); 12270 s[len - 1] = '\0'; 12271 }
static int bump_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2200 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().
02201 { 02202 int res; 02203 02204 /* Bump receive gain by value stored in cid_rxgain */ 02205 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law); 02206 if (res) { 02207 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno)); 02208 return -1; 02209 } 02210 02211 return 0; 02212 }
static int calc_energy | ( | const unsigned char * | buf, | |
int | len, | |||
int | law | |||
) | [static] |
Definition at line 7744 of file chan_dahdi.c.
References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.
Referenced by mwi_thread().
07745 { 07746 int x; 07747 int sum = 0; 07748 07749 if (!len) 07750 return 0; 07751 07752 for (x = 0; x < len; x++) 07753 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x])); 07754 07755 return sum / len; 07756 }
Definition at line 9376 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().
09377 { 09378 struct dahdi_pvt *p; 09379 struct dahdi_bufferinfo bi; 09380 int res; 09381 09382 if ((p = ast_malloc(sizeof(*p)))) { 09383 memcpy(p, src, sizeof(struct dahdi_pvt)); 09384 ast_mutex_init(&p->lock); 09385 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo"); 09386 /* Allocate a dahdi structure */ 09387 if (p->subs[SUB_REAL].dfd < 0) { 09388 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno)); 09389 destroy_dahdi_pvt(&p); 09390 return NULL; 09391 } 09392 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 09393 if (!res) { 09394 bi.txbufpolicy = src->buf_policy; 09395 bi.rxbufpolicy = src->buf_policy; 09396 bi.numbufs = src->buf_no; 09397 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 09398 if (res < 0) { 09399 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno)); 09400 } 09401 } else 09402 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno)); 09403 } 09404 p->destroy = 1; 09405 p->next = iflist; 09406 p->prev = NULL; 09407 iflist = p; 09408 if (iflist->next) 09409 iflist->next->prev = p; 09410 return p; 09411 }
static int check_for_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4561 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().
04562 { 04563 struct dahdi_confinfo ci; 04564 /* Fine if we already have a master, etc */ 04565 if (p->master || (p->confno > -1)) 04566 return 0; 04567 memset(&ci, 0, sizeof(ci)); 04568 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 04569 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno)); 04570 return 0; 04571 } 04572 /* If we have no master and don't have a confno, then 04573 if we're in a conference, it's probably a MeetMe room or 04574 some such, so don't let us 3-way out! */ 04575 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) { 04576 ast_verb(3, "Avoiding 3-way call when in an external conference\n"); 04577 return 1; 04578 } 04579 return 0; 04580 }
static char* complete_span_4 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 12077 of file chan_dahdi.c.
References complete_span_helper().
Referenced by handle_pri_debug(), and handle_pri_show_span().
12078 { 12079 return complete_span_helper(line,word,pos,state,3); 12080 }
static char* complete_span_5 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 12082 of file chan_dahdi.c.
References complete_span_helper().
Referenced by handle_pri_no_debug(), and handle_pri_really_debug().
12083 { 12084 return complete_span_helper(line,word,pos,state,4); 12085 }
static char* complete_span_helper | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state, | |||
int | rpos | |||
) | [static] |
Definition at line 12058 of file chan_dahdi.c.
References asprintf, ast_log(), errno, NUM_SPANS, and pris.
Referenced by complete_span_4(), and complete_span_5().
12059 { 12060 int which, span; 12061 char *ret = NULL; 12062 12063 if (pos != rpos) 12064 return ret; 12065 12066 for (which = span = 0; span < NUM_SPANS; span++) { 12067 if (pris[span].pri && ++which > state) { 12068 if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */ 12069 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 12070 } 12071 break; 12072 } 12073 } 12074 return ret; 12075 }
static int conf_add | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | idx, | |||
int | slavechannel | |||
) | [static] |
Definition at line 1842 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().
01843 { 01844 /* If the conference already exists, and we're already in it 01845 don't bother doing anything */ 01846 struct dahdi_confinfo zi; 01847 01848 memset(&zi, 0, sizeof(zi)); 01849 zi.chan = 0; 01850 01851 if (slavechannel > 0) { 01852 /* If we have only one slave, do a digital mon */ 01853 zi.confmode = DAHDI_CONF_DIGITALMON; 01854 zi.confno = slavechannel; 01855 } else { 01856 if (!idx) { 01857 /* Real-side and pseudo-side both participate in conference */ 01858 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER | 01859 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 01860 } else 01861 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 01862 zi.confno = p->confno; 01863 } 01864 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode)) 01865 return 0; 01866 if (c->dfd < 0) 01867 return 0; 01868 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 01869 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno)); 01870 return -1; 01871 } 01872 if (slavechannel < 1) { 01873 p->confno = zi.confno; 01874 } 01875 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 01876 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 01877 return 0; 01878 }
static int conf_del | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | idx | |||
) | [static] |
Definition at line 1891 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().
01892 { 01893 struct dahdi_confinfo zi; 01894 if (/* Can't delete if there's no dfd */ 01895 (c->dfd < 0) || 01896 /* Don't delete from the conference if it's not our conference */ 01897 !isourconf(p, c) 01898 /* Don't delete if we don't think it's conferenced at all (implied) */ 01899 ) return 0; 01900 memset(&zi, 0, sizeof(zi)); 01901 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 01902 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno)); 01903 return -1; 01904 } 01905 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 01906 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 01907 return 0; 01908 }
static int dahdi_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3749 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.
03750 { 03751 struct dahdi_pvt *p = ast->tech_pvt; 03752 int res = 0; 03753 int idx; 03754 int oldstate = ast->_state; 03755 ast_setstate(ast, AST_STATE_UP); 03756 ast_mutex_lock(&p->lock); 03757 idx = dahdi_get_index(ast, p, 0); 03758 if (idx < 0) 03759 idx = SUB_REAL; 03760 /* nothing to do if a radio channel */ 03761 if ((p->radio || (p->oprmode < 0))) { 03762 ast_mutex_unlock(&p->lock); 03763 return 0; 03764 } 03765 switch (p->sig) { 03766 case SIG_FXSLS: 03767 case SIG_FXSGS: 03768 case SIG_FXSKS: 03769 p->ringt = 0; 03770 /* Fall through */ 03771 case SIG_EM: 03772 case SIG_EM_E1: 03773 case SIG_EMWINK: 03774 case SIG_FEATD: 03775 case SIG_FEATDMF: 03776 case SIG_FEATDMF_TA: 03777 case SIG_E911: 03778 case SIG_FGC_CAMA: 03779 case SIG_FGC_CAMAMF: 03780 case SIG_FEATB: 03781 case SIG_SF: 03782 case SIG_SFWINK: 03783 case SIG_SF_FEATD: 03784 case SIG_SF_FEATDMF: 03785 case SIG_SF_FEATB: 03786 case SIG_FXOLS: 03787 case SIG_FXOGS: 03788 case SIG_FXOKS: 03789 /* Pick up the line */ 03790 ast_debug(1, "Took %s off hook\n", ast->name); 03791 if (p->hanguponpolarityswitch) { 03792 p->polaritydelaytv = ast_tvnow(); 03793 } 03794 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 03795 tone_zone_play_tone(p->subs[idx].dfd, -1); 03796 p->dialing = 0; 03797 if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) { 03798 if (oldstate == AST_STATE_RINGING) { 03799 ast_debug(1, "Finally swapping real and threeway\n"); 03800 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1); 03801 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03802 p->owner = p->subs[SUB_REAL].owner; 03803 } 03804 } 03805 if (p->sig & __DAHDI_SIG_FXS) { 03806 dahdi_enable_ec(p); 03807 dahdi_train_ec(p); 03808 } 03809 break; 03810 #ifdef HAVE_PRI 03811 case SIG_BRI: 03812 case SIG_BRI_PTMP: 03813 case SIG_PRI: 03814 /* Send a pri acknowledge */ 03815 if (!pri_grab(p, p->pri)) { 03816 p->proceeding = 1; 03817 p->dialing = 0; 03818 res = pri_answer(p->pri->pri, p->call, 0, !p->digital); 03819 pri_rel(p->pri); 03820 } else { 03821 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 03822 res = -1; 03823 } 03824 break; 03825 #endif 03826 #ifdef HAVE_SS7 03827 case SIG_SS7: 03828 if (!ss7_grab(p, p->ss7)) { 03829 p->proceeding = 1; 03830 res = isup_anm(p->ss7->ss7, p->ss7call); 03831 ss7_rel(p->ss7); 03832 } else { 03833 ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span); 03834 res = -1; 03835 } 03836 break; 03837 #endif 03838 case 0: 03839 ast_mutex_unlock(&p->lock); 03840 return 0; 03841 default: 03842 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel); 03843 res = -1; 03844 } 03845 ast_mutex_unlock(&p->lock); 03846 return res; 03847 }
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 4161 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, CHANNEL_DEADLOCK_AVOIDANCE, 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().
04162 { 04163 struct ast_channel *who; 04164 struct dahdi_pvt *p0, *p1, *op0, *op1; 04165 struct dahdi_pvt *master = NULL, *slave = NULL; 04166 struct ast_frame *f; 04167 int inconf = 0; 04168 int nothingok = 1; 04169 int ofd0, ofd1; 04170 int oi0, oi1, i0 = -1, i1 = -1, t0, t1; 04171 int os0 = -1, os1 = -1; 04172 int priority = 0; 04173 struct ast_channel *oc0, *oc1; 04174 enum ast_bridge_result res; 04175 04176 #ifdef PRI_2BCT 04177 int triedtopribridge = 0; 04178 q931_call *q931c0 = NULL, *q931c1 = NULL; 04179 #endif 04180 04181 /* For now, don't attempt to native bridge if either channel needs DTMF detection. 04182 There is code below to handle it properly until DTMF is actually seen, 04183 but due to currently unresolved issues it's ignored... 04184 */ 04185 04186 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 04187 return AST_BRIDGE_FAILED_NOWARN; 04188 04189 ast_channel_lock(c0); 04190 while (ast_channel_trylock(c1)) { 04191 CHANNEL_DEADLOCK_AVOIDANCE(c0); 04192 } 04193 04194 p0 = c0->tech_pvt; 04195 p1 = c1->tech_pvt; 04196 /* cant do pseudo-channels here */ 04197 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) { 04198 ast_channel_unlock(c0); 04199 ast_channel_unlock(c1); 04200 return AST_BRIDGE_FAILED_NOWARN; 04201 } 04202 04203 oi0 = dahdi_get_index(c0, p0, 0); 04204 oi1 = dahdi_get_index(c1, p1, 0); 04205 if ((oi0 < 0) || (oi1 < 0)) { 04206 ast_channel_unlock(c0); 04207 ast_channel_unlock(c1); 04208 return AST_BRIDGE_FAILED; 04209 } 04210 04211 op0 = p0 = c0->tech_pvt; 04212 op1 = p1 = c1->tech_pvt; 04213 ofd0 = c0->fds[0]; 04214 ofd1 = c1->fds[0]; 04215 oc0 = p0->owner; 04216 oc1 = p1->owner; 04217 04218 if (ast_mutex_trylock(&p0->lock)) { 04219 /* Don't block, due to potential for deadlock */ 04220 ast_channel_unlock(c0); 04221 ast_channel_unlock(c1); 04222 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 04223 return AST_BRIDGE_RETRY; 04224 } 04225 if (ast_mutex_trylock(&p1->lock)) { 04226 /* Don't block, due to potential for deadlock */ 04227 ast_mutex_unlock(&p0->lock); 04228 ast_channel_unlock(c0); 04229 ast_channel_unlock(c1); 04230 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 04231 return AST_BRIDGE_RETRY; 04232 } 04233 04234 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 04235 if (p0->owner && p1->owner) { 04236 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */ 04237 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) { 04238 master = p0; 04239 slave = p1; 04240 inconf = 1; 04241 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) { 04242 master = p1; 04243 slave = p0; 04244 inconf = 1; 04245 } else { 04246 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n"); 04247 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n", 04248 p0->channel, 04249 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 04250 p0->subs[SUB_REAL].inthreeway, p0->channel, 04251 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 04252 p1->subs[SUB_REAL].inthreeway); 04253 } 04254 nothingok = 0; 04255 } 04256 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) { 04257 if (p1->subs[SUB_THREEWAY].inthreeway) { 04258 master = p1; 04259 slave = p0; 04260 nothingok = 0; 04261 } 04262 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) { 04263 if (p0->subs[SUB_THREEWAY].inthreeway) { 04264 master = p0; 04265 slave = p1; 04266 nothingok = 0; 04267 } 04268 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) { 04269 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise, 04270 don't put us in anything */ 04271 if (p1->subs[SUB_CALLWAIT].inthreeway) { 04272 master = p1; 04273 slave = p0; 04274 nothingok = 0; 04275 } 04276 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) { 04277 /* Same as previous */ 04278 if (p0->subs[SUB_CALLWAIT].inthreeway) { 04279 master = p0; 04280 slave = p1; 04281 nothingok = 0; 04282 } 04283 } 04284 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n", 04285 master ? master->channel : 0, slave ? slave->channel : 0, nothingok); 04286 if (master && slave) { 04287 /* Stop any tones, or play ringtone as appropriate. If they're bridged 04288 in an active threeway call with a channel that is ringing, we should 04289 indicate ringing. */ 04290 if ((oi1 == SUB_THREEWAY) && 04291 p1->subs[SUB_THREEWAY].inthreeway && 04292 p1->subs[SUB_REAL].owner && 04293 p1->subs[SUB_REAL].inthreeway && 04294 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 04295 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name); 04296 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE); 04297 os1 = p1->subs[SUB_REAL].owner->_state; 04298 } else { 04299 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1); 04300 tone_zone_play_tone(p0->subs[oi0].dfd, -1); 04301 } 04302 if ((oi0 == SUB_THREEWAY) && 04303 p0->subs[SUB_THREEWAY].inthreeway && 04304 p0->subs[SUB_REAL].owner && 04305 p0->subs[SUB_REAL].inthreeway && 04306 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 04307 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name); 04308 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE); 04309 os0 = p0->subs[SUB_REAL].owner->_state; 04310 } else { 04311 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0); 04312 tone_zone_play_tone(p1->subs[oi0].dfd, -1); 04313 } 04314 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 04315 if (!p0->echocanbridged || !p1->echocanbridged) { 04316 /* Disable echo cancellation if appropriate */ 04317 dahdi_disable_ec(p0); 04318 dahdi_disable_ec(p1); 04319 } 04320 } 04321 dahdi_link(slave, master); 04322 master->inconference = inconf; 04323 } else if (!nothingok) 04324 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]); 04325 04326 update_conf(p0); 04327 update_conf(p1); 04328 t0 = p0->subs[SUB_REAL].inthreeway; 04329 t1 = p1->subs[SUB_REAL].inthreeway; 04330 04331 ast_mutex_unlock(&p0->lock); 04332 ast_mutex_unlock(&p1->lock); 04333 04334 ast_channel_unlock(c0); 04335 ast_channel_unlock(c1); 04336 04337 /* Native bridge failed */ 04338 if ((!master || !slave) && !nothingok) { 04339 dahdi_enable_ec(p0); 04340 dahdi_enable_ec(p1); 04341 return AST_BRIDGE_FAILED; 04342 } 04343 04344 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name); 04345 04346 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 04347 disable_dtmf_detect(op0); 04348 04349 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 04350 disable_dtmf_detect(op1); 04351 04352 for (;;) { 04353 struct ast_channel *c0_priority[2] = {c0, c1}; 04354 struct ast_channel *c1_priority[2] = {c1, c0}; 04355 04356 /* Here's our main loop... Start by locking things, looking for private parts, 04357 and then balking if anything is wrong */ 04358 04359 ast_channel_lock(c0); 04360 while (ast_channel_trylock(c1)) { 04361 CHANNEL_DEADLOCK_AVOIDANCE(c0); 04362 } 04363 04364 p0 = c0->tech_pvt; 04365 p1 = c1->tech_pvt; 04366 04367 if (op0 == p0) 04368 i0 = dahdi_get_index(c0, p0, 1); 04369 if (op1 == p1) 04370 i1 = dahdi_get_index(c1, p1, 1); 04371 04372 ast_channel_unlock(c0); 04373 ast_channel_unlock(c1); 04374 04375 if (!timeoutms || 04376 (op0 != p0) || 04377 (op1 != p1) || 04378 (ofd0 != c0->fds[0]) || 04379 (ofd1 != c1->fds[0]) || 04380 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 04381 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 04382 (oc0 != p0->owner) || 04383 (oc1 != p1->owner) || 04384 (t0 != p0->subs[SUB_REAL].inthreeway) || 04385 (t1 != p1->subs[SUB_REAL].inthreeway) || 04386 (oi0 != i0) || 04387 (oi1 != i1)) { 04388 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n", 04389 op0->channel, oi0, op1->channel, oi1); 04390 res = AST_BRIDGE_RETRY; 04391 goto return_from_bridge; 04392 } 04393 04394 #ifdef PRI_2BCT 04395 q931c0 = p0->call; 04396 q931c1 = p1->call; 04397 if (p0->transfer && p1->transfer 04398 && q931c0 && q931c1 04399 && !triedtopribridge) { 04400 pri_channel_bridge(q931c0, q931c1); 04401 triedtopribridge = 1; 04402 } 04403 #endif 04404 04405 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms); 04406 if (!who) { 04407 ast_debug(1, "Ooh, empty read...\n"); 04408 continue; 04409 } 04410 f = ast_read(who); 04411 if (!f || (f->frametype == AST_FRAME_CONTROL)) { 04412 *fo = f; 04413 *rc = who; 04414 res = AST_BRIDGE_COMPLETE; 04415 goto return_from_bridge; 04416 } 04417 if (f->frametype == AST_FRAME_DTMF) { 04418 if ((who == c0) && p0->pulsedial) { 04419 ast_write(c1, f); 04420 } else if ((who == c1) && p1->pulsedial) { 04421 ast_write(c0, f); 04422 } else { 04423 *fo = f; 04424 *rc = who; 04425 res = AST_BRIDGE_COMPLETE; 04426 goto return_from_bridge; 04427 } 04428 } 04429 ast_frfree(f); 04430 04431 /* Swap who gets priority */ 04432 priority = !priority; 04433 } 04434 04435 return_from_bridge: 04436 if (op0 == p0) 04437 dahdi_enable_ec(p0); 04438 04439 if (op1 == p1) 04440 dahdi_enable_ec(p1); 04441 04442 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 04443 enable_dtmf_detect(op0); 04444 04445 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 04446 enable_dtmf_detect(op1); 04447 04448 dahdi_unlink(slave, master, 1); 04449 04450 return res; 04451 }
static int dahdi_call | ( | struct ast_channel * | ast, | |
char * | rdest, | |||
int | timeout | |||
) | [static] |
Definition at line 2463 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.
02464 { 02465 struct dahdi_pvt *p = ast->tech_pvt; 02466 int x, res, idx,mysig; 02467 char *c, *n, *l; 02468 #ifdef HAVE_PRI 02469 char *s = NULL; 02470 #endif 02471 char dest[256]; /* must be same length as p->dialdest */ 02472 ast_mutex_lock(&p->lock); 02473 ast_copy_string(dest, rdest, sizeof(dest)); 02474 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest)); 02475 if ((ast->_state == AST_STATE_BUSY)) { 02476 p->subs[SUB_REAL].needbusy = 1; 02477 ast_mutex_unlock(&p->lock); 02478 return 0; 02479 } 02480 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 02481 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name); 02482 ast_mutex_unlock(&p->lock); 02483 return -1; 02484 } 02485 p->dialednone = 0; 02486 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ 02487 { 02488 /* Special pseudo -- automatically up */ 02489 ast_setstate(ast, AST_STATE_UP); 02490 ast_mutex_unlock(&p->lock); 02491 return 0; 02492 } 02493 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE; 02494 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 02495 if (res) 02496 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno)); 02497 p->outgoing = 1; 02498 02499 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02500 02501 mysig = p->sig; 02502 if (p->outsigmod > -1) 02503 mysig = p->outsigmod; 02504 02505 switch (mysig) { 02506 case SIG_FXOLS: 02507 case SIG_FXOGS: 02508 case SIG_FXOKS: 02509 if (p->owner == ast) { 02510 /* Normal ring, on hook */ 02511 02512 /* Don't send audio while on hook, until the call is answered */ 02513 p->dialing = 1; 02514 if (p->use_callerid) { 02515 /* Generate the Caller-ID spill if desired */ 02516 if (p->cidspill) { 02517 ast_log(LOG_WARNING, "cidspill already exists??\n"); 02518 ast_free(p->cidspill); 02519 } 02520 p->callwaitcas = 0; 02521 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) { 02522 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p)); 02523 p->cidpos = 0; 02524 send_callerid(p); 02525 } 02526 } 02527 /* Choose proper cadence */ 02528 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { 02529 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) 02530 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); 02531 p->cidrings = cidrings[p->distinctivering - 1]; 02532 } else { 02533 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) 02534 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); 02535 p->cidrings = p->sendcalleridafter; 02536 } 02537 02538 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */ 02539 c = strchr(dest, '/'); 02540 if (c) 02541 c++; 02542 if (c && (strlen(c) < p->stripmsd)) { 02543 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02544 c = NULL; 02545 } 02546 if (c) { 02547 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02548 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c); 02549 ast_debug(1, "FXO: setup deferred dialstring: %s\n", c); 02550 } else { 02551 p->dop.dialstr[0] = '\0'; 02552 } 02553 x = DAHDI_RING; 02554 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) { 02555 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno)); 02556 ast_mutex_unlock(&p->lock); 02557 return -1; 02558 } 02559 p->dialing = 1; 02560 } else { 02561 /* Call waiting call */ 02562 p->callwaitrings = 0; 02563 if (ast->cid.cid_num) 02564 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num)); 02565 else 02566 p->callwait_num[0] = '\0'; 02567 if (ast->cid.cid_name) 02568 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name)); 02569 else 02570 p->callwait_name[0] = '\0'; 02571 /* Call waiting tone instead */ 02572 if (dahdi_callwait(ast)) { 02573 ast_mutex_unlock(&p->lock); 02574 return -1; 02575 } 02576 /* Make ring-back */ 02577 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE)) 02578 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name); 02579 02580 } 02581 n = ast->cid.cid_name; 02582 l = ast->cid.cid_num; 02583 if (l) 02584 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num)); 02585 else 02586 p->lastcid_num[0] = '\0'; 02587 if (n) 02588 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name)); 02589 else 02590 p->lastcid_name[0] = '\0'; 02591 ast_setstate(ast, AST_STATE_RINGING); 02592 idx = dahdi_get_index(ast, p, 0); 02593 if (idx > -1) { 02594 p->subs[idx].needringing = 1; 02595 } 02596 break; 02597 case SIG_FXSLS: 02598 case SIG_FXSGS: 02599 case SIG_FXSKS: 02600 case SIG_EMWINK: 02601 case SIG_EM: 02602 case SIG_EM_E1: 02603 case SIG_FEATD: 02604 case SIG_FEATDMF: 02605 case SIG_E911: 02606 case SIG_FGC_CAMA: 02607 case SIG_FGC_CAMAMF: 02608 case SIG_FEATB: 02609 case SIG_SFWINK: 02610 case SIG_SF: 02611 case SIG_SF_FEATD: 02612 case SIG_SF_FEATDMF: 02613 case SIG_FEATDMF_TA: 02614 case SIG_SF_FEATB: 02615 c = strchr(dest, '/'); 02616 if (c) 02617 c++; 02618 else 02619 c = ""; 02620 if (strlen(c) < p->stripmsd) { 02621 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02622 ast_mutex_unlock(&p->lock); 02623 return -1; 02624 } 02625 #ifdef HAVE_PRI 02626 /* Start the trunk, if not GR-303 */ 02627 if (!p->pri) { 02628 #endif 02629 x = DAHDI_START; 02630 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02631 if (res < 0) { 02632 if (errno != EINPROGRESS) { 02633 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 02634 ast_mutex_unlock(&p->lock); 02635 return -1; 02636 } 02637 } 02638 #ifdef HAVE_PRI 02639 } 02640 #endif 02641 ast_debug(1, "Dialing '%s'\n", c); 02642 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02643 02644 c += p->stripmsd; 02645 02646 switch (mysig) { 02647 case SIG_FEATD: 02648 l = ast->cid.cid_num; 02649 if (l) 02650 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c); 02651 else 02652 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c); 02653 break; 02654 case SIG_FEATDMF: 02655 l = ast->cid.cid_num; 02656 if (l) 02657 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c); 02658 else 02659 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c); 02660 break; 02661 case SIG_FEATDMF_TA: 02662 { 02663 const char *cic, *ozz; 02664 02665 /* If you have to go through a Tandem Access point you need to use this */ 02666 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ"); 02667 if (!ozz) 02668 ozz = defaultozz; 02669 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC"); 02670 if (!cic) 02671 cic = defaultcic; 02672 if (!ozz || !cic) { 02673 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n"); 02674 ast_mutex_unlock(&p->lock); 02675 return -1; 02676 } 02677 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic); 02678 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c); 02679 p->whichwink = 0; 02680 } 02681 break; 02682 case SIG_E911: 02683 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr)); 02684 break; 02685 case SIG_FGC_CAMA: 02686 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c); 02687 break; 02688 case SIG_FGC_CAMAMF: 02689 case SIG_FEATB: 02690 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c); 02691 break; 02692 default: 02693 if (p->pulse) 02694 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c); 02695 else 02696 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c); 02697 break; 02698 } 02699 02700 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) { 02701 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 02702 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 02703 p->echorest[sizeof(p->echorest) - 1] = '\0'; 02704 p->echobreak = 1; 02705 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 02706 } else 02707 p->echobreak = 0; 02708 if (!res) { 02709 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 02710 int saveerr = errno; 02711 02712 x = DAHDI_ONHOOK; 02713 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02714 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 02715 ast_mutex_unlock(&p->lock); 02716 return -1; 02717 } 02718 } else 02719 ast_debug(1, "Deferring dialing...\n"); 02720 02721 p->dialing = 1; 02722 if (ast_strlen_zero(c)) 02723 p->dialednone = 1; 02724 ast_setstate(ast, AST_STATE_DIALING); 02725 break; 02726 case 0: 02727 /* Special pseudo -- automatically up*/ 02728 ast_setstate(ast, AST_STATE_UP); 02729 break; 02730 case SIG_PRI: 02731 case SIG_BRI: 02732 case SIG_BRI_PTMP: 02733 case SIG_SS7: 02734 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */ 02735 p->dialdest[0] = '\0'; 02736 p->dialing = 1; 02737 break; 02738 default: 02739 ast_debug(1, "not yet implemented\n"); 02740 ast_mutex_unlock(&p->lock); 02741 return -1; 02742 } 02743 #ifdef HAVE_SS7 02744 if (p->ss7) { 02745 char ss7_called_nai; 02746 int called_nai_strip; 02747 char ss7_calling_nai; 02748 int calling_nai_strip; 02749 const char *charge_str = NULL; 02750 const char *gen_address = NULL; 02751 const char *gen_digits = NULL; 02752 const char *gen_dig_type = NULL; 02753 const char *gen_dig_scheme = NULL; 02754 const char *gen_name = NULL; 02755 const char *jip_digits = NULL; 02756 const char *lspi_ident = NULL; 02757 const char *rlt_flag = NULL; 02758 const char *call_ref_id = NULL; 02759 const char *call_ref_pc = NULL; 02760 const char *send_far = NULL; 02761 02762 c = strchr(dest, '/'); 02763 if (c) { 02764 c++; 02765 } else { 02766 c = ""; 02767 } 02768 if (strlen(c) < p->stripmsd) { 02769 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02770 ast_mutex_unlock(&p->lock); 02771 return -1; 02772 } 02773 02774 if (!p->hidecallerid) { 02775 l = ast->cid.cid_num; 02776 } else { 02777 l = NULL; 02778 } 02779 02780 if (ss7_grab(p, p->ss7)) { 02781 ast_log(LOG_WARNING, "Failed to grab SS7!\n"); 02782 ast_mutex_unlock(&p->lock); 02783 return -1; 02784 } 02785 p->digital = IS_DIGITAL(ast->transfercapability); 02786 p->ss7call = isup_new_call(p->ss7->ss7); 02787 02788 if (!p->ss7call) { 02789 ss7_rel(p->ss7); 02790 ast_mutex_unlock(&p->lock); 02791 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n"); 02792 return -1; 02793 } 02794 02795 called_nai_strip = 0; 02796 ss7_called_nai = p->ss7->called_nai; 02797 if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */ 02798 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) { 02799 called_nai_strip = strlen(p->ss7->internationalprefix); 02800 ss7_called_nai = SS7_NAI_INTERNATIONAL; 02801 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) { 02802 called_nai_strip = strlen(p->ss7->nationalprefix); 02803 ss7_called_nai = SS7_NAI_NATIONAL; 02804 } else { 02805 ss7_called_nai = SS7_NAI_SUBSCRIBER; 02806 } 02807 } 02808 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7); 02809 02810 calling_nai_strip = 0; 02811 ss7_calling_nai = p->ss7->calling_nai; 02812 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */ 02813 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) { 02814 calling_nai_strip = strlen(p->ss7->internationalprefix); 02815 ss7_calling_nai = SS7_NAI_INTERNATIONAL; 02816 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) { 02817 calling_nai_strip = strlen(p->ss7->nationalprefix); 02818 ss7_calling_nai = SS7_NAI_NATIONAL; 02819 } else { 02820 ss7_calling_nai = SS7_NAI_SUBSCRIBER; 02821 } 02822 } 02823 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai, 02824 p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED), 02825 p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED ); 02826 02827 isup_set_oli(p->ss7call, ast->cid.cid_ani2); 02828 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc); 02829 02830 ast_channel_lock(ast); 02831 /* Set the charge number if it is set */ 02832 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER"); 02833 if (charge_str) 02834 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10); 02835 02836 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS"); 02837 if (gen_address) 02838 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 */ 02839 02840 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS"); 02841 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE"); 02842 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME"); 02843 if (gen_digits) 02844 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme)); 02845 02846 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME"); 02847 if (gen_name) 02848 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED); 02849 02850 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP"); 02851 if (jip_digits) 02852 isup_set_jip_digits(p->ss7call, jip_digits); 02853 02854 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT"); 02855 if (lspi_ident) 02856 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00); 02857 02858 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON"); 02859 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) { 02860 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */ 02861 } 02862 02863 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT"); 02864 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC"); 02865 if (call_ref_id && call_ref_pc) { 02866 isup_set_callref(p->ss7call, atoi(call_ref_id), 02867 call_ref_pc ? atoi(call_ref_pc) : 0); 02868 } 02869 02870 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR"); 02871 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 )) 02872 (isup_far(p->ss7->ss7, p->ss7call)); 02873 02874 ast_channel_unlock(ast); 02875 02876 isup_iam(p->ss7->ss7, p->ss7call); 02877 ast_setstate(ast, AST_STATE_DIALING); 02878 ss7_rel(p->ss7); 02879 } 02880 #endif /* HAVE_SS7 */ 02881 #ifdef HAVE_PRI 02882 if (p->pri) { 02883 struct pri_sr *sr; 02884 #ifdef SUPPORT_USERUSER 02885 const char *useruser; 02886 #endif 02887 int pridialplan; 02888 int dp_strip; 02889 int prilocaldialplan; 02890 int ldp_strip; 02891 int exclusive; 02892 const char *rr_str; 02893 int redirect_reason; 02894 02895 c = strchr(dest, '/'); 02896 if (c) { 02897 c++; 02898 } else { 02899 c = ""; 02900 } 02901 02902 l = NULL; 02903 n = NULL; 02904 if (!p->hidecallerid) { 02905 l = ast->cid.cid_num; 02906 if (!p->hidecalleridname) { 02907 n = ast->cid.cid_name; 02908 } 02909 } 02910 02911 if (strlen(c) < p->stripmsd) { 02912 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02913 ast_mutex_unlock(&p->lock); 02914 return -1; 02915 } 02916 if (mysig != SIG_FXSKS) { 02917 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02918 s = strchr(c + p->stripmsd, 'w'); 02919 if (s) { 02920 if (strlen(s) > 1) 02921 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s); 02922 else 02923 p->dop.dialstr[0] = '\0'; 02924 *s = '\0'; 02925 } else { 02926 p->dop.dialstr[0] = '\0'; 02927 } 02928 } 02929 if (pri_grab(p, p->pri)) { 02930 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 02931 ast_mutex_unlock(&p->lock); 02932 return -1; 02933 } 02934 if (!(p->call = pri_new_call(p->pri->pri))) { 02935 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel); 02936 pri_rel(p->pri); 02937 ast_mutex_unlock(&p->lock); 02938 return -1; 02939 } 02940 if (!(sr = pri_sr_new())) { 02941 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel); 02942 pri_rel(p->pri); 02943 ast_mutex_unlock(&p->lock); 02944 } 02945 if (p->bearer || (mysig == SIG_FXSKS)) { 02946 if (p->bearer) { 02947 ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel); 02948 p->bearer->call = p->call; 02949 } else 02950 ast_debug(1, "I'm being setup with no bearer right now...\n"); 02951 02952 pri_set_crv(p->pri->pri, p->call, p->channel, 0); 02953 } 02954 p->digital = IS_DIGITAL(ast->transfercapability); 02955 /* Add support for exclusive override */ 02956 if (p->priexclusive) 02957 exclusive = 1; 02958 else { 02959 /* otherwise, traditional behavior */ 02960 if (p->pri->nodetype == PRI_NETWORK) 02961 exclusive = 0; 02962 else 02963 exclusive = 1; 02964 } 02965 02966 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1); 02967 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 02968 (p->digital ? -1 : 02969 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW))); 02970 if (p->pri->facilityenable) 02971 pri_facility_enable(p->pri->pri); 02972 02973 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability)); 02974 dp_strip = 0; 02975 pridialplan = p->pri->dialplan - 1; 02976 if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */ 02977 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 02978 if (pridialplan == -2) { 02979 dp_strip = strlen(p->pri->internationalprefix); 02980 } 02981 pridialplan = PRI_INTERNATIONAL_ISDN; 02982 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 02983 if (pridialplan == -2) { 02984 dp_strip = strlen(p->pri->nationalprefix); 02985 } 02986 pridialplan = PRI_NATIONAL_ISDN; 02987 } else { 02988 pridialplan = PRI_LOCAL_ISDN; 02989 } 02990 } 02991 while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') { 02992 switch (c[p->stripmsd]) { 02993 case 'U': 02994 pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf); 02995 break; 02996 case 'I': 02997 pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf); 02998 break; 02999 case 'N': 03000 pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf); 03001 break; 03002 case 'L': 03003 pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf); 03004 break; 03005 case 'S': 03006 pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf); 03007 break; 03008 case 'V': 03009 pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf); 03010 break; 03011 case 'R': 03012 pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf); 03013 break; 03014 case 'u': 03015 pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0); 03016 break; 03017 case 'e': 03018 pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0); 03019 break; 03020 case 'x': 03021 pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0); 03022 break; 03023 case 'f': 03024 pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0); 03025 break; 03026 case 'n': 03027 pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0); 03028 break; 03029 case 'p': 03030 pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0); 03031 break; 03032 case 'r': 03033 pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0); 03034 break; 03035 default: 03036 if (isalpha(c[p->stripmsd])) { 03037 ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n", 03038 c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]); 03039 } 03040 break; 03041 } 03042 c++; 03043 } 03044 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0); 03045 03046 ldp_strip = 0; 03047 prilocaldialplan = p->pri->localdialplan - 1; 03048 if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */ 03049 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 03050 if (prilocaldialplan == -2) { 03051 ldp_strip = strlen(p->pri->internationalprefix); 03052 } 03053 prilocaldialplan = PRI_INTERNATIONAL_ISDN; 03054 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 03055 if (prilocaldialplan == -2) { 03056 ldp_strip = strlen(p->pri->nationalprefix); 03057 } 03058 prilocaldialplan = PRI_NATIONAL_ISDN; 03059 } else { 03060 prilocaldialplan = PRI_LOCAL_ISDN; 03061 } 03062 } 03063 if (l != NULL) { 03064 while (*l > '9' && *l != '*' && *l != '#') { 03065 switch (*l) { 03066 case 'U': 03067 prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf); 03068 break; 03069 case 'I': 03070 prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf); 03071 break; 03072 case 'N': 03073 prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf); 03074 break; 03075 case 'L': 03076 prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf); 03077 break; 03078 case 'S': 03079 prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf); 03080 break; 03081 case 'V': 03082 prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf); 03083 break; 03084 case 'R': 03085 prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf); 03086 break; 03087 case 'u': 03088 prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0); 03089 break; 03090 case 'e': 03091 prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0); 03092 break; 03093 case 'x': 03094 prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0); 03095 break; 03096 case 'f': 03097 prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0); 03098 break; 03099 case 'n': 03100 prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0); 03101 break; 03102 case 'p': 03103 prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0); 03104 break; 03105 case 'r': 03106 prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0); 03107 break; 03108 default: 03109 if (isalpha(*l)) { 03110 ast_log(LOG_WARNING, 03111 "Unrecognized prilocaldialplan %s modifier: %c\n", 03112 *l > 'Z' ? "NPI" : "TON", *l); 03113 } 03114 break; 03115 } 03116 l++; 03117 } 03118 } 03119 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan, 03120 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE)); 03121 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) { 03122 if (!strcasecmp(rr_str, "UNKNOWN")) 03123 redirect_reason = 0; 03124 else if (!strcasecmp(rr_str, "BUSY")) 03125 redirect_reason = 1; 03126 else if (!strcasecmp(rr_str, "NO_REPLY")) 03127 redirect_reason = 2; 03128 else if (!strcasecmp(rr_str, "UNCONDITIONAL")) 03129 redirect_reason = 15; 03130 else 03131 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03132 } else 03133 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03134 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason); 03135 03136 #ifdef SUPPORT_USERUSER 03137 /* User-user info */ 03138 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO"); 03139 03140 if (useruser) 03141 pri_sr_set_useruser(sr, useruser); 03142 #endif 03143 03144 if (pri_setup(p->pri->pri, p->call, sr)) { 03145 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 03146 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan)); 03147 pri_rel(p->pri); 03148 ast_mutex_unlock(&p->lock); 03149 pri_sr_free(sr); 03150 return -1; 03151 } 03152 pri_sr_free(sr); 03153 ast_setstate(ast, AST_STATE_DIALING); 03154 pri_rel(p->pri); 03155 } 03156 #endif 03157 ast_mutex_unlock(&p->lock); 03158 return 0; 03159 }
static int dahdi_callwait | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 2423 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().
02424 { 02425 struct dahdi_pvt *p = ast->tech_pvt; 02426 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 02427 if (p->cidspill) { 02428 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 02429 ast_free(p->cidspill); 02430 } 02431 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 02432 return -1; 02433 save_conference(p); 02434 /* Silence */ 02435 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 02436 if (!p->callwaitrings && p->callwaitingcallerid) { 02437 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 02438 p->callwaitcas = 1; 02439 p->cidlen = 2400 + 680 + READ_SIZE * 4; 02440 } else { 02441 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 02442 p->callwaitcas = 0; 02443 p->cidlen = 2400 + READ_SIZE * 4; 02444 } 02445 p->cidpos = 0; 02446 send_callerid(p); 02447 02448 return 0; 02449 }
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 1108 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().
01108 { 01109 /* recall that if a field is not included here it is initialized 01110 * to 0 or equivalent 01111 */ 01112 struct dahdi_chan_conf conf = { 01113 #ifdef HAVE_PRI 01114 .pri = { 01115 .nsf = PRI_NSF_NONE, 01116 .switchtype = PRI_SWITCH_NI2, 01117 .dialplan = PRI_UNKNOWN + 1, 01118 .localdialplan = PRI_NATIONAL_ISDN + 1, 01119 .nodetype = PRI_CPE, 01120 01121 .minunused = 2, 01122 .idleext = "", 01123 .idledial = "", 01124 .internationalprefix = "", 01125 .nationalprefix = "", 01126 .localprefix = "", 01127 .privateprefix = "", 01128 .unknownprefix = "", 01129 .resetinterval = -1, 01130 }, 01131 #endif 01132 #ifdef HAVE_SS7 01133 .ss7 = { 01134 .called_nai = SS7_NAI_NATIONAL, 01135 .calling_nai = SS7_NAI_NATIONAL, 01136 .internationalprefix = "", 01137 .nationalprefix = "", 01138 .subscriberprefix = "", 01139 .unknownprefix = "" 01140 }, 01141 #endif 01142 .chan = { 01143 .context = "default", 01144 .cid_num = "", 01145 .cid_name = "", 01146 .mohinterpret = "default", 01147 .mohsuggest = "", 01148 .parkinglot = "", 01149 .transfertobusy = 1, 01150 01151 .cid_signalling = CID_SIG_BELL, 01152 .cid_start = CID_START_RING, 01153 .dahditrcallerid = 0, 01154 .use_callerid = 1, 01155 .sig = -1, 01156 .outsigmod = -1, 01157 01158 .cid_rxgain = +5.0, 01159 01160 .tonezone = -1, 01161 01162 .echocancel.head.tap_length = 1, 01163 01164 .busycount = 3, 01165 .busycompare = 0, 01166 .busytonelength = 0, 01167 .busyquietlength = 0, 01168 .busyfuzziness = 0, 01169 .silencethreshold = 0, 01170 01171 .accountcode = "", 01172 01173 .mailbox = "", 01174 01175 01176 .polarityonanswerdelay = 600, 01177 01178 .sendcalleridafter = DEFAULT_CIDRINGS, 01179 01180 .buf_policy = DAHDI_POLICY_IMMEDIATE, 01181 .buf_no = numbufs 01182 }, 01183 .timing = { 01184 .prewinktime = -1, 01185 .preflashtime = -1, 01186 .winktime = -1, 01187 .flashtime = -1, 01188 .starttime = -1, 01189 .rxwinktime = -1, 01190 .rxflashtime = -1, 01191 .debouncetime = -1 01192 }, 01193 .is_sig_auto = 1, 01194 .smdi_port = "/dev/ttyS0", 01195 }; 01196 01197 return conf; 01198 }
static void dahdi_close | ( | int | fd | ) | [static] |
Definition at line 1503 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 1516 of file chan_dahdi.c.
References dahdi_close(), and dahdi_pri::fds.
Referenced by __unload_module(), dahdi_restart(), and start_pri().
01517 { 01518 dahdi_close(pri->fds[fd_num]); 01519 pri->fds[fd_num] = -1; 01520 }
static void dahdi_close_sub | ( | struct dahdi_pvt * | chan_pvt, | |
int | sub_num | |||
) | [static] |
Definition at line 1509 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().
01510 { 01511 dahdi_close(chan_pvt->subs[sub_num].dfd); 01512 chan_pvt->subs[sub_num].dfd = -1; 01513 }
static int dahdi_confmute | ( | struct dahdi_pvt * | p, | |
int | muted | |||
) | [inline, static] |
Definition at line 2244 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(), dahdi_new(), and dahdi_read().
02245 { 02246 int x, y, res; 02247 x = muted; 02248 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 02249 y = 1; 02250 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y); 02251 if (res) 02252 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno)); 02253 } 02254 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x); 02255 if (res < 0) 02256 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno)); 02257 return res; 02258 }
static char* dahdi_destroy_channel | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12429 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.
12430 { 12431 int channel; 12432 int ret; 12433 switch (cmd) { 12434 case CLI_INIT: 12435 e->command = "dahdi destroy channel"; 12436 e->usage = 12437 "Usage: dahdi destroy channel <chan num>\n" 12438 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n"; 12439 return NULL; 12440 case CLI_GENERATE: 12441 return NULL; 12442 } 12443 if (a->argc != 4) 12444 return CLI_SHOWUSAGE; 12445 12446 channel = atoi(a->argv[3]); 12447 ret = dahdi_destroy_channel_bynum(channel); 12448 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE; 12449 }
static int dahdi_destroy_channel_bynum | ( | int | channel | ) | [static] |
Definition at line 8054 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().
08055 { 08056 struct dahdi_pvt *tmp = NULL; 08057 struct dahdi_pvt *prev = NULL; 08058 08059 tmp = iflist; 08060 while (tmp) { 08061 if (tmp->channel == channel) { 08062 int x = DAHDI_FLASH; 08063 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 */ 08064 destroy_channel(prev, tmp, 1); 08065 ast_module_unref(ast_module_info->self); 08066 return RESULT_SUCCESS; 08067 } 08068 prev = tmp; 08069 tmp = tmp->next; 08070 } 08071 return RESULT_FAILURE; 08072 }
static int dahdi_digit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 1611 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.
01612 { 01613 struct dahdi_pvt *pvt; 01614 int idx; 01615 int dtmf = -1; 01616 01617 pvt = chan->tech_pvt; 01618 01619 ast_mutex_lock(&pvt->lock); 01620 01621 idx = dahdi_get_index(chan, pvt, 0); 01622 01623 if ((idx != SUB_REAL) || !pvt->owner) 01624 goto out; 01625 01626 #ifdef HAVE_PRI 01627 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP)) 01628 && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) { 01629 if (pvt->setup_ack) { 01630 if (!pri_grab(pvt, pvt->pri)) { 01631 pri_information(pvt->pri->pri, pvt->call, digit); 01632 pri_rel(pvt->pri); 01633 } else 01634 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span); 01635 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) { 01636 int res; 01637 ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit); 01638 res = strlen(pvt->dialdest); 01639 pvt->dialdest[res++] = digit; 01640 pvt->dialdest[res] = '\0'; 01641 } 01642 goto out; 01643 } 01644 #endif 01645 if ((dtmf = digit_to_dtmfindex(digit)) == -1) 01646 goto out; 01647 01648 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) { 01649 int res; 01650 struct dahdi_dialoperation zo = { 01651 .op = DAHDI_DIAL_OP_APPEND, 01652 }; 01653 01654 zo.dialstr[0] = 'T'; 01655 zo.dialstr[1] = digit; 01656 zo.dialstr[2] = '\0'; 01657 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo))) 01658 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno)); 01659 else 01660 pvt->dialing = 1; 01661 } else { 01662 ast_debug(1, "Started VLDTMF digit '%c'\n", digit); 01663 pvt->dialing = 1; 01664 pvt->begindigit = digit; 01665 } 01666 01667 out: 01668 ast_mutex_unlock(&pvt->lock); 01669 01670 return 0; 01671 }
static int dahdi_digit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 1673 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.
01674 { 01675 struct dahdi_pvt *pvt; 01676 int res = 0; 01677 int idx; 01678 int x; 01679 01680 pvt = chan->tech_pvt; 01681 01682 ast_mutex_lock(&pvt->lock); 01683 01684 idx = dahdi_get_index(chan, pvt, 0); 01685 01686 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse) 01687 goto out; 01688 01689 #ifdef HAVE_PRI 01690 /* This means that the digit was already sent via PRI signalling */ 01691 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP)) 01692 && !pvt->begindigit) 01693 goto out; 01694 #endif 01695 01696 if (pvt->begindigit) { 01697 x = -1; 01698 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit); 01699 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x); 01700 pvt->dialing = 0; 01701 pvt->begindigit = 0; 01702 } 01703 01704 out: 01705 ast_mutex_unlock(&pvt->lock); 01706 01707 return res; 01708 }
static void dahdi_disable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2073 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().
02074 { 02075 int res; 02076 02077 if (p->echocanon) { 02078 struct dahdi_echocanparams ecp = { .tap_length = 0 }; 02079 02080 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp); 02081 02082 if (res) 02083 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno)); 02084 else 02085 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel); 02086 } 02087 02088 p->echocanon = 0; 02089 }
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 6517 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().
06518 { 06519 /* Do not disturb */ 06520 dahdichan->dnd = on; 06521 ast_verb(3, "%s DND on channel %d\n", 06522 on? "Enabled" : "Disabled", 06523 dahdichan->channel); 06524 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 06525 "Channel: DAHDI/%d\r\n" 06526 "Status: %s\r\n", dahdichan->channel, 06527 on? "enabled" : "disabled"); 06528 }
static void dahdi_enable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2024 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().
02025 { 02026 int x; 02027 int res; 02028 if (!p) 02029 return; 02030 if (p->echocanon) { 02031 ast_debug(1, "Echo cancellation already on\n"); 02032 return; 02033 } 02034 if (p->digital) { 02035 ast_debug(1, "Echo cancellation isn't required on digital connection\n"); 02036 return; 02037 } 02038 if (p->echocancel.head.tap_length) { 02039 if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) { 02040 x = 1; 02041 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x); 02042 if (res) 02043 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno)); 02044 } 02045 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel); 02046 if (res) { 02047 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno)); 02048 } else { 02049 p->echocanon = 1; 02050 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel); 02051 } 02052 } else 02053 ast_debug(1, "No echo cancellation requested\n"); 02054 }
static struct ast_frame * dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5633 of file chan_dahdi.c.
References __dahdi_exception(), ast_mutex_lock(), ast_mutex_unlock(), f, dahdi_pvt::lock, and ast_channel::tech_pvt.
05634 { 05635 struct dahdi_pvt *p = ast->tech_pvt; 05636 struct ast_frame *f; 05637 ast_mutex_lock(&p->lock); 05638 f = __dahdi_exception(ast); 05639 ast_mutex_unlock(&p->lock); 05640 return f; 05641 }
static int dahdi_fake_event | ( | struct dahdi_pvt * | p, | |
int | mode | |||
) | [static] |
Definition at line 13319 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().
13320 { 13321 if (p) { 13322 switch (mode) { 13323 case TRANSFER: 13324 p->fake_event = DAHDI_EVENT_WINKFLASH; 13325 break; 13326 case HANGUP: 13327 p->fake_event = DAHDI_EVENT_ONHOOK; 13328 break; 13329 default: 13330 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name); 13331 } 13332 } 13333 return 0; 13334 }
static int dahdi_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 4453 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.
04454 { 04455 struct dahdi_pvt *p = newchan->tech_pvt; 04456 int x; 04457 ast_mutex_lock(&p->lock); 04458 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name); 04459 if (p->owner == oldchan) { 04460 p->owner = newchan; 04461 } 04462 for (x = 0; x < 3; x++) 04463 if (p->subs[x].owner == oldchan) { 04464 if (!x) 04465 dahdi_unlink(NULL, p, 0); 04466 p->subs[x].owner = newchan; 04467 } 04468 if (newchan->_state == AST_STATE_RINGING) 04469 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0); 04470 update_conf(p); 04471 ast_mutex_unlock(&p->lock); 04472 return 0; 04473 }
static int dahdi_func_read | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 4030 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.
04031 { 04032 struct dahdi_pvt *p = chan->tech_pvt; 04033 04034 if (!strcasecmp(data, "rxgain")) { 04035 ast_mutex_lock(&p->lock); 04036 snprintf(buf, len, "%f", p->rxgain); 04037 ast_mutex_unlock(&p->lock); 04038 } else if (!strcasecmp(data, "txgain")) { 04039 ast_mutex_lock(&p->lock); 04040 snprintf(buf, len, "%f", p->txgain); 04041 ast_mutex_unlock(&p->lock); 04042 } else { 04043 ast_copy_string(buf, "", len); 04044 } 04045 return 0; 04046 }
static int dahdi_get_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition at line 303 of file chan_dahdi.c.
Referenced by __dahdi_exception(), dahdi_handle_event(), mwi_send_thread(), mwi_thread(), and ss_thread().
00304 { 00305 int j; 00306 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) 00307 return -1; 00308 return j; 00309 }
static int dahdi_get_index | ( | struct ast_channel * | ast, | |
struct dahdi_pvt * | p, | |||
int | nullok | |||
) | [static] |
Definition at line 1317 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().
01318 { 01319 int res; 01320 if (p->subs[SUB_REAL].owner == ast) 01321 res = 0; 01322 else if (p->subs[SUB_CALLWAIT].owner == ast) 01323 res = 1; 01324 else if (p->subs[SUB_THREEWAY].owner == ast) 01325 res = 2; 01326 else { 01327 res = -1; 01328 if (!nullok) 01329 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n"); 01330 } 01331 return res; 01332 }
static void dahdi_handle_dtmfup | ( | struct ast_channel * | ast, | |
int | idx, | |||
struct ast_frame ** | dest | |||
) | [static] |
Definition at line 4614 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().
04615 { 04616 struct dahdi_pvt *p = ast->tech_pvt; 04617 struct ast_frame *f = *dest; 04618 04619 ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name); 04620 04621 if (p->confirmanswer) { 04622 ast_debug(1, "Confirm answer on %s!\n", ast->name); 04623 /* Upon receiving a DTMF digit, consider this an answer confirmation instead 04624 of a DTMF digit */ 04625 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04626 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 04627 *dest = &p->subs[idx].f; 04628 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */ 04629 p->confirmanswer = 0; 04630 } else if (p->callwaitcas) { 04631 if ((f->subclass == 'A') || (f->subclass == 'D')) { 04632 ast_debug(1, "Got some DTMF, but it's for the CAS\n"); 04633 if (p->cidspill) 04634 ast_free(p->cidspill); 04635 send_cwcidspill(p); 04636 } 04637 p->callwaitcas = 0; 04638 p->subs[idx].f.frametype = AST_FRAME_NULL; 04639 p->subs[idx].f.subclass = 0; 04640 *dest = &p->subs[idx].f; 04641 } else if (f->subclass == 'f') { 04642 /* Fax tone -- Handle and return NULL */ 04643 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) { 04644 p->faxhandled = 1; 04645 if (strcmp(ast->exten, "fax")) { 04646 const char *target_context = S_OR(ast->macrocontext, ast->context); 04647 04648 /* We need to unlock 'ast' here because ast_exists_extension has the 04649 * potential to start autoservice on the channel. Such action is prone 04650 * to deadlock. 04651 */ 04652 ast_mutex_unlock(&p->lock); 04653 ast_channel_unlock(ast); 04654 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) { 04655 ast_channel_lock(ast); 04656 ast_mutex_lock(&p->lock); 04657 ast_verb(3, "Redirecting %s to fax extension\n", ast->name); 04658 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 04659 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 04660 if (ast_async_goto(ast, target_context, "fax", 1)) 04661 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 04662 } else { 04663 ast_channel_lock(ast); 04664 ast_mutex_lock(&p->lock); 04665 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 04666 } 04667 } else { 04668 ast_debug(1, "Already in a fax extension, not redirecting\n"); 04669 } 04670 } else { 04671 ast_debug(1, "Fax already handled\n"); 04672 } 04673 dahdi_confmute(p, 0); 04674 p->subs[idx].f.frametype = AST_FRAME_NULL; 04675 p->subs[idx].f.subclass = 0; 04676 *dest = &p->subs[idx].f; 04677 } 04678 }
static struct ast_frame* dahdi_handle_event | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 4691 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, alloc_sub(), dahdi_pvt::answeronpolarityswitch, ast_bridged_channel(), AST_CAUSE_NO_ANSWER, 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_pthread_create_detached, ast_queue_control(), ast_queue_control_data(), ast_queue_hangup_with_cause(), 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, CHANNEL_DEADLOCK_AVOIDANCE, 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, DLA_LOCK, DLA_UNLOCK, 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, ast_frame::ptr, 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().
04692 { 04693 int res, x; 04694 int idx, mysig; 04695 char *c; 04696 struct dahdi_pvt *p = ast->tech_pvt; 04697 pthread_t threadid; 04698 struct ast_channel *chan; 04699 struct ast_frame *f; 04700 04701 idx = dahdi_get_index(ast, p, 0); 04702 mysig = p->sig; 04703 if (p->outsigmod > -1) 04704 mysig = p->outsigmod; 04705 p->subs[idx].f.frametype = AST_FRAME_NULL; 04706 p->subs[idx].f.subclass = 0; 04707 p->subs[idx].f.datalen = 0; 04708 p->subs[idx].f.samples = 0; 04709 p->subs[idx].f.mallocd = 0; 04710 p->subs[idx].f.offset = 0; 04711 p->subs[idx].f.src = "dahdi_handle_event"; 04712 p->subs[idx].f.data.ptr = NULL; 04713 f = &p->subs[idx].f; 04714 04715 if (idx < 0) 04716 return &p->subs[idx].f; 04717 if (p->fake_event) { 04718 res = p->fake_event; 04719 p->fake_event = 0; 04720 } else 04721 res = dahdi_get_event(p->subs[idx].dfd); 04722 04723 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx); 04724 04725 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) { 04726 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0; 04727 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff); 04728 #ifdef HAVE_PRI 04729 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 04730 /* absorb event */ 04731 } else { 04732 #endif 04733 p->subs[idx].f.frametype = AST_FRAME_DTMF_END; 04734 p->subs[idx].f.subclass = res & 0xff; 04735 #ifdef HAVE_PRI 04736 } 04737 #endif 04738 dahdi_handle_dtmfup(ast, idx, &f); 04739 return f; 04740 } 04741 04742 if (res & DAHDI_EVENT_DTMFDOWN) { 04743 ast_debug(1, "DTMF Down '%c'\n", res & 0xff); 04744 /* Mute conference */ 04745 dahdi_confmute(p, 1); 04746 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN; 04747 p->subs[idx].f.subclass = res & 0xff; 04748 return &p->subs[idx].f; 04749 } 04750 04751 switch (res) { 04752 case DAHDI_EVENT_EC_DISABLED: 04753 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel); 04754 p->echocanon = 0; 04755 break; 04756 case DAHDI_EVENT_BITSCHANGED: 04757 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig)); 04758 case DAHDI_EVENT_PULSE_START: 04759 /* Stop tone if there's a pulse start and the PBX isn't started */ 04760 if (!ast->pbx) 04761 tone_zone_play_tone(p->subs[idx].dfd, -1); 04762 break; 04763 case DAHDI_EVENT_DIALCOMPLETE: 04764 if (p->inalarm) break; 04765 if ((p->radio || (p->oprmode < 0))) break; 04766 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) { 04767 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno)); 04768 return NULL; 04769 } 04770 if (!x) { /* if not still dialing in driver */ 04771 dahdi_enable_ec(p); 04772 if (p->echobreak) { 04773 dahdi_train_ec(p); 04774 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); 04775 p->dop.op = DAHDI_DIAL_OP_REPLACE; 04776 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 04777 p->echobreak = 0; 04778 } else { 04779 p->dialing = 0; 04780 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) { 04781 /* if thru with dialing after offhook */ 04782 if (ast->_state == AST_STATE_DIALING_OFFHOOK) { 04783 ast_setstate(ast, AST_STATE_UP); 04784 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04785 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 04786 break; 04787 } else { /* if to state wait for offhook to dial rest */ 04788 /* we now wait for off hook */ 04789 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK); 04790 } 04791 } 04792 if (ast->_state == AST_STATE_DIALING) { 04793 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 04794 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n"); 04795 } 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)))) { 04796 ast_setstate(ast, AST_STATE_RINGING); 04797 } else if (!p->answeronpolarityswitch) { 04798 ast_setstate(ast, AST_STATE_UP); 04799 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04800 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 04801 /* If aops=0 and hops=1, this is necessary */ 04802 p->polarity = POLARITY_REV; 04803 } else { 04804 /* Start clean, so we can catch the change to REV polarity when party answers */ 04805 p->polarity = POLARITY_IDLE; 04806 } 04807 } 04808 } 04809 } 04810 break; 04811 case DAHDI_EVENT_ALARM: 04812 #ifdef HAVE_PRI 04813 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 04814 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) { 04815 /* T309 is not enabled : hangup calls when alarm occurs */ 04816 if (p->call) { 04817 if (p->pri && p->pri->pri) { 04818 if (!pri_grab(p, p->pri)) { 04819 pri_hangup(p->pri->pri, p->call, -1); 04820 pri_destroycall(p->pri->pri, p->call); 04821 p->call = NULL; 04822 pri_rel(p->pri); 04823 } else 04824 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 04825 } else 04826 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n"); 04827 } 04828 if (p->owner) 04829 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 04830 } 04831 } 04832 if (p->bearer) 04833 p->bearer->inalarm = 1; 04834 else 04835 #endif 04836 p->inalarm = 1; 04837 res = get_alarms(p); 04838 handle_alarms(p, res); 04839 #ifdef HAVE_PRI 04840 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 04841 /* fall through intentionally */ 04842 } else { 04843 break; 04844 } 04845 #endif 04846 #ifdef HAVE_SS7 04847 if (p->sig == SIG_SS7) 04848 break; 04849 #endif 04850 case DAHDI_EVENT_ONHOOK: 04851 if (p->radio) { 04852 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04853 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY; 04854 break; 04855 } 04856 if (p->oprmode < 0) 04857 { 04858 if (p->oprmode != -1) break; 04859 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 04860 { 04861 /* Make sure it starts ringing */ 04862 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 04863 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING); 04864 save_conference(p->oprpeer); 04865 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04866 } 04867 break; 04868 } 04869 switch (p->sig) { 04870 case SIG_FXOLS: 04871 case SIG_FXOGS: 04872 case SIG_FXOKS: 04873 p->onhooktime = time(NULL); 04874 p->msgstate = -1; 04875 /* Check for some special conditions regarding call waiting */ 04876 if (idx == SUB_REAL) { 04877 /* The normal line was hung up */ 04878 if (p->subs[SUB_CALLWAIT].owner) { 04879 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */ 04880 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 04881 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel); 04882 unalloc_sub(p, SUB_CALLWAIT); 04883 #if 0 04884 p->subs[idx].needanswer = 0; 04885 p->subs[idx].needringing = 0; 04886 #endif 04887 p->callwaitingrepeat = 0; 04888 p->cidcwexpire = 0; 04889 p->owner = NULL; 04890 /* Don't start streaming audio yet if the incoming call isn't up yet */ 04891 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP) 04892 p->dialing = 1; 04893 dahdi_ring_phone(p); 04894 } else if (p->subs[SUB_THREEWAY].owner) { 04895 unsigned int mssinceflash; 04896 /* Here we have to retain the lock on both the main channel, the 3-way channel, and 04897 the private structure -- not especially easy or clean */ 04898 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) { 04899 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */ 04900 DLA_UNLOCK(&p->lock); 04901 CHANNEL_DEADLOCK_AVOIDANCE(ast); 04902 /* We can grab ast and p in that order, without worry. We should make sure 04903 nothing seriously bad has happened though like some sort of bizarre double 04904 masquerade! */ 04905 DLA_LOCK(&p->lock); 04906 if (p->owner != ast) { 04907 ast_log(LOG_WARNING, "This isn't good...\n"); 04908 return NULL; 04909 } 04910 } 04911 if (!p->subs[SUB_THREEWAY].owner) { 04912 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n"); 04913 return NULL; 04914 } 04915 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime); 04916 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash); 04917 if (mssinceflash < MIN_MS_SINCE_FLASH) { 04918 /* It hasn't been long enough since the last flashook. This is probably a bounce on 04919 hanging up. Hangup both channels now */ 04920 if (p->subs[SUB_THREEWAY].owner) 04921 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER); 04922 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04923 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel); 04924 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04925 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) { 04926 if (p->transfer) { 04927 /* In any case this isn't a threeway call anymore */ 04928 p->subs[SUB_REAL].inthreeway = 0; 04929 p->subs[SUB_THREEWAY].inthreeway = 0; 04930 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */ 04931 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) { 04932 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04933 /* Swap subs and dis-own channel */ 04934 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04935 p->owner = NULL; 04936 /* Ring the phone */ 04937 dahdi_ring_phone(p); 04938 } else { 04939 if ((res = attempt_transfer(p)) < 0) { 04940 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04941 if (p->subs[SUB_THREEWAY].owner) 04942 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04943 } else if (res) { 04944 /* Don't actually hang up at this point */ 04945 if (p->subs[SUB_THREEWAY].owner) 04946 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04947 break; 04948 } 04949 } 04950 } else { 04951 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04952 if (p->subs[SUB_THREEWAY].owner) 04953 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04954 } 04955 } else { 04956 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04957 /* Swap subs and dis-own channel */ 04958 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04959 p->owner = NULL; 04960 /* Ring the phone */ 04961 dahdi_ring_phone(p); 04962 } 04963 } 04964 } else { 04965 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx); 04966 } 04967 /* Fall through */ 04968 default: 04969 dahdi_disable_ec(p); 04970 return NULL; 04971 } 04972 break; 04973 case DAHDI_EVENT_RINGOFFHOOK: 04974 if (p->inalarm) break; 04975 if (p->oprmode < 0) 04976 { 04977 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 04978 { 04979 /* Make sure it stops ringing */ 04980 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 04981 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1); 04982 restore_conference(p->oprpeer); 04983 } 04984 break; 04985 } 04986 if (p->radio) 04987 { 04988 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04989 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY; 04990 break; 04991 } 04992 /* for E911, its supposed to wait for offhook then dial 04993 the second half of the dial string */ 04994 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) { 04995 c = strchr(p->dialdest, '/'); 04996 if (c) 04997 c++; 04998 else 04999 c = p->dialdest; 05000 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c); 05001 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr)); 05002 if (strlen(p->dop.dialstr) > 4) { 05003 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 05004 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 05005 p->echorest[sizeof(p->echorest) - 1] = '\0'; 05006 p->echobreak = 1; 05007 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 05008 } else 05009 p->echobreak = 0; 05010 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 05011 int saveerr = errno; 05012 05013 x = DAHDI_ONHOOK; 05014 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 05015 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 05016 return NULL; 05017 } 05018 p->dialing = 1; 05019 return &p->subs[idx].f; 05020 } 05021 switch (p->sig) { 05022 case SIG_FXOLS: 05023 case SIG_FXOGS: 05024 case SIG_FXOKS: 05025 switch (ast->_state) { 05026 case AST_STATE_RINGING: 05027 dahdi_enable_ec(p); 05028 dahdi_train_ec(p); 05029 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05030 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 05031 /* Make sure it stops ringing */ 05032 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 05033 ast_debug(1, "channel %d answered\n", p->channel); 05034 if (p->cidspill) { 05035 /* Cancel any running CallerID spill */ 05036 ast_free(p->cidspill); 05037 p->cidspill = NULL; 05038 } 05039 p->dialing = 0; 05040 p->callwaitcas = 0; 05041 if (p->confirmanswer) { 05042 /* Ignore answer if "confirm answer" is enabled */ 05043 p->subs[idx].f.frametype = AST_FRAME_NULL; 05044 p->subs[idx].f.subclass = 0; 05045 } else if (!ast_strlen_zero(p->dop.dialstr)) { 05046 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ 05047 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05048 if (res < 0) { 05049 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05050 p->dop.dialstr[0] = '\0'; 05051 return NULL; 05052 } else { 05053 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr); 05054 p->subs[idx].f.frametype = AST_FRAME_NULL; 05055 p->subs[idx].f.subclass = 0; 05056 p->dialing = 1; 05057 } 05058 p->dop.dialstr[0] = '\0'; 05059 ast_setstate(ast, AST_STATE_DIALING); 05060 } else 05061 ast_setstate(ast, AST_STATE_UP); 05062 return &p->subs[idx].f; 05063 case AST_STATE_DOWN: 05064 ast_setstate(ast, AST_STATE_RING); 05065 ast->rings = 1; 05066 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05067 p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK; 05068 ast_debug(1, "channel %d picked up\n", p->channel); 05069 return &p->subs[idx].f; 05070 case AST_STATE_UP: 05071 /* Make sure it stops ringing */ 05072 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 05073 /* Okay -- probably call waiting*/ 05074 if (ast_bridged_channel(p->owner)) 05075 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05076 p->subs[idx].needunhold = 1; 05077 break; 05078 case AST_STATE_RESERVED: 05079 /* Start up dialtone */ 05080 if (has_voicemail(p)) 05081 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 05082 else 05083 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 05084 break; 05085 default: 05086 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state); 05087 } 05088 break; 05089 case SIG_FXSLS: 05090 case SIG_FXSGS: 05091 case SIG_FXSKS: 05092 if (ast->_state == AST_STATE_RING) { 05093 p->ringt = p->ringt_base; 05094 } 05095 05096 /* If we get a ring then we cannot be in 05097 * reversed polarity. So we reset to idle */ 05098 ast_debug(1, "Setting IDLE polarity due " 05099 "to ring. Old polarity was %d\n", 05100 p->polarity); 05101 p->polarity = POLARITY_IDLE; 05102 05103 /* Fall through */ 05104 case SIG_EM: 05105 case SIG_EM_E1: 05106 case SIG_EMWINK: 05107 case SIG_FEATD: 05108 case SIG_FEATDMF: 05109 case SIG_FEATDMF_TA: 05110 case SIG_E911: 05111 case SIG_FGC_CAMA: 05112 case SIG_FGC_CAMAMF: 05113 case SIG_FEATB: 05114 case SIG_SF: 05115 case SIG_SFWINK: 05116 case SIG_SF_FEATD: 05117 case SIG_SF_FEATDMF: 05118 case SIG_SF_FEATB: 05119 if (ast->_state == AST_STATE_PRERING) 05120 ast_setstate(ast, AST_STATE_RING); 05121 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) { 05122 ast_debug(1, "Ring detected\n"); 05123 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05124 p->subs[idx].f.subclass = AST_CONTROL_RING; 05125 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) { 05126 ast_debug(1, "Line answered\n"); 05127 if (p->confirmanswer) { 05128 p->subs[idx].f.frametype = AST_FRAME_NULL; 05129 p->subs[idx].f.subclass = 0; 05130 } else { 05131 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05132 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 05133 ast_setstate(ast, AST_STATE_UP); 05134 } 05135 } else if (ast->_state != AST_STATE_RING) 05136 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel); 05137 break; 05138 default: 05139 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 05140 } 05141 break; 05142 case DAHDI_EVENT_RINGBEGIN: 05143 switch (p->sig) { 05144 case SIG_FXSLS: 05145 case SIG_FXSGS: 05146 case SIG_FXSKS: 05147 if (ast->_state == AST_STATE_RING) { 05148 p->ringt = p->ringt_base; 05149 } 05150 break; 05151 } 05152 break; 05153 case DAHDI_EVENT_RINGEROFF: 05154 if (p->inalarm) break; 05155 if ((p->radio || (p->oprmode < 0))) break; 05156 ast->rings++; 05157 if ((ast->rings > p->cidrings) && (p->cidspill)) { 05158 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n"); 05159 ast_free(p->cidspill); 05160 p->cidspill = NULL; 05161 p->callwaitcas = 0; 05162 } 05163 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05164 p->subs[idx].f.subclass = AST_CONTROL_RINGING; 05165 break; 05166 case DAHDI_EVENT_RINGERON: 05167 break; 05168 case DAHDI_EVENT_NOALARM: 05169 p->inalarm = 0; 05170 #ifdef HAVE_PRI 05171 /* Extremely unlikely but just in case */ 05172 if (p->bearer) 05173 p->bearer->inalarm = 0; 05174 #endif 05175 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 05176 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 05177 "Channel: %d\r\n", p->channel); 05178 break; 05179 case DAHDI_EVENT_WINKFLASH: 05180 if (p->inalarm) break; 05181 if (p->radio) break; 05182 if (p->oprmode < 0) break; 05183 if (p->oprmode > 1) 05184 { 05185 struct dahdi_params par; 05186 05187 memset(&par, 0, sizeof(par)); 05188 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1) 05189 { 05190 if (!par.rxisoffhook) 05191 { 05192 /* Make sure it stops ringing */ 05193 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 05194 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING); 05195 save_conference(p); 05196 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05197 } 05198 } 05199 break; 05200 } 05201 /* Remember last time we got a flash-hook */ 05202 p->flashtime = ast_tvnow(); 05203 switch (mysig) { 05204 case SIG_FXOLS: 05205 case SIG_FXOGS: 05206 case SIG_FXOKS: 05207 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n", 05208 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 05209 p->callwaitcas = 0; 05210 05211 if (idx != SUB_REAL) { 05212 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel); 05213 goto winkflashdone; 05214 } 05215 05216 if (p->subs[SUB_CALLWAIT].owner) { 05217 /* Swap to call-wait */ 05218 swap_subs(p, SUB_REAL, SUB_CALLWAIT); 05219 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 05220 p->owner = p->subs[SUB_REAL].owner; 05221 ast_debug(1, "Making %s the new owner\n", p->owner->name); 05222 if (p->owner->_state == AST_STATE_RINGING) { 05223 ast_setstate(p->owner, AST_STATE_UP); 05224 p->subs[SUB_REAL].needanswer = 1; 05225 } 05226 p->callwaitingrepeat = 0; 05227 p->cidcwexpire = 0; 05228 /* Start music on hold if appropriate */ 05229 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 05230 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 05231 S_OR(p->mohsuggest, NULL), 05232 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05233 } 05234 p->subs[SUB_CALLWAIT].needhold = 1; 05235 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 05236 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD, 05237 S_OR(p->mohsuggest, NULL), 05238 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05239 } 05240 p->subs[SUB_REAL].needunhold = 1; 05241 } else if (!p->subs[SUB_THREEWAY].owner) { 05242 if (!p->threewaycalling) { 05243 /* Just send a flash if no 3-way calling */ 05244 p->subs[SUB_REAL].needflash = 1; 05245 goto winkflashdone; 05246 } else if (!check_for_conference(p)) { 05247 char cid_num[256]; 05248 char cid_name[256]; 05249 05250 cid_num[0] = 0; 05251 cid_name[0] = 0; 05252 if (p->dahditrcallerid && p->owner) { 05253 if (p->owner->cid.cid_num) 05254 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num)); 05255 if (p->owner->cid.cid_name) 05256 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name)); 05257 } 05258 /* XXX This section needs much more error checking!!! XXX */ 05259 /* Start a 3-way call if feasible */ 05260 if (!((ast->pbx) || 05261 (ast->_state == AST_STATE_UP) || 05262 (ast->_state == AST_STATE_RING))) { 05263 ast_debug(1, "Flash when call not up or ringing\n"); 05264 goto winkflashdone; 05265 } 05266 if (alloc_sub(p, SUB_THREEWAY)) { 05267 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n"); 05268 goto winkflashdone; 05269 } 05270 /* Make new channel */ 05271 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0); 05272 if (p->dahditrcallerid) { 05273 if (!p->origcid_num) 05274 p->origcid_num = ast_strdup(p->cid_num); 05275 if (!p->origcid_name) 05276 p->origcid_name = ast_strdup(p->cid_name); 05277 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num)); 05278 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name)); 05279 } 05280 /* Swap things around between the three-way and real call */ 05281 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05282 /* Disable echo canceller for better dialing */ 05283 dahdi_disable_ec(p); 05284 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL); 05285 if (res) 05286 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel); 05287 p->owner = chan; 05288 if (!chan) { 05289 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel); 05290 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 05291 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel); 05292 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 05293 dahdi_enable_ec(p); 05294 ast_hangup(chan); 05295 } else { 05296 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 05297 int way3bridge = 0, cdr3way = 0; 05298 05299 if (!other) { 05300 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 05301 } else 05302 way3bridge = 1; 05303 05304 if (p->subs[SUB_THREEWAY].owner->cdr) 05305 cdr3way = 1; 05306 05307 ast_verb(3, "Started three way call on channel %d\n", p->channel); 05308 05309 /* Start music on hold if appropriate */ 05310 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 05311 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 05312 S_OR(p->mohsuggest, NULL), 05313 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05314 } 05315 p->subs[SUB_THREEWAY].needhold = 1; 05316 } 05317 } 05318 } else { 05319 /* Already have a 3 way call */ 05320 if (p->subs[SUB_THREEWAY].inthreeway) { 05321 /* Call is already up, drop the last person */ 05322 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel); 05323 /* If the primary call isn't answered yet, use it */ 05324 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) { 05325 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/ 05326 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05327 p->owner = p->subs[SUB_REAL].owner; 05328 } 05329 /* Drop the last call and stop the conference */ 05330 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name); 05331 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05332 p->subs[SUB_REAL].inthreeway = 0; 05333 p->subs[SUB_THREEWAY].inthreeway = 0; 05334 } else { 05335 /* Lets see what we're up to */ 05336 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 05337 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) { 05338 int otherindex = SUB_THREEWAY; 05339 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 05340 int way3bridge = 0, cdr3way = 0; 05341 05342 if (!other) { 05343 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 05344 } else 05345 way3bridge = 1; 05346 05347 if (p->subs[SUB_THREEWAY].owner->cdr) 05348 cdr3way = 1; 05349 05350 ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name); 05351 /* Put them in the threeway, and flip */ 05352 p->subs[SUB_THREEWAY].inthreeway = 1; 05353 p->subs[SUB_REAL].inthreeway = 1; 05354 if (ast->_state == AST_STATE_UP) { 05355 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05356 otherindex = SUB_REAL; 05357 } 05358 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner)) 05359 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD); 05360 p->subs[otherindex].needunhold = 1; 05361 p->owner = p->subs[SUB_REAL].owner; 05362 if (ast->_state == AST_STATE_RINGING) { 05363 ast_debug(1, "Enabling ringtone on real and threeway\n"); 05364 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05365 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 05366 } 05367 } else { 05368 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name); 05369 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05370 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05371 p->owner = p->subs[SUB_REAL].owner; 05372 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner)) 05373 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 05374 p->subs[SUB_REAL].needunhold = 1; 05375 dahdi_enable_ec(p); 05376 } 05377 05378 } 05379 } 05380 winkflashdone: 05381 update_conf(p); 05382 break; 05383 case SIG_EM: 05384 case SIG_EM_E1: 05385 case SIG_EMWINK: 05386 case SIG_FEATD: 05387 case SIG_SF: 05388 case SIG_SFWINK: 05389 case SIG_SF_FEATD: 05390 case SIG_FXSLS: 05391 case SIG_FXSGS: 05392 if (option_debug) { 05393 if (p->dialing) 05394 ast_debug(1, "Ignoring wink on channel %d\n", p->channel); 05395 else 05396 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel); 05397 } 05398 break; 05399 case SIG_FEATDMF_TA: 05400 switch (p->whichwink) { 05401 case 0: 05402 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 05403 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 05404 break; 05405 case 1: 05406 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr)); 05407 break; 05408 case 2: 05409 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n"); 05410 return NULL; 05411 } 05412 p->whichwink++; 05413 /* Fall through */ 05414 case SIG_FEATDMF: 05415 case SIG_E911: 05416 case SIG_FGC_CAMAMF: 05417 case SIG_FGC_CAMA: 05418 case SIG_FEATB: 05419 case SIG_SF_FEATDMF: 05420 case SIG_SF_FEATB: 05421 /* FGD MF *Must* wait for wink */ 05422 if (!ast_strlen_zero(p->dop.dialstr)) { 05423 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05424 if (res < 0) { 05425 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05426 p->dop.dialstr[0] = '\0'; 05427 return NULL; 05428 } else 05429 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 05430 } 05431 p->dop.dialstr[0] = '\0'; 05432 break; 05433 default: 05434 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig); 05435 } 05436 break; 05437 case DAHDI_EVENT_HOOKCOMPLETE: 05438 if (p->inalarm) break; 05439 if ((p->radio || (p->oprmode < 0))) break; 05440 switch (mysig) { 05441 case SIG_FXSLS: /* only interesting for FXS */ 05442 case SIG_FXSGS: 05443 case SIG_FXSKS: 05444 case SIG_EM: 05445 case SIG_EM_E1: 05446 case SIG_EMWINK: 05447 case SIG_FEATD: 05448 case SIG_SF: 05449 case SIG_SFWINK: 05450 case SIG_SF_FEATD: 05451 if (!ast_strlen_zero(p->dop.dialstr)) { 05452 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05453 if (res < 0) { 05454 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05455 p->dop.dialstr[0] = '\0'; 05456 return NULL; 05457 } else 05458 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 05459 } 05460 p->dop.dialstr[0] = '\0'; 05461 p->dop.op = DAHDI_DIAL_OP_REPLACE; 05462 break; 05463 case SIG_FEATDMF: 05464 case SIG_FEATDMF_TA: 05465 case SIG_E911: 05466 case SIG_FGC_CAMA: 05467 case SIG_FGC_CAMAMF: 05468 case SIG_FEATB: 05469 case SIG_SF_FEATDMF: 05470 case SIG_SF_FEATB: 05471 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel); 05472 break; 05473 default: 05474 break; 05475 } 05476 break; 05477 case DAHDI_EVENT_POLARITY: 05478 /* 05479 * If we get a Polarity Switch event, check to see 05480 * if we should change the polarity state and 05481 * mark the channel as UP or if this is an indication 05482 * of remote end disconnect. 05483 */ 05484 if (p->polarity == POLARITY_IDLE) { 05485 p->polarity = POLARITY_REV; 05486 if (p->answeronpolarityswitch && 05487 ((ast->_state == AST_STATE_DIALING) || 05488 (ast->_state == AST_STATE_RINGING))) { 05489 ast_debug(1, "Answering on polarity switch!\n"); 05490 ast_setstate(p->owner, AST_STATE_UP); 05491 if (p->hanguponpolarityswitch) { 05492 p->polaritydelaytv = ast_tvnow(); 05493 } 05494 } else 05495 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state); 05496 05497 } 05498 /* Removed else statement from here as it was preventing hangups from ever happening*/ 05499 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */ 05500 if (p->hanguponpolarityswitch && 05501 (p->polarityonanswerdelay > 0) && 05502 (p->polarity == POLARITY_REV) && 05503 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) { 05504 /* Added log_debug information below to provide a better indication of what is going on */ 05505 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) ); 05506 05507 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) { 05508 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel); 05509 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 05510 p->polarity = POLARITY_IDLE; 05511 } else 05512 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); 05513 05514 } else { 05515 p->polarity = POLARITY_IDLE; 05516 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state); 05517 } 05518 /* Added more log_debug information below to provide a better indication of what is going on */ 05519 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) ); 05520 break; 05521 default: 05522 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel); 05523 } 05524 return &p->subs[idx].f; 05525 }
static int dahdi_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3391 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_free(), ast_dsp_set_digitmode(), 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, dahdi_pvt::muting, 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().
03392 { 03393 int res; 03394 int idx,x, law; 03395 /*static int restore_gains(struct dahdi_pvt *p);*/ 03396 struct dahdi_pvt *p = ast->tech_pvt; 03397 struct dahdi_pvt *tmp = NULL; 03398 struct dahdi_pvt *prev = NULL; 03399 struct dahdi_params par; 03400 03401 ast_debug(1, "dahdi_hangup(%s)\n", ast->name); 03402 if (!ast->tech_pvt) { 03403 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 03404 return 0; 03405 } 03406 03407 ast_mutex_lock(&p->lock); 03408 03409 idx = dahdi_get_index(ast, p, 1); 03410 03411 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 03412 x = 1; 03413 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 03414 } 03415 03416 x = 0; 03417 dahdi_confmute(p, 0); 03418 p->muting = 0; 03419 restore_gains(p); 03420 if (p->origcid_num) { 03421 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num)); 03422 ast_free(p->origcid_num); 03423 p->origcid_num = NULL; 03424 } 03425 if (p->origcid_name) { 03426 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name)); 03427 ast_free(p->origcid_name); 03428 p->origcid_name = NULL; 03429 } 03430 if (p->dsp) 03431 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 03432 p->exten[0] = '\0'; 03433 03434 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n", 03435 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 03436 p->ignoredtmf = 0; 03437 03438 if (idx > -1) { 03439 /* Real channel, do some fixup */ 03440 p->subs[idx].owner = NULL; 03441 p->subs[idx].needanswer = 0; 03442 p->subs[idx].needflash = 0; 03443 p->subs[idx].needringing = 0; 03444 p->subs[idx].needbusy = 0; 03445 p->subs[idx].needcongestion = 0; 03446 p->subs[idx].linear = 0; 03447 p->subs[idx].needcallerid = 0; 03448 p->polarity = POLARITY_IDLE; 03449 dahdi_setlinear(p->subs[idx].dfd, 0); 03450 if (idx == SUB_REAL) { 03451 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) { 03452 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n"); 03453 if (p->subs[SUB_CALLWAIT].inthreeway) { 03454 /* We had flipped over to answer a callwait and now it's gone */ 03455 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n"); 03456 /* Move to the call-wait, but un-own us until they flip back. */ 03457 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03458 unalloc_sub(p, SUB_CALLWAIT); 03459 p->owner = NULL; 03460 } else { 03461 /* The three way hung up, but we still have a call wait */ 03462 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n"); 03463 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03464 unalloc_sub(p, SUB_THREEWAY); 03465 if (p->subs[SUB_REAL].inthreeway) { 03466 /* This was part of a three way call. Immediately make way for 03467 another call */ 03468 ast_debug(1, "Call was complete, setting owner to former third call\n"); 03469 p->owner = p->subs[SUB_REAL].owner; 03470 } else { 03471 /* This call hasn't been completed yet... Set owner to NULL */ 03472 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 03473 p->owner = NULL; 03474 } 03475 p->subs[SUB_REAL].inthreeway = 0; 03476 } 03477 } else if (p->subs[SUB_CALLWAIT].dfd > -1) { 03478 /* Move to the call-wait and switch back to them. */ 03479 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03480 unalloc_sub(p, SUB_CALLWAIT); 03481 p->owner = p->subs[SUB_REAL].owner; 03482 if (p->owner->_state != AST_STATE_UP) 03483 p->subs[SUB_REAL].needanswer = 1; 03484 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 03485 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 03486 } else if (p->subs[SUB_THREEWAY].dfd > -1) { 03487 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03488 unalloc_sub(p, SUB_THREEWAY); 03489 if (p->subs[SUB_REAL].inthreeway) { 03490 /* This was part of a three way call. Immediately make way for 03491 another call */ 03492 ast_debug(1, "Call was complete, setting owner to former third call\n"); 03493 p->owner = p->subs[SUB_REAL].owner; 03494 } else { 03495 /* This call hasn't been completed yet... Set owner to NULL */ 03496 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 03497 p->owner = NULL; 03498 } 03499 p->subs[SUB_REAL].inthreeway = 0; 03500 } 03501 } else if (idx == SUB_CALLWAIT) { 03502 /* Ditch the holding callwait call, and immediately make it availabe */ 03503 if (p->subs[SUB_CALLWAIT].inthreeway) { 03504 /* This is actually part of a three way, placed on hold. Place the third part 03505 on music on hold now */ 03506 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 03507 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 03508 S_OR(p->mohsuggest, NULL), 03509 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 03510 } 03511 p->subs[SUB_THREEWAY].inthreeway = 0; 03512 /* Make it the call wait now */ 03513 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 03514 unalloc_sub(p, SUB_THREEWAY); 03515 } else 03516 unalloc_sub(p, SUB_CALLWAIT); 03517 } else if (idx == SUB_THREEWAY) { 03518 if (p->subs[SUB_CALLWAIT].inthreeway) { 03519 /* The other party of the three way call is currently in a call-wait state. 03520 Start music on hold for them, and take the main guy out of the third call */ 03521 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 03522 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 03523 S_OR(p->mohsuggest, NULL), 03524 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 03525 } 03526 p->subs[SUB_CALLWAIT].inthreeway = 0; 03527 } 03528 p->subs[SUB_REAL].inthreeway = 0; 03529 /* If this was part of a three way call index, let us make 03530 another three way call */ 03531 unalloc_sub(p, SUB_THREEWAY); 03532 } else { 03533 /* This wasn't any sort of call, but how are we an index? */ 03534 ast_log(LOG_WARNING, "Index found but not any type of call?\n"); 03535 } 03536 } 03537 03538 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 03539 p->owner = NULL; 03540 p->ringt = 0; 03541 p->distinctivering = 0; 03542 p->confirmanswer = 0; 03543 p->cidrings = 1; 03544 p->outgoing = 0; 03545 p->digital = 0; 03546 p->faxhandled = 0; 03547 p->pulsedial = 0; 03548 p->onhooktime = time(NULL); 03549 #if defined(HAVE_PRI) || defined(HAVE_SS7) 03550 p->proceeding = 0; 03551 p->dialing = 0; 03552 p->progress = 0; 03553 p->alerting = 0; 03554 p->setup_ack = 0; 03555 p->rlt = 0; 03556 #endif 03557 if (p->dsp) { 03558 ast_dsp_free(p->dsp); 03559 p->dsp = NULL; 03560 } 03561 03562 law = DAHDI_LAW_DEFAULT; 03563 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 03564 if (res < 0) 03565 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 03566 /* Perform low level hangup if no owner left */ 03567 #ifdef HAVE_SS7 03568 if (p->ss7) { 03569 if (p->ss7call) { 03570 if (!ss7_grab(p, p->ss7)) { 03571 if (!p->alreadyhungup) { 03572 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE"); 03573 int icause = ast->hangupcause ? ast->hangupcause : -1; 03574 03575 if (cause) { 03576 if (atoi(cause)) 03577 icause = atoi(cause); 03578 } 03579 isup_rel(p->ss7->ss7, p->ss7call, icause); 03580 ss7_rel(p->ss7); 03581 p->alreadyhungup = 1; 03582 } else 03583 ast_log(LOG_WARNING, "Trying to hangup twice!\n"); 03584 } else { 03585 ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic); 03586 res = -1; 03587 } 03588 } 03589 } 03590 #endif 03591 #ifdef HAVE_PRI 03592 if (p->pri) { 03593 #ifdef SUPPORT_USERUSER 03594 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO"); 03595 #endif 03596 03597 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */ 03598 if (p->call && (!p->bearer || (p->bearer->call == p->call))) { 03599 if (!pri_grab(p, p->pri)) { 03600 if (p->alreadyhungup) { 03601 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n"); 03602 03603 #ifdef SUPPORT_USERUSER 03604 pri_call_set_useruser(p->call, useruser); 03605 #endif 03606 03607 pri_hangup(p->pri->pri, p->call, -1); 03608 p->call = NULL; 03609 if (p->bearer) 03610 p->bearer->call = NULL; 03611 } else { 03612 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE"); 03613 int icause = ast->hangupcause ? ast->hangupcause : -1; 03614 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n"); 03615 03616 #ifdef SUPPORT_USERUSER 03617 pri_call_set_useruser(p->call, useruser); 03618 #endif 03619 03620 p->alreadyhungup = 1; 03621 if (p->bearer) 03622 p->bearer->alreadyhungup = 1; 03623 if (cause) { 03624 if (atoi(cause)) 03625 icause = atoi(cause); 03626 } 03627 pri_hangup(p->pri->pri, p->call, icause); 03628 } 03629 if (res < 0) 03630 ast_log(LOG_WARNING, "pri_disconnect failed\n"); 03631 pri_rel(p->pri); 03632 } else { 03633 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 03634 res = -1; 03635 } 03636 } else { 03637 if (p->bearer) 03638 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call); 03639 p->call = NULL; 03640 res = 0; 03641 } 03642 } 03643 #endif 03644 if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7) && (p->sig != SIG_BRI) && (p->sig != SIG_BRI_PTMP))) 03645 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 03646 if (res < 0) { 03647 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name); 03648 } 03649 switch (p->sig) { 03650 case SIG_FXOGS: 03651 case SIG_FXOLS: 03652 case SIG_FXOKS: 03653 memset(&par, 0, sizeof(par)); 03654 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 03655 if (!res) { 03656 #if 0 03657 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook); 03658 #endif 03659 /* If they're off hook, try playing congestion */ 03660 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0)))) 03661 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 03662 else 03663 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03664 } 03665 break; 03666 case SIG_FXSGS: 03667 case SIG_FXSLS: 03668 case SIG_FXSKS: 03669 /* Make sure we're not made available for at least two seconds assuming 03670 we were actually used for an inbound or outbound call. */ 03671 if (ast->_state != AST_STATE_RESERVED) { 03672 time(&p->guardtime); 03673 p->guardtime += 2; 03674 } 03675 break; 03676 default: 03677 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03678 } 03679 if (p->cidspill) 03680 ast_free(p->cidspill); 03681 if (p->sig) 03682 dahdi_disable_ec(p); 03683 x = 0; 03684 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); 03685 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0); 03686 p->didtdd = 0; 03687 p->cidspill = NULL; 03688 p->callwaitcas = 0; 03689 p->callwaiting = p->permcallwaiting; 03690 p->hidecallerid = p->permhidecallerid; 03691 p->dialing = 0; 03692 p->rdnis[0] = '\0'; 03693 update_conf(p); 03694 reset_conf(p); 03695 /* Restore data mode */ 03696 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 03697 x = 0; 03698 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 03699 } 03700 #ifdef HAVE_PRI 03701 if (p->bearer) { 03702 ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel); 03703 /* Free up the bearer channel as well, and 03704 don't use its file descriptor anymore */ 03705 update_conf(p->bearer); 03706 reset_conf(p->bearer); 03707 p->bearer->owner = NULL; 03708 p->bearer->realcall = NULL; 03709 p->bearer = NULL; 03710 p->subs[SUB_REAL].dfd = -1; 03711 p->pri = NULL; 03712 } 03713 #endif 03714 if (num_restart_pending == 0) 03715 restart_monitor(); 03716 } 03717 03718 p->callwaitingrepeat = 0; 03719 p->cidcwexpire = 0; 03720 p->oprmode = 0; 03721 ast->tech_pvt = NULL; 03722 ast_mutex_unlock(&p->lock); 03723 ast_module_unref(ast_module_info->self); 03724 ast_verb(3, "Hungup '%s'\n", ast->name); 03725 03726 ast_mutex_lock(&iflock); 03727 03728 if (p->restartpending) { 03729 num_restart_pending--; 03730 } 03731 03732 tmp = iflist; 03733 prev = NULL; 03734 if (p->destroy) { 03735 while (tmp) { 03736 if (tmp == p) { 03737 destroy_channel(prev, tmp, 0); 03738 break; 03739 } else { 03740 prev = tmp; 03741 tmp = tmp->next; 03742 } 03743 } 03744 } 03745 ast_mutex_unlock(&iflock); 03746 return 0; 03747 }
static int dahdi_indicate | ( | struct ast_channel * | chan, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 6047 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.
06048 { 06049 struct dahdi_pvt *p = chan->tech_pvt; 06050 int res=-1; 06051 int idx; 06052 int func = DAHDI_FLASH; 06053 ast_mutex_lock(&p->lock); 06054 idx = dahdi_get_index(chan, p, 0); 06055 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name); 06056 if (idx == SUB_REAL) { 06057 switch (condition) { 06058 case AST_CONTROL_BUSY: 06059 #ifdef HAVE_PRI 06060 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) { 06061 chan->hangupcause = AST_CAUSE_USER_BUSY; 06062 chan->_softhangup |= AST_SOFTHANGUP_DEV; 06063 res = 0; 06064 } else if (!p->progress && 06065 ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06066 && p->pri && !p->outgoing) { 06067 if (p->pri->pri) { 06068 if (!pri_grab(p, p->pri)) { 06069 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06070 pri_rel(p->pri); 06071 } 06072 else 06073 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06074 } 06075 p->progress = 1; 06076 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY); 06077 } else 06078 #endif 06079 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY); 06080 break; 06081 case AST_CONTROL_RINGING: 06082 #ifdef HAVE_PRI 06083 if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06084 && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) { 06085 if (p->pri->pri) { 06086 if (!pri_grab(p, p->pri)) { 06087 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06088 pri_rel(p->pri); 06089 } 06090 else 06091 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06092 } 06093 p->alerting = 1; 06094 } 06095 06096 #endif 06097 #ifdef HAVE_SS7 06098 if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) { 06099 if (p->ss7->ss7) { 06100 ss7_grab(p, p->ss7); 06101 06102 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) 06103 p->rlt = 1; 06104 if (p->rlt != 1) /* No need to send CPG if call will be RELEASE */ 06105 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING); 06106 p->alerting = 1; 06107 ss7_rel(p->ss7); 06108 } 06109 } 06110 #endif 06111 06112 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE); 06113 06114 if (chan->_state != AST_STATE_UP) { 06115 if ((chan->_state != AST_STATE_RING) || 06116 ((p->sig != SIG_FXSKS) && 06117 (p->sig != SIG_FXSLS) && 06118 (p->sig != SIG_FXSGS))) 06119 ast_setstate(chan, AST_STATE_RINGING); 06120 } 06121 break; 06122 case AST_CONTROL_PROCEEDING: 06123 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name); 06124 #ifdef HAVE_PRI 06125 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06126 && p->pri && !p->outgoing) { 06127 if (p->pri->pri) { 06128 if (!pri_grab(p, p->pri)) { 06129 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06130 pri_rel(p->pri); 06131 } 06132 else 06133 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06134 } 06135 p->proceeding = 1; 06136 p->dialing = 0; 06137 } 06138 #endif 06139 #ifdef HAVE_SS7 06140 /* This IF sends the FAR for an answered ALEG call */ 06141 if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){ 06142 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) 06143 p->rlt = 1; 06144 } 06145 06146 if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) { 06147 if (p->ss7->ss7) { 06148 ss7_grab(p, p->ss7); 06149 isup_acm(p->ss7->ss7, p->ss7call); 06150 p->proceeding = 1; 06151 ss7_rel(p->ss7); 06152 06153 } 06154 } 06155 #endif 06156 /* don't continue in ast_indicate */ 06157 res = 0; 06158 break; 06159 case AST_CONTROL_PROGRESS: 06160 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name); 06161 #ifdef HAVE_PRI 06162 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */ 06163 if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06164 && p->pri && !p->outgoing) { 06165 if (p->pri->pri) { 06166 if (!pri_grab(p, p->pri)) { 06167 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06168 pri_rel(p->pri); 06169 } 06170 else 06171 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06172 } 06173 p->progress = 1; 06174 } 06175 #endif 06176 #ifdef HAVE_SS7 06177 if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) { 06178 if (p->ss7->ss7) { 06179 ss7_grab(p, p->ss7); 06180 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO); 06181 p->progress = 1; 06182 ss7_rel(p->ss7); 06183 /* enable echo canceler here on SS7 calls */ 06184 dahdi_enable_ec(p); 06185 06186 } 06187 } 06188 #endif 06189 /* don't continue in ast_indicate */ 06190 res = 0; 06191 break; 06192 case AST_CONTROL_CONGESTION: 06193 chan->hangupcause = AST_CAUSE_CONGESTION; 06194 #ifdef HAVE_PRI 06195 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) { 06196 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 06197 chan->_softhangup |= AST_SOFTHANGUP_DEV; 06198 res = 0; 06199 } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06200 && p->pri && !p->outgoing) { 06201 if (p->pri) { 06202 if (!pri_grab(p, p->pri)) { 06203 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06204 pri_rel(p->pri); 06205 } else 06206 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06207 } 06208 p->progress = 1; 06209 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06210 } else 06211 #endif 06212 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06213 break; 06214 case AST_CONTROL_HOLD: 06215 #ifdef HAVE_PRI 06216 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 06217 if (!pri_grab(p, p->pri)) { 06218 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD); 06219 pri_rel(p->pri); 06220 } else 06221 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06222 } else 06223 #endif 06224 ast_moh_start(chan, data, p->mohinterpret); 06225 break; 06226 case AST_CONTROL_UNHOLD: 06227 #ifdef HAVE_PRI 06228 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 06229 if (!pri_grab(p, p->pri)) { 06230 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL); 06231 pri_rel(p->pri); 06232 } else 06233 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06234 } else 06235 #endif 06236 ast_moh_stop(chan); 06237 break; 06238 case AST_CONTROL_RADIO_KEY: 06239 if (p->radio) 06240 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 06241 res = 0; 06242 break; 06243 case AST_CONTROL_RADIO_UNKEY: 06244 if (p->radio) 06245 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF); 06246 res = 0; 06247 break; 06248 case AST_CONTROL_FLASH: 06249 /* flash hookswitch */ 06250 if (ISTRUNK(p) && (p->sig != SIG_PRI)) { 06251 /* Clear out the dial buffer */ 06252 p->dop.dialstr[0] = '\0'; 06253 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 06254 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 06255 chan->name, strerror(errno)); 06256 } else 06257 res = 0; 06258 } else 06259 res = 0; 06260 break; 06261 case AST_CONTROL_SRCUPDATE: 06262 res = 0; 06263 break; 06264 case -1: 06265 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 06266 break; 06267 } 06268 } else 06269 res = 0; 06270 ast_mutex_unlock(&p->lock); 06271 return res; 06272 }
Definition at line 4105 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and master.
Referenced by dahdi_bridge().
04105 { 04106 int x; 04107 if (!slave || !master) { 04108 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n"); 04109 return; 04110 } 04111 for (x = 0; x < MAX_SLAVES; x++) { 04112 if (!master->slaves[x]) { 04113 master->slaves[x] = slave; 04114 break; 04115 } 04116 } 04117 if (x >= MAX_SLAVES) { 04118 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel); 04119 master->slaves[MAX_SLAVES - 1] = slave; 04120 } 04121 if (slave->master) 04122 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel); 04123 slave->master = master; 04124 04125 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x); 04126 }
static struct ast_channel * dahdi_new | ( | struct dahdi_pvt * | , | |
int | , | |||
int | , | |||
int | , | |||
int | , | |||
int | ||||
) | [static] |
Definition at line 6274 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_devstate_changed_literal(), 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_digitmode(), 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_chan2dev(), 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_DIGIT_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, dahdi_pvt::muting, ast_variable::name, ast_channel::name, ast_channel::nativeformats, NEED_MFDETECT, ast_variable::next, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, dahdi_pvt::parkinglot, 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().
06275 { 06276 struct ast_channel *tmp; 06277 int deflaw; 06278 int res; 06279 int x,y; 06280 int features; 06281 struct ast_str *chan_name; 06282 struct ast_variable *v; 06283 struct dahdi_params ps; 06284 if (i->subs[idx].owner) { 06285 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]); 06286 return NULL; 06287 } 06288 y = 1; 06289 chan_name = ast_str_alloca(32); 06290 do { 06291 #ifdef HAVE_PRI 06292 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS))) 06293 ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y); 06294 else 06295 #endif 06296 if (i->channel == CHAN_PSEUDO) 06297 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random()); 06298 else 06299 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y); 06300 for (x = 0; x < 3; x++) { 06301 if ((idx != x) && i->subs[x].owner && !strcasecmp(chan_name->str, i->subs[x].owner->name + 6)) 06302 break; 06303 } 06304 y++; 06305 } while (x < 3); 06306 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); 06307 if (!tmp) 06308 return NULL; 06309 tmp->tech = &dahdi_tech; 06310 memset(&ps, 0, sizeof(ps)); 06311 ps.channo = i->channel; 06312 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps); 06313 if (res) { 06314 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno)); 06315 ps.curlaw = DAHDI_LAW_MULAW; 06316 } 06317 if (ps.curlaw == DAHDI_LAW_ALAW) 06318 deflaw = AST_FORMAT_ALAW; 06319 else 06320 deflaw = AST_FORMAT_ULAW; 06321 if (law) { 06322 if (law == DAHDI_LAW_ALAW) 06323 deflaw = AST_FORMAT_ALAW; 06324 else 06325 deflaw = AST_FORMAT_ULAW; 06326 } 06327 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd); 06328 tmp->nativeformats = deflaw; 06329 /* Start out assuming ulaw since it's smaller :) */ 06330 tmp->rawreadformat = deflaw; 06331 tmp->readformat = deflaw; 06332 tmp->rawwriteformat = deflaw; 06333 tmp->writeformat = deflaw; 06334 i->subs[idx].linear = 0; 06335 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear); 06336 features = 0; 06337 if (idx == SUB_REAL) { 06338 if (i->busydetect && CANBUSYDETECT(i)) 06339 features |= DSP_FEATURE_BUSY_DETECT; 06340 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i)) 06341 features |= DSP_FEATURE_CALL_PROGRESS; 06342 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) || 06343 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) { 06344 features |= DSP_FEATURE_FAX_DETECT; 06345 } 06346 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 06347 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) { 06348 i->hardwaredtmf = 0; 06349 features |= DSP_FEATURE_DIGIT_DETECT; 06350 } else if (NEED_MFDETECT(i)) { 06351 i->hardwaredtmf = 1; 06352 features |= DSP_FEATURE_DIGIT_DETECT; 06353 } 06354 } 06355 if (features) { 06356 if (i->dsp) { 06357 ast_debug(1, "Already have a dsp on %s?\n", tmp->name); 06358 } else { 06359 if (i->channel != CHAN_PSEUDO) 06360 i->dsp = ast_dsp_new(); 06361 else 06362 i->dsp = NULL; 06363 if (i->dsp) { 06364 i->dsp_features = features; 06365 #if defined(HAVE_PRI) || defined(HAVE_SS7) 06366 /* We cannot do progress detection until receives PROGRESS message */ 06367 if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) { 06368 /* Remember requested DSP features, don't treat 06369 talking as ANSWER */ 06370 i->dsp_features = features & ~DSP_PROGRESS_TALK; 06371 features = 0; 06372 } 06373 #endif 06374 ast_dsp_set_features(i->dsp, features); 06375 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax); 06376 if (!ast_strlen_zero(progzone)) 06377 ast_dsp_set_call_progress_zone(i->dsp, progzone); 06378 if (i->busydetect && CANBUSYDETECT(i)) { 06379 if(i->silencethreshold > 0) 06380 ast_dsp_set_threshold(i->dsp, i->silencethreshold); 06381 ast_dsp_set_busy_count(i->dsp, i->busycount); 06382 if(i->busytonelength > 0) 06383 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness); 06384 if((i->busytonelength == i->busyquietlength) && i->busycompare) 06385 ast_dsp_set_busy_compare(i->dsp, i->busycompare); 06386 } 06387 } 06388 } 06389 } 06390 06391 if (state == AST_STATE_RING) 06392 tmp->rings = 1; 06393 tmp->tech_pvt = i; 06394 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) { 06395 /* Only FXO signalled stuff can be picked up */ 06396 tmp->callgroup = i->callgroup; 06397 tmp->pickupgroup = i->pickupgroup; 06398 } 06399 if (!ast_strlen_zero(i->parkinglot)) 06400 ast_string_field_set(tmp, parkinglot, i->parkinglot); 06401 if (!ast_strlen_zero(i->language)) 06402 ast_string_field_set(tmp, language, i->language); 06403 if (!i->owner) 06404 i->owner = tmp; 06405 if (!ast_strlen_zero(i->accountcode)) 06406 ast_string_field_set(tmp, accountcode, i->accountcode); 06407 if (i->amaflags) 06408 tmp->amaflags = i->amaflags; 06409 i->subs[idx].owner = tmp; 06410 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 06411 ast_string_field_set(tmp, call_forward, i->call_forward); 06412 /* If we've been told "no ADSI" then enforce it */ 06413 if (!i->adsi) 06414 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 06415 if (!ast_strlen_zero(i->exten)) 06416 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 06417 if (!ast_strlen_zero(i->rdnis)) 06418 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 06419 if (!ast_strlen_zero(i->dnid)) 06420 tmp->cid.cid_dnid = ast_strdup(i->dnid); 06421 06422 /* Don't use ast_set_callerid() here because it will 06423 * generate a needless NewCallerID event */ 06424 #ifdef PRI_ANI 06425 if (!ast_strlen_zero(i->cid_ani)) 06426 tmp->cid.cid_ani = ast_strdup(i->cid_ani); 06427 else 06428 tmp->cid.cid_ani = ast_strdup(i->cid_num); 06429 #else 06430 tmp->cid.cid_ani = ast_strdup(i->cid_num); 06431 #endif 06432 tmp->cid.cid_pres = i->callingpres; 06433 tmp->cid.cid_ton = i->cid_ton; 06434 tmp->cid.cid_ani2 = i->cid_ani2; 06435 #if defined(HAVE_PRI) || defined(HAVE_SS7) 06436 tmp->transfercapability = transfercapability; 06437 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability)); 06438 if (transfercapability & AST_TRANS_CAP_DIGITAL) 06439 i->digital = 1; 06440 /* Assume calls are not idle calls unless we're told differently */ 06441 i->isidlecall = 0; 06442 i->alreadyhungup = 0; 06443 #endif 06444 /* clear the fake event in case we posted one before we had ast_channel */ 06445 i->fake_event = 0; 06446 /* Assure there is no confmute on this channel */ 06447 dahdi_confmute(i, 0); 06448 i->muting = 0; 06449 /* Configure the new channel jb */ 06450 ast_jb_configure(tmp, &global_jbconf); 06451 06452 ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name); 06453 06454 for (v = i->vars ; v ; v = v->next) 06455 pbx_builtin_setvar_helper(tmp, v->name, v->value); 06456 06457 if (startpbx) { 06458 if (ast_pbx_start(tmp)) { 06459 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 06460 ast_hangup(tmp); 06461 i->owner = NULL; 06462 return NULL; 06463 } 06464 } 06465 06466 ast_module_ref(ast_module_info->self); 06467 return tmp; 06468 }
static int dahdi_open | ( | char * | fn | ) | [static] |
Definition at line 1456 of file chan_dahdi.c.
References ast_log(), chan, errno, LOG_WARNING, and READ_SIZE.
Referenced by alloc_sub(), chandup(), and mkintf().
01457 { 01458 int fd; 01459 int isnum; 01460 int chan = 0; 01461 int bs; 01462 int x; 01463 isnum = 1; 01464 for (x = 0; x < strlen(fn); x++) { 01465 if (!isdigit(fn[x])) { 01466 isnum = 0; 01467 break; 01468 } 01469 } 01470 if (isnum) { 01471 chan = atoi(fn); 01472 if (chan < 1) { 01473 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn); 01474 return -1; 01475 } 01476 fn = "/dev/dahdi/channel"; 01477 } 01478 fd = open(fn, O_RDWR | O_NONBLOCK); 01479 if (fd < 0) { 01480 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno)); 01481 return -1; 01482 } 01483 if (chan) { 01484 if (ioctl(fd, DAHDI_SPECIFY, &chan)) { 01485 x = errno; 01486 close(fd); 01487 errno = x; 01488 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno)); 01489 return -1; 01490 } 01491 } 01492 bs = READ_SIZE; 01493 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) { 01494 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno)); 01495 x = errno; 01496 close(fd); 01497 errno = x; 01498 return -1; 01499 } 01500 return fd; 01501 }
static void dahdi_pri_error | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 10725 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().
10726 { 10727 int x, y; 10728 int dchan = -1, span = -1; 10729 int dchancount = 0; 10730 10731 if (pri) { 10732 for (x = 0; x < NUM_SPANS; x++) { 10733 for (y = 0; y < NUM_DCHANS; y++) { 10734 if (pris[x].dchans[y]) 10735 dchancount++; 10736 10737 if (pris[x].dchans[y] == pri) 10738 dchan = y; 10739 } 10740 if (dchan >= 0) { 10741 span = x; 10742 break; 10743 } 10744 dchancount = 0; 10745 } 10746 if ((dchancount > 1) && (span > -1)) 10747 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s); 10748 else 10749 ast_log(LOG_ERROR, "%s", s); 10750 } else 10751 ast_log(LOG_ERROR, "%s", s); 10752 10753 ast_mutex_lock(&pridebugfdlock); 10754 10755 if (pridebugfd >= 0) { 10756 if (write(pridebugfd, s, strlen(s)) < 0) { 10757 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 10758 } 10759 } 10760 10761 ast_mutex_unlock(&pridebugfdlock); 10762 }
static void dahdi_pri_message | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 10686 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().
10687 { 10688 int x, y; 10689 int dchan = -1, span = -1; 10690 int dchancount = 0; 10691 10692 if (pri) { 10693 for (x = 0; x < NUM_SPANS; x++) { 10694 for (y = 0; y < NUM_DCHANS; y++) { 10695 if (pris[x].dchans[y]) 10696 dchancount++; 10697 10698 if (pris[x].dchans[y] == pri) 10699 dchan = y; 10700 } 10701 if (dchan >= 0) { 10702 span = x; 10703 break; 10704 } 10705 dchancount = 0; 10706 } 10707 if (dchancount > 1 && (span > -1)) 10708 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s); 10709 else 10710 ast_verbose("%s", s); 10711 } else 10712 ast_verbose("%s", s); 10713 10714 ast_mutex_lock(&pridebugfdlock); 10715 10716 if (pridebugfd >= 0) { 10717 if (write(pridebugfd, s, strlen(s)) < 0) { 10718 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 10719 } 10720 } 10721 10722 ast_mutex_unlock(&pridebugfdlock); 10723 }
Definition at line 1362 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().
01363 { 01364 #ifdef HAVE_PRI 01365 struct dahdi_pri *pri = (struct dahdi_pri*) data; 01366 #endif 01367 #ifdef HAVE_SS7 01368 struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data; 01369 #endif 01370 /* We must unlock the PRI to avoid the possibility of a deadlock */ 01371 #if defined(HAVE_PRI) || defined(HAVE_SS7) 01372 if (data) { 01373 switch (p->sig) { 01374 #ifdef HAVE_PRI 01375 case SIG_BRI: 01376 case SIG_BRI_PTMP: 01377 case SIG_PRI: 01378 ast_mutex_unlock(&pri->lock); 01379 break; 01380 #endif 01381 #ifdef HAVE_SS7 01382 case SIG_SS7: 01383 ast_mutex_unlock(&ss7->lock); 01384 break; 01385 #endif 01386 default: 01387 break; 01388 } 01389 } 01390 #endif 01391 for (;;) { 01392 if (p->owner) { 01393 if (ast_channel_trylock(p->owner)) { 01394 DEADLOCK_AVOIDANCE(&p->lock); 01395 } else { 01396 ast_queue_frame(p->owner, f); 01397 ast_channel_unlock(p->owner); 01398 break; 01399 } 01400 } else 01401 break; 01402 } 01403 #if defined(HAVE_PRI) || defined(HAVE_SS7) 01404 if (data) { 01405 switch (p->sig) { 01406 #ifdef HAVE_PRI 01407 case SIG_BRI: 01408 case SIG_BRI_PTMP: 01409 case SIG_PRI: 01410 ast_mutex_lock(&pri->lock); 01411 break; 01412 #endif 01413 #ifdef HAVE_SS7 01414 case SIG_SS7: 01415 ast_mutex_lock(&ss7->lock); 01416 break; 01417 #endif 01418 default: 01419 break; 01420 } 01421 } 01422 01423 #endif 01424 }
static struct ast_frame * dahdi_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5643 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_dsp_was_muted(), 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_confmute(), 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, dahdi_pvt::muting, 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, ast_frame::ptr, 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.
05644 { 05645 struct dahdi_pvt *p = ast->tech_pvt; 05646 int res; 05647 int idx; 05648 void *readbuf; 05649 struct ast_frame *f; 05650 05651 while (ast_mutex_trylock(&p->lock)) { 05652 CHANNEL_DEADLOCK_AVOIDANCE(ast); 05653 } 05654 05655 idx = dahdi_get_index(ast, p, 0); 05656 05657 /* Hang up if we don't really exist */ 05658 if (idx < 0) { 05659 ast_log(LOG_WARNING, "We dont exist?\n"); 05660 ast_mutex_unlock(&p->lock); 05661 return NULL; 05662 } 05663 05664 if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL; 05665 05666 p->subs[idx].f.frametype = AST_FRAME_NULL; 05667 p->subs[idx].f.datalen = 0; 05668 p->subs[idx].f.samples = 0; 05669 p->subs[idx].f.mallocd = 0; 05670 p->subs[idx].f.offset = 0; 05671 p->subs[idx].f.subclass = 0; 05672 p->subs[idx].f.delivery = ast_tv(0,0); 05673 p->subs[idx].f.src = "dahdi_read"; 05674 p->subs[idx].f.data.ptr = NULL; 05675 05676 /* make sure it sends initial key state as first frame */ 05677 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio)) 05678 { 05679 struct dahdi_params ps; 05680 05681 memset(&ps, 0, sizeof(ps)); 05682 ps.channo = p->channel; 05683 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 05684 ast_mutex_unlock(&p->lock); 05685 return NULL; 05686 } 05687 p->firstradio = 1; 05688 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05689 if (ps.rxisoffhook) 05690 { 05691 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY; 05692 } 05693 else 05694 { 05695 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY; 05696 } 05697 ast_mutex_unlock(&p->lock); 05698 return &p->subs[idx].f; 05699 } 05700 if (p->ringt == 1) { 05701 ast_mutex_unlock(&p->lock); 05702 return NULL; 05703 } 05704 else if (p->ringt > 0) 05705 p->ringt--; 05706 05707 if (p->subs[idx].needringing) { 05708 /* Send ringing frame if requested */ 05709 p->subs[idx].needringing = 0; 05710 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05711 p->subs[idx].f.subclass = AST_CONTROL_RINGING; 05712 ast_setstate(ast, AST_STATE_RINGING); 05713 ast_mutex_unlock(&p->lock); 05714 return &p->subs[idx].f; 05715 } 05716 05717 if (p->subs[idx].needbusy) { 05718 /* Send busy frame if requested */ 05719 p->subs[idx].needbusy = 0; 05720 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05721 p->subs[idx].f.subclass = AST_CONTROL_BUSY; 05722 ast_mutex_unlock(&p->lock); 05723 return &p->subs[idx].f; 05724 } 05725 05726 if (p->subs[idx].needcongestion) { 05727 /* Send congestion frame if requested */ 05728 p->subs[idx].needcongestion = 0; 05729 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05730 p->subs[idx].f.subclass = AST_CONTROL_CONGESTION; 05731 ast_mutex_unlock(&p->lock); 05732 return &p->subs[idx].f; 05733 } 05734 05735 if (p->subs[idx].needcallerid) { 05736 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL), 05737 S_OR(p->lastcid_name, NULL), 05738 S_OR(p->lastcid_num, NULL) 05739 ); 05740 p->subs[idx].needcallerid = 0; 05741 } 05742 05743 if (p->subs[idx].needanswer) { 05744 /* Send answer frame if requested */ 05745 p->subs[idx].needanswer = 0; 05746 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05747 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 05748 ast_mutex_unlock(&p->lock); 05749 return &p->subs[idx].f; 05750 } 05751 05752 if (p->subs[idx].needflash) { 05753 /* Send answer frame if requested */ 05754 p->subs[idx].needflash = 0; 05755 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05756 p->subs[idx].f.subclass = AST_CONTROL_FLASH; 05757 ast_mutex_unlock(&p->lock); 05758 return &p->subs[idx].f; 05759 } 05760 05761 if (p->subs[idx].needhold) { 05762 /* Send answer frame if requested */ 05763 p->subs[idx].needhold = 0; 05764 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05765 p->subs[idx].f.subclass = AST_CONTROL_HOLD; 05766 ast_mutex_unlock(&p->lock); 05767 ast_debug(1, "Sending hold on '%s'\n", ast->name); 05768 return &p->subs[idx].f; 05769 } 05770 05771 if (p->subs[idx].needunhold) { 05772 /* Send answer frame if requested */ 05773 p->subs[idx].needunhold = 0; 05774 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05775 p->subs[idx].f.subclass = AST_CONTROL_UNHOLD; 05776 ast_mutex_unlock(&p->lock); 05777 ast_debug(1, "Sending unhold on '%s'\n", ast->name); 05778 return &p->subs[idx].f; 05779 } 05780 05781 if (ast->rawreadformat == AST_FORMAT_SLINEAR) { 05782 if (!p->subs[idx].linear) { 05783 p->subs[idx].linear = 1; 05784 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 05785 if (res) 05786 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx); 05787 } 05788 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) || 05789 (ast->rawreadformat == AST_FORMAT_ALAW)) { 05790 if (p->subs[idx].linear) { 05791 p->subs[idx].linear = 0; 05792 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 05793 if (res) 05794 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx); 05795 } 05796 } else { 05797 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat)); 05798 ast_mutex_unlock(&p->lock); 05799 return NULL; 05800 } 05801 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET; 05802 CHECK_BLOCKING(ast); 05803 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); 05804 ast_clear_flag(ast, AST_FLAG_BLOCKING); 05805 /* Check for hangup */ 05806 if (res < 0) { 05807 f = NULL; 05808 if (res == -1) { 05809 if (errno == EAGAIN) { 05810 /* Return "NULL" frame if there is nobody there */ 05811 ast_mutex_unlock(&p->lock); 05812 return &p->subs[idx].f; 05813 } else if (errno == ELAST) { 05814 f = __dahdi_exception(ast); 05815 } else 05816 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno)); 05817 } 05818 ast_mutex_unlock(&p->lock); 05819 return f; 05820 } 05821 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) { 05822 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); 05823 f = __dahdi_exception(ast); 05824 ast_mutex_unlock(&p->lock); 05825 return f; 05826 } 05827 if (p->tdd) { /* if in TDD mode, see if we receive that */ 05828 int c; 05829 05830 c = tdd_feed(p->tdd,readbuf,READ_SIZE); 05831 if (c < 0) { 05832 ast_debug(1,"tdd_feed failed\n"); 05833 ast_mutex_unlock(&p->lock); 05834 return NULL; 05835 } 05836 if (c) { /* if a char to return */ 05837 p->subs[idx].f.subclass = 0; 05838 p->subs[idx].f.frametype = AST_FRAME_TEXT; 05839 p->subs[idx].f.mallocd = 0; 05840 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; 05841 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET; 05842 p->subs[idx].f.datalen = 1; 05843 *((char *) p->subs[idx].f.data.ptr) = c; 05844 ast_mutex_unlock(&p->lock); 05845 return &p->subs[idx].f; 05846 } 05847 } 05848 /* Ensure the CW timer decrements only on a single subchannel */ 05849 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) { 05850 p->callwaitingrepeat--; 05851 } 05852 if (p->cidcwexpire) 05853 p->cidcwexpire--; 05854 /* Repeat callwaiting */ 05855 if (p->callwaitingrepeat == 1) { 05856 p->callwaitrings++; 05857 dahdi_callwait(ast); 05858 } 05859 /* Expire CID/CW */ 05860 if (p->cidcwexpire == 1) { 05861 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n"); 05862 restore_conference(p); 05863 } 05864 if (p->subs[idx].linear) { 05865 p->subs[idx].f.datalen = READ_SIZE * 2; 05866 } else 05867 p->subs[idx].f.datalen = READ_SIZE; 05868 05869 /* Handle CallerID Transmission */ 05870 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) { 05871 send_callerid(p); 05872 } 05873 05874 p->subs[idx].f.frametype = AST_FRAME_VOICE; 05875 p->subs[idx].f.subclass = ast->rawreadformat; 05876 p->subs[idx].f.samples = READ_SIZE; 05877 p->subs[idx].f.mallocd = 0; 05878 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; 05879 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]); 05880 #if 0 05881 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name); 05882 #endif 05883 if (p->dialing || /* Transmitting something */ 05884 (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */ 05885 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */ 05886 ) { 05887 /* Whoops, we're still dialing, or in a state where we shouldn't transmit.... 05888 don't send anything */ 05889 p->subs[idx].f.frametype = AST_FRAME_NULL; 05890 p->subs[idx].f.subclass = 0; 05891 p->subs[idx].f.samples = 0; 05892 p->subs[idx].f.mallocd = 0; 05893 p->subs[idx].f.offset = 0; 05894 p->subs[idx].f.data.ptr = NULL; 05895 p->subs[idx].f.datalen= 0; 05896 } 05897 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !idx) { 05898 /* Perform busy detection. etc on the dahdi line */ 05899 int mute; 05900 05901 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f); 05902 05903 /* Check if DSP code thinks we should be muting this frame and mute the conference if so */ 05904 mute = ast_dsp_was_muted(p->dsp); 05905 if (p->muting != mute) { 05906 p->muting = mute; 05907 dahdi_confmute(p, mute); 05908 } 05909 05910 if (f) { 05911 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) { 05912 if ((ast->_state == AST_STATE_UP) && !p->outgoing) { 05913 /* Treat this as a "hangup" instead of a "busy" on the assumption that 05914 a busy */ 05915 f = NULL; 05916 } 05917 } else if (f->frametype == AST_FRAME_DTMF) { 05918 #ifdef HAVE_PRI 05919 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && 05920 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) || 05921 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) { 05922 /* Don't accept in-band DTMF when in overlap dial mode */ 05923 f->frametype = AST_FRAME_NULL; 05924 f->subclass = 0; 05925 } 05926 #endif 05927 /* DSP clears us of being pulse */ 05928 p->pulsedial = 0; 05929 } 05930 } 05931 } else 05932 f = &p->subs[idx].f; 05933 05934 if (f && (f->frametype == AST_FRAME_DTMF)) 05935 dahdi_handle_dtmfup(ast, idx, &f); 05936 05937 /* If we have a fake_event, trigger exception to handle it */ 05938 if (p->fake_event) 05939 ast_set_flag(ast, AST_FLAG_EXCEPTION); 05940 05941 ast_mutex_unlock(&p->lock); 05942 return f; 05943 }
static struct ast_channel * dahdi_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 9441 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().
09442 { 09443 ast_group_t groupmatch = 0; 09444 int channelmatch = -1; 09445 int roundrobin = 0; 09446 int callwait = 0; 09447 int busy = 0; 09448 struct dahdi_pvt *p; 09449 struct ast_channel *tmp = NULL; 09450 char *dest=NULL; 09451 int x; 09452 char *s; 09453 char opt=0; 09454 int res=0, y=0; 09455 int backwards = 0; 09456 #ifdef HAVE_PRI 09457 int crv; 09458 int bearer = -1; 09459 int trunkgroup; 09460 struct dahdi_pri *pri=NULL; 09461 #endif 09462 struct dahdi_pvt *exitpvt, *start, *end; 09463 ast_mutex_t *lock; 09464 int channelmatched = 0; 09465 int groupmatched = 0; 09466 09467 /* 09468 * data is ---v 09469 * Dial(DAHDI/pseudo[/extension]) 09470 * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension]) 09471 * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension]) 09472 * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension]) 09473 * 09474 * g - channel group allocation search forward 09475 * G - channel group allocation search backward 09476 * r - channel group allocation round robin search forward 09477 * R - channel group allocation round robin search backward 09478 * 09479 * c - Wait for DTMF digit to confirm answer 09480 * r<cadance#> - Set distintive ring cadance number 09481 * d - Force bearer capability for ISDN/SS7 call to digital. 09482 */ 09483 09484 /* Assume we're locking the iflock */ 09485 lock = &iflock; 09486 start = iflist; 09487 end = ifend; 09488 if (data) { 09489 dest = ast_strdupa((char *)data); 09490 } else { 09491 ast_log(LOG_WARNING, "Channel requested with no data\n"); 09492 return NULL; 09493 } 09494 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') { 09495 /* Retrieve the group number */ 09496 char *stringp; 09497 09498 stringp = dest + 1; 09499 s = strsep(&stringp, "/"); 09500 if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) { 09501 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data); 09502 return NULL; 09503 } 09504 groupmatch = ((ast_group_t) 1 << x); 09505 if (toupper(dest[0]) == 'G') { 09506 if (dest[0] == 'G') { 09507 backwards = 1; 09508 p = ifend; 09509 } else 09510 p = iflist; 09511 } else { 09512 if (dest[0] == 'R') { 09513 backwards = 1; 09514 p = round_robin[x]?round_robin[x]->prev:ifend; 09515 if (!p) 09516 p = ifend; 09517 } else { 09518 p = round_robin[x]?round_robin[x]->next:iflist; 09519 if (!p) 09520 p = iflist; 09521 } 09522 roundrobin = 1; 09523 } 09524 } else { 09525 char *stringp; 09526 09527 stringp = dest; 09528 s = strsep(&stringp, "/"); 09529 p = iflist; 09530 if (!strcasecmp(s, "pseudo")) { 09531 /* Special case for pseudo */ 09532 x = CHAN_PSEUDO; 09533 channelmatch = x; 09534 } 09535 #ifdef HAVE_PRI 09536 else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) { 09537 if ((trunkgroup < 1) || (crv < 1)) { 09538 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data); 09539 return NULL; 09540 } 09541 res--; 09542 for (x = 0; x < NUM_SPANS; x++) { 09543 if (pris[x].trunkgroup == trunkgroup) { 09544 pri = pris + x; 09545 lock = &pri->lock; 09546 start = pri->crvs; 09547 end = pri->crvend; 09548 break; 09549 } 09550 } 09551 if (!pri) { 09552 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup); 09553 return NULL; 09554 } 09555 channelmatch = crv; 09556 p = pris[x].crvs; 09557 } 09558 #endif 09559 else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) { 09560 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data); 09561 return NULL; 09562 } else { 09563 channelmatch = x; 09564 } 09565 } 09566 /* Search for an unowned channel */ 09567 ast_mutex_lock(lock); 09568 exitpvt = p; 09569 while (p && !tmp) { 09570 if (roundrobin) 09571 round_robin[x] = p; 09572 #if 0 09573 ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch); 09574 #endif 09575 09576 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) { 09577 ast_debug(1, "Using channel %d\n", p->channel); 09578 if (p->inalarm) 09579 goto next; 09580 09581 callwait = (p->owner != NULL); 09582 #ifdef HAVE_PRI 09583 if (pri && (p->subs[SUB_REAL].dfd < 0)) { 09584 if (p->sig != SIG_FXSKS) { 09585 /* Gotta find an actual channel to use for this 09586 CRV if this isn't a callwait */ 09587 bearer = pri_find_empty_chan(pri, 0); 09588 if (bearer < 0) { 09589 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv); 09590 p = NULL; 09591 break; 09592 } 09593 pri_assign_bearer(p, pri, pri->pvts[bearer]); 09594 } else { 09595 if (alloc_sub(p, 0)) { 09596 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n"); 09597 p = NULL; 09598 break; 09599 } else 09600 ast_debug(1, "Allocated placeholder pseudo channel\n"); 09601 09602 p->pri = pri; 09603 } 09604 } 09605 #endif 09606 if (p->channel == CHAN_PSEUDO) { 09607 p = chandup(p); 09608 if (!p) { 09609 break; 09610 } 09611 } 09612 if (p->owner) { 09613 if (alloc_sub(p, SUB_CALLWAIT)) { 09614 p = NULL; 09615 break; 09616 } 09617 } 09618 p->outgoing = 1; 09619 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0); 09620 #ifdef HAVE_PRI 09621 if (p->bearer) { 09622 /* Log owner to bearer channel, too */ 09623 p->bearer->owner = tmp; 09624 } 09625 #endif 09626 /* Make special notes */ 09627 if (res > 1) { 09628 if (opt == 'c') { 09629 /* Confirm answer */ 09630 p->confirmanswer = 1; 09631 } else if (opt == 'r') { 09632 /* Distinctive ring */ 09633 if (res < 3) 09634 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data); 09635 else 09636 p->distinctivering = y; 09637 } else if (opt == 'd') { 09638 /* If this is an ISDN call, make it digital */ 09639 p->digital = 1; 09640 if (tmp) 09641 tmp->transfercapability = AST_TRANS_CAP_DIGITAL; 09642 } else { 09643 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data); 09644 } 09645 } 09646 /* Note if the call is a call waiting call */ 09647 if (tmp && callwait) 09648 tmp->cdrflags |= AST_CDR_CALLWAIT; 09649 break; 09650 } 09651 next: 09652 if (backwards) { 09653 p = p->prev; 09654 if (!p) 09655 p = end; 09656 } else { 09657 p = p->next; 09658 if (!p) 09659 p = start; 09660 } 09661 /* stop when you roll to the one that we started from */ 09662 if (p == exitpvt) 09663 break; 09664 } 09665 ast_mutex_unlock(lock); 09666 restart_monitor(); 09667 if (callwait) 09668 *cause = AST_CAUSE_BUSY; 09669 else if (!tmp) { 09670 if (channelmatched) { 09671 if (busy) 09672 *cause = AST_CAUSE_BUSY; 09673 } else if (groupmatched) { 09674 *cause = AST_CAUSE_CONGESTION; 09675 } 09676 } 09677 09678 return tmp; 09679 }
static int dahdi_restart | ( | void | ) | [static] |
Definition at line 12480 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, mwi_thread_lock, 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().
12481 { 12482 #if defined(HAVE_PRI) || defined(HAVE_SS7) 12483 int i, j; 12484 #endif 12485 int cancel_code; 12486 struct dahdi_pvt *p; 12487 12488 ast_mutex_lock(&restart_lock); 12489 12490 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n"); 12491 dahdi_softhangup_all(); 12492 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n"); 12493 12494 #if defined(HAVE_PRI) 12495 for (i = 0; i < NUM_SPANS; i++) { 12496 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) { 12497 cancel_code = pthread_cancel(pris[i].master); 12498 pthread_kill(pris[i].master, SIGURG); 12499 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code); 12500 pthread_join(pris[i].master, NULL); 12501 ast_debug(4, "Joined thread of span %d\n", i); 12502 } 12503 } 12504 #endif 12505 12506 #if defined(HAVE_SS7) 12507 for (i = 0; i < NUM_SPANS; i++) { 12508 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) { 12509 cancel_code = pthread_cancel(linksets[i].master); 12510 pthread_kill(linksets[i].master, SIGURG); 12511 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code); 12512 pthread_join(linksets[i].master, NULL); 12513 ast_debug(4, "Joined thread of span %d\n", i); 12514 } 12515 } 12516 #endif 12517 12518 ast_mutex_lock(&monlock); 12519 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 12520 cancel_code = pthread_cancel(monitor_thread); 12521 pthread_kill(monitor_thread, SIGURG); 12522 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code); 12523 pthread_join(monitor_thread, NULL); 12524 ast_debug(4, "Joined monitor thread\n"); 12525 } 12526 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */ 12527 12528 ast_mutex_lock(&mwi_thread_lock); 12529 while (mwi_thread_count > 0) { 12530 ast_debug(3, "Waiting on %d mwi_send_thread(s) to finish\n", mwi_thread_count); 12531 ast_cond_wait(&mwi_thread_complete, &mwi_thread_lock); 12532 } 12533 ast_mutex_unlock(&mwi_thread_lock); 12534 ast_mutex_lock(&ss_thread_lock); 12535 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */ 12536 int x = DAHDI_FLASH; 12537 ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count); 12538 12539 for (p = iflist; p; p = p->next) { 12540 if (p->owner) 12541 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 */ 12542 } 12543 ast_cond_wait(&ss_thread_complete, &ss_thread_lock); 12544 } 12545 12546 /* ensure any created channels before monitor threads were stopped are hungup */ 12547 dahdi_softhangup_all(); 12548 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n"); 12549 destroy_all_channels(); 12550 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels()); 12551 12552 ast_mutex_unlock(&monlock); 12553 12554 #ifdef HAVE_PRI 12555 for (i = 0; i < NUM_SPANS; i++) { 12556 for (j = 0; j < NUM_DCHANS; j++) 12557 dahdi_close_pri_fd(&(pris[i]), j); 12558 } 12559 12560 memset(pris, 0, sizeof(pris)); 12561 for (i = 0; i < NUM_SPANS; i++) { 12562 ast_mutex_init(&pris[i].lock); 12563 pris[i].offset = -1; 12564 pris[i].master = AST_PTHREADT_NULL; 12565 for (j = 0; j < NUM_DCHANS; j++) 12566 pris[i].fds[j] = -1; 12567 } 12568 pri_set_error(dahdi_pri_error); 12569 pri_set_message(dahdi_pri_message); 12570 #endif 12571 #ifdef HAVE_SS7 12572 for (i = 0; i < NUM_SPANS; i++) { 12573 for (j = 0; j < NUM_DCHANS; j++) 12574 dahdi_close_ss7_fd(&(linksets[i]), j); 12575 } 12576 12577 memset(linksets, 0, sizeof(linksets)); 12578 for (i = 0; i < NUM_SPANS; i++) { 12579 ast_mutex_init(&linksets[i].lock); 12580 linksets[i].master = AST_PTHREADT_NULL; 12581 for (j = 0; j < NUM_DCHANS; j++) 12582 linksets[i].fds[j] = -1; 12583 } 12584 ss7_set_error(dahdi_ss7_error); 12585 ss7_set_message(dahdi_ss7_message); 12586 #endif 12587 12588 if (setup_dahdi(2) != 0) { 12589 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n"); 12590 ast_mutex_unlock(&ss_thread_lock); 12591 return 1; 12592 } 12593 ast_mutex_unlock(&ss_thread_lock); 12594 ast_mutex_unlock(&restart_lock); 12595 return 0; 12596 }
static char* dahdi_restart_cmd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12598 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.
12599 { 12600 switch (cmd) { 12601 case CLI_INIT: 12602 e->command = "dahdi restart"; 12603 e->usage = 12604 "Usage: dahdi restart\n" 12605 " Restarts the DAHDI channels: destroys them all and then\n" 12606 " re-reads them from chan_dahdi.conf.\n" 12607 " Note that this will STOP any running CALL on DAHDI channels.\n" 12608 ""; 12609 return NULL; 12610 case CLI_GENERATE: 12611 return NULL; 12612 } 12613 if (a->argc != 2) 12614 return CLI_SHOWUSAGE; 12615 12616 if (dahdi_restart() != 0) 12617 return CLI_FAILURE; 12618 return CLI_SUCCESS; 12619 }
static int dahdi_ring_phone | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4475 of file chan_dahdi.c.
References ast_log(), errno, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), and dahdi_handle_event().
04476 { 04477 int x; 04478 int res; 04479 /* Make sure our transmit state is on hook */ 04480 x = 0; 04481 x = DAHDI_ONHOOK; 04482 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04483 do { 04484 x = DAHDI_RING; 04485 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04486 if (res) { 04487 switch (errno) { 04488 case EBUSY: 04489 case EINTR: 04490 /* Wait just in case */ 04491 usleep(10000); 04492 continue; 04493 case EINPROGRESS: 04494 res = 0; 04495 break; 04496 default: 04497 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno)); 04498 res = 0; 04499 } 04500 } 04501 } while (res); 04502 return res; 04503 }
static int dahdi_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3272 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().
03273 { 03274 /* Data will be our digit string */ 03275 struct dahdi_pvt *p; 03276 char *digits = (char *) data; 03277 03278 if (ast_strlen_zero(digits)) { 03279 ast_debug(1, "No digit string sent to application!\n"); 03280 return -1; 03281 } 03282 03283 p = (struct dahdi_pvt *)chan->tech_pvt; 03284 03285 if (!p) { 03286 ast_debug(1, "Unable to find technology private\n"); 03287 return -1; 03288 } 03289 03290 ast_mutex_lock(&p->lock); 03291 03292 if (!p->pri || !p->call) { 03293 ast_debug(1, "Unable to find pri or call on channel!\n"); 03294 ast_mutex_unlock(&p->lock); 03295 return -1; 03296 } 03297 03298 if (!pri_grab(p, p->pri)) { 03299 pri_keypad_facility(p->pri->pri, p->call, digits); 03300 pri_rel(p->pri); 03301 } else { 03302 ast_debug(1, "Unable to grab pri to send keypad facility!\n"); 03303 ast_mutex_unlock(&p->lock); 03304 return -1; 03305 } 03306 03307 ast_mutex_unlock(&p->lock); 03308 03309 return 0; 03310 }
static int dahdi_sendtext | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 15347 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.
15348 { 15349 #define END_SILENCE_LEN 400 15350 #define HEADER_MS 50 15351 #define TRAILER_MS 5 15352 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) 15353 #define ASCII_BYTES_PER_CHAR 80 15354 15355 unsigned char *buf,*mybuf; 15356 struct dahdi_pvt *p = c->tech_pvt; 15357 struct pollfd fds[1]; 15358 int size,res,fd,len,x; 15359 int bytes=0; 15360 /* Initial carrier (imaginary) */ 15361 float cr = 1.0; 15362 float ci = 0.0; 15363 float scont = 0.0; 15364 int idx; 15365 15366 idx = dahdi_get_index(c, p, 0); 15367 if (idx < 0) { 15368 ast_log(LOG_WARNING, "Huh? I don't exist?\n"); 15369 return -1; 15370 } 15371 if (!text[0]) return(0); /* if nothing to send, dont */ 15372 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */ 15373 if (p->mate) 15374 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN); 15375 else 15376 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN); 15377 if (!buf) 15378 return -1; 15379 mybuf = buf; 15380 if (p->mate) { 15381 int codec = AST_LAW(p); 15382 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */ 15383 PUT_CLID_MARKMS; 15384 } 15385 /* Put actual message */ 15386 for (x = 0; text[x]; x++) { 15387 PUT_CLID(text[x]); 15388 } 15389 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */ 15390 PUT_CLID_MARKMS; 15391 } 15392 len = bytes; 15393 buf = mybuf; 15394 } else { 15395 len = tdd_generate(p->tdd, buf, text); 15396 if (len < 1) { 15397 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text)); 15398 ast_free(mybuf); 15399 return -1; 15400 } 15401 } 15402 memset(buf + len, 0x7f, END_SILENCE_LEN); 15403 len += END_SILENCE_LEN; 15404 fd = p->subs[idx].dfd; 15405 while (len) { 15406 if (ast_check_hangup(c)) { 15407 ast_free(mybuf); 15408 return -1; 15409 } 15410 size = len; 15411 if (size > READ_SIZE) 15412 size = READ_SIZE; 15413 fds[0].fd = fd; 15414 fds[0].events = POLLOUT | POLLPRI; 15415 fds[0].revents = 0; 15416 res = poll(fds, 1, -1); 15417 if (!res) { 15418 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 15419 continue; 15420 } 15421 /* if got exception */ 15422 if (fds[0].revents & POLLPRI) { 15423 ast_free(mybuf); 15424 return -1; 15425 } 15426 if (!(fds[0].revents & POLLOUT)) { 15427 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 15428 continue; 15429 } 15430 res = write(fd, buf, size); 15431 if (res != size) { 15432 if (res == -1) { 15433 ast_free(mybuf); 15434 return -1; 15435 } 15436 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 15437 break; 15438 } 15439 len -= size; 15440 buf += size; 15441 } 15442 ast_free(mybuf); 15443 return(0); 15444 }
static char* dahdi_set_dnd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 13246 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.
13247 { 13248 int channel; 13249 int on; 13250 struct dahdi_pvt *dahdi_chan = NULL; 13251 13252 switch (cmd) { 13253 case CLI_INIT: 13254 e->command = "dahdi set dnd"; 13255 e->usage = 13256 "Usage: dahdi set dnd <chan#> <on|off>\n" 13257 " Sets/resets DND (Do Not Disturb) mode on a channel.\n" 13258 " Changes take effect immediately.\n" 13259 " <chan num> is the channel number\n" 13260 " <on|off> Enable or disable DND mode?\n" 13261 ; 13262 return NULL; 13263 case CLI_GENERATE: 13264 return NULL; 13265 } 13266 13267 if (a->argc != 5) 13268 return CLI_SHOWUSAGE; 13269 13270 if ((channel = atoi(a->argv[3])) <= 0) { 13271 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]); 13272 return CLI_SHOWUSAGE; 13273 } 13274 13275 if (ast_true(a->argv[4])) 13276 on = 1; 13277 else if (ast_false(a->argv[4])) 13278 on = 0; 13279 else { 13280 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]); 13281 return CLI_SHOWUSAGE; 13282 } 13283 13284 ast_mutex_lock(&iflock); 13285 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) { 13286 if (dahdi_chan->channel != channel) 13287 continue; 13288 13289 /* Found the channel. Actually set it */ 13290 dahdi_dnd(dahdi_chan, on); 13291 break; 13292 } 13293 ast_mutex_unlock(&iflock); 13294 13295 if (!dahdi_chan) { 13296 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 13297 return CLI_FAILURE; 13298 } 13299 13300 return CLI_SUCCESS; 13301 }
static int dahdi_set_hook | ( | int | fd, | |
int | hs | |||
) | [inline, static] |
Definition at line 2227 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(), mwi_send_thread(), and ss_thread().
02228 { 02229 int x, res; 02230 02231 x = hs; 02232 res = ioctl(fd, DAHDI_HOOK, &x); 02233 02234 if (res < 0) { 02235 if (errno == EINPROGRESS) 02236 return 0; 02237 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno)); 02238 /* will expectedly fail if phone is off hook during operation, such as during a restart */ 02239 } 02240 02241 return res; 02242 }
static char* dahdi_set_hwgain | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 13103 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.
13104 { 13105 int channel; 13106 int gain; 13107 int tx; 13108 struct dahdi_hwgain hwgain; 13109 struct dahdi_pvt *tmp = NULL; 13110 13111 switch (cmd) { 13112 case CLI_INIT: 13113 e->command = "dahdi set hwgain"; 13114 e->usage = 13115 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n" 13116 " Sets the hardware gain on a a given channel, overriding the\n" 13117 " value provided at module loadtime, whether the channel is in\n" 13118 " use or not. Changes take effect immediately.\n" 13119 " <rx|tx> which direction do you want to change (relative to our module)\n" 13120 " <chan num> is the channel number relative to the device\n" 13121 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"; 13122 return NULL; 13123 case CLI_GENERATE: 13124 return NULL; 13125 } 13126 13127 if (a->argc != 6) 13128 return CLI_SHOWUSAGE; 13129 13130 if (!strcasecmp("rx", a->argv[3])) 13131 tx = 0; /* rx */ 13132 else if (!strcasecmp("tx", a->argv[3])) 13133 tx = 1; /* tx */ 13134 else 13135 return CLI_SHOWUSAGE; 13136 13137 channel = atoi(a->argv[4]); 13138 gain = atof(a->argv[5])*10.0; 13139 13140 ast_mutex_lock(&iflock); 13141 13142 for (tmp = iflist; tmp; tmp = tmp->next) { 13143 13144 if (tmp->channel != channel) 13145 continue; 13146 13147 if (tmp->subs[SUB_REAL].dfd == -1) 13148 break; 13149 13150 hwgain.newgain = gain; 13151 hwgain.tx = tx; 13152 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) { 13153 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno)); 13154 ast_mutex_unlock(&iflock); 13155 return CLI_FAILURE; 13156 } 13157 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n", 13158 tx ? "tx" : "rx", gain, (float)gain/10.0, channel); 13159 break; 13160 } 13161 13162 ast_mutex_unlock(&iflock); 13163 13164 if (tmp) 13165 return CLI_SUCCESS; 13166 13167 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 13168 return CLI_FAILURE; 13169 13170 }
static char* dahdi_set_swgain | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 13172 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.
13173 { 13174 int channel; 13175 float gain; 13176 int tx; 13177 int res; 13178 ast_mutex_t *lock; 13179 struct dahdi_pvt *tmp = NULL; 13180 13181 switch (cmd) { 13182 case CLI_INIT: 13183 e->command = "dahdi set swgain"; 13184 e->usage = 13185 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n" 13186 " Sets the software gain on a a given channel, overriding the\n" 13187 " value provided at module loadtime, whether the channel is in\n" 13188 " use or not. Changes take effect immediately.\n" 13189 " <rx|tx> which direction do you want to change (relative to our module)\n" 13190 " <chan num> is the channel number relative to the device\n" 13191 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"; 13192 return NULL; 13193 case CLI_GENERATE: 13194 return NULL; 13195 } 13196 13197 lock = &iflock; 13198 13199 if (a->argc != 6) 13200 return CLI_SHOWUSAGE; 13201 13202 if (!strcasecmp("rx", a->argv[3])) 13203 tx = 0; /* rx */ 13204 else if (!strcasecmp("tx", a->argv[3])) 13205 tx = 1; /* tx */ 13206 else 13207 return CLI_SHOWUSAGE; 13208 13209 channel = atoi(a->argv[4]); 13210 gain = atof(a->argv[5]); 13211 13212 ast_mutex_lock(lock); 13213 for (tmp = iflist; tmp; tmp = tmp->next) { 13214 13215 if (tmp->channel != channel) 13216 continue; 13217 13218 if (tmp->subs[SUB_REAL].dfd == -1) 13219 break; 13220 13221 if (tx) 13222 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law); 13223 else 13224 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law); 13225 13226 if (res) { 13227 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel); 13228 ast_mutex_unlock(lock); 13229 return CLI_FAILURE; 13230 } 13231 13232 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n", 13233 tx ? "tx" : "rx", gain, channel); 13234 break; 13235 } 13236 ast_mutex_unlock(lock); 13237 13238 if (tmp) 13239 return CLI_SUCCESS; 13240 13241 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 13242 return CLI_FAILURE; 13243 13244 }
static int dahdi_setlaw | ( | int | dfd, | |
int | law | |||
) | [static] |
Definition at line 9682 of file chan_dahdi.c.
09683 { 09684 return ioctl(dfd, DAHDI_SETLAW, &law); 09685 }
static int dahdi_setlinear | ( | int | dfd, | |
int | linear | |||
) | [static] |
Definition at line 1531 of file chan_dahdi.c.
Referenced by dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_write(), send_callerid(), and ss_thread().
01532 { 01533 int res; 01534 res = ioctl(dfd, DAHDI_SETLINEAR, &linear); 01535 if (res) 01536 return res; 01537 return 0; 01538 }
static int dahdi_setoption | ( | struct ast_channel * | chan, | |
int | option, | |||
void * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 3849 of file chan_dahdi.c.
References ast_check_hangup(), ast_debug, ast_dsp_set_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.
03850 { 03851 char *cp; 03852 signed char *scp; 03853 int x; 03854 int idx; 03855 struct dahdi_pvt *p = chan->tech_pvt, *pp; 03856 struct oprmode *oprmode; 03857 03858 03859 /* all supported options require data */ 03860 if (!data || (datalen < 1)) { 03861 errno = EINVAL; 03862 return -1; 03863 } 03864 03865 switch (option) { 03866 case AST_OPTION_TXGAIN: 03867 scp = (signed char *) data; 03868 idx = dahdi_get_index(chan, p, 0); 03869 if (idx < 0) { 03870 ast_log(LOG_WARNING, "No index in TXGAIN?\n"); 03871 return -1; 03872 } 03873 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp); 03874 return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law); 03875 case AST_OPTION_RXGAIN: 03876 scp = (signed char *) data; 03877 idx = dahdi_get_index(chan, p, 0); 03878 if (idx < 0) { 03879 ast_log(LOG_WARNING, "No index in RXGAIN?\n"); 03880 return -1; 03881 } 03882 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp); 03883 return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law); 03884 case AST_OPTION_TONE_VERIFY: 03885 if (!p->dsp) 03886 break; 03887 cp = (char *) data; 03888 switch (*cp) { 03889 case 1: 03890 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name); 03891 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */ 03892 break; 03893 case 2: 03894 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name); 03895 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */ 03896 break; 03897 default: 03898 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name); 03899 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */ 03900 break; 03901 } 03902 break; 03903 case AST_OPTION_TDD: 03904 /* turn on or off TDD */ 03905 cp = (char *) data; 03906 p->mate = 0; 03907 if (!*cp) { /* turn it off */ 03908 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name); 03909 if (p->tdd) 03910 tdd_free(p->tdd); 03911 p->tdd = 0; 03912 break; 03913 } 03914 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n", 03915 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name); 03916 dahdi_disable_ec(p); 03917 /* otherwise, turn it on */ 03918 if (!p->didtdd) { /* if havent done it yet */ 03919 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */ 03920 unsigned char *buf; 03921 int size, res, fd, len; 03922 struct pollfd fds[1]; 03923 03924 buf = mybuf; 03925 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */ 03926 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */ 03927 len = 40000; 03928 idx = dahdi_get_index(chan, p, 0); 03929 if (idx < 0) { 03930 ast_log(LOG_WARNING, "No index in TDD?\n"); 03931 return -1; 03932 } 03933 fd = p->subs[idx].dfd; 03934 while (len) { 03935 if (ast_check_hangup(chan)) 03936 return -1; 03937 size = len; 03938 if (size > READ_SIZE) 03939 size = READ_SIZE; 03940 fds[0].fd = fd; 03941 fds[0].events = POLLPRI | POLLOUT; 03942 fds[0].revents = 0; 03943 res = poll(fds, 1, -1); 03944 if (!res) { 03945 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 03946 continue; 03947 } 03948 /* if got exception */ 03949 if (fds[0].revents & POLLPRI) 03950 return -1; 03951 if (!(fds[0].revents & POLLOUT)) { 03952 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 03953 continue; 03954 } 03955 res = write(fd, buf, size); 03956 if (res != size) { 03957 if (res == -1) return -1; 03958 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 03959 break; 03960 } 03961 len -= size; 03962 buf += size; 03963 } 03964 p->didtdd = 1; /* set to have done it now */ 03965 } 03966 if (*cp == 2) { /* Mate mode */ 03967 if (p->tdd) 03968 tdd_free(p->tdd); 03969 p->tdd = 0; 03970 p->mate = 1; 03971 break; 03972 } 03973 if (!p->tdd) { /* if we dont have one yet */ 03974 p->tdd = tdd_new(); /* allocate one */ 03975 } 03976 break; 03977 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */ 03978 if (!p->dsp) 03979 break; 03980 cp = (char *) data; 03981 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n", 03982 *cp ? "ON" : "OFF", (int) *cp, chan->name); 03983 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax); 03984 break; 03985 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */ 03986 cp = (char *) data; 03987 if (!*cp) { 03988 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name); 03989 x = 0; 03990 dahdi_disable_ec(p); 03991 } else { 03992 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name); 03993 x = 1; 03994 } 03995 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1) 03996 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno)); 03997 break; 03998 case AST_OPTION_OPRMODE: /* Operator services mode */ 03999 oprmode = (struct oprmode *) data; 04000 pp = oprmode->peer->tech_pvt; 04001 p->oprmode = pp->oprmode = 0; 04002 /* setup peers */ 04003 p->oprpeer = pp; 04004 pp->oprpeer = p; 04005 /* setup modes, if any */ 04006 if (oprmode->mode) 04007 { 04008 pp->oprmode = oprmode->mode; 04009 p->oprmode = -oprmode->mode; 04010 } 04011 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n", 04012 oprmode->mode, chan->name,oprmode->peer->name); 04013 break; 04014 case AST_OPTION_ECHOCAN: 04015 cp = (char *) data; 04016 if (*cp) { 04017 ast_debug(1, "Enabling echo cancelation on %s\n", chan->name); 04018 dahdi_enable_ec(p); 04019 } else { 04020 ast_debug(1, "Disabling echo cancelation on %s\n", chan->name); 04021 dahdi_disable_ec(p); 04022 } 04023 break; 04024 } 04025 errno = 0; 04026 04027 return 0; 04028 }
static char* dahdi_show_channel | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12755 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.
12756 { 12757 int channel; 12758 struct dahdi_pvt *tmp = NULL; 12759 struct dahdi_confinfo ci; 12760 struct dahdi_params ps; 12761 int x; 12762 ast_mutex_t *lock; 12763 struct dahdi_pvt *start; 12764 #ifdef HAVE_PRI 12765 char *c; 12766 int trunkgroup; 12767 struct dahdi_pri *pri=NULL; 12768 #endif 12769 switch (cmd) { 12770 case CLI_INIT: 12771 e->command = "dahdi show channel"; 12772 e->usage = 12773 "Usage: dahdi show channel <chan num>\n" 12774 " Detailed information about a given channel\n"; 12775 return NULL; 12776 case CLI_GENERATE: 12777 return NULL; 12778 } 12779 12780 lock = &iflock; 12781 start = iflist; 12782 12783 if (a->argc != 4) 12784 return CLI_SHOWUSAGE; 12785 #ifdef HAVE_PRI 12786 if ((c = strchr(a->argv[3], ':'))) { 12787 if (sscanf(a->argv[3], "%d:%d", &trunkgroup, &channel) != 2) 12788 return CLI_SHOWUSAGE; 12789 if ((trunkgroup < 1) || (channel < 1)) 12790 return CLI_SHOWUSAGE; 12791 for (x = 0; x < NUM_SPANS; x++) { 12792 if (pris[x].trunkgroup == trunkgroup) { 12793 pri = pris + x; 12794 break; 12795 } 12796 } 12797 if (pri) { 12798 start = pri->crvs; 12799 lock = &pri->lock; 12800 } else { 12801 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup); 12802 return CLI_FAILURE; 12803 } 12804 } else 12805 #endif 12806 channel = atoi(a->argv[3]); 12807 12808 ast_mutex_lock(lock); 12809 tmp = start; 12810 while (tmp) { 12811 if (tmp->channel == channel) { 12812 #ifdef HAVE_PRI 12813 if (pri) 12814 ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel); 12815 else 12816 #endif 12817 ast_cli(a->fd, "Channel: %d\n", tmp->channel); 12818 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd); 12819 ast_cli(a->fd, "Span: %d\n", tmp->span); 12820 ast_cli(a->fd, "Extension: %s\n", tmp->exten); 12821 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no"); 12822 ast_cli(a->fd, "Context: %s\n", tmp->context); 12823 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num); 12824 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton); 12825 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name); 12826 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none")); 12827 if (tmp->vars) { 12828 struct ast_variable *v; 12829 ast_cli(a->fd, "Variables:\n"); 12830 for (v = tmp->vars ; v ; v = v->next) 12831 ast_cli(a->fd, " %s = %s\n", v->name, v->value); 12832 } 12833 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy); 12834 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm); 12835 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig)); 12836 ast_cli(a->fd, "Radio: %d\n", tmp->radio); 12837 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>"); 12838 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)" : ""); 12839 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)" : ""); 12840 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)" : ""); 12841 ast_cli(a->fd, "Confno: %d\n", tmp->confno); 12842 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno); 12843 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference); 12844 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no"); 12845 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no"); 12846 if (tmp->busydetect) { 12847 #if defined(BUSYDETECT_TONEONLY) 12848 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n"); 12849 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE) 12850 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n"); 12851 #endif 12852 #ifdef BUSYDETECT_DEBUG 12853 ast_cli(a->fd, " Busy Detector Debug: Enabled\n"); 12854 #endif 12855 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount); 12856 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength); 12857 } 12858 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no"); 12859 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no"); 12860 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas); 12861 ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown"); 12862 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no"); 12863 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no"); 12864 ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no"); 12865 ast_cli(a->fd, "Echo Cancellation:\n"); 12866 12867 if (tmp->echocancel.head.tap_length) { 12868 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length); 12869 for (x = 0; x < tmp->echocancel.head.param_count; x++) { 12870 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value); 12871 } 12872 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF"); 12873 } else { 12874 ast_cli(a->fd, "\tnone\n"); 12875 } 12876 if (tmp->master) 12877 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel); 12878 for (x = 0; x < MAX_SLAVES; x++) { 12879 if (tmp->slaves[x]) 12880 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel); 12881 } 12882 #ifdef HAVE_SS7 12883 if (tmp->ss7) { 12884 ast_cli(a->fd, "CIC: %d\n", tmp->cic); 12885 } 12886 #endif 12887 #ifdef HAVE_PRI 12888 if (tmp->pri) { 12889 ast_cli(a->fd, "PRI Flags: "); 12890 if (tmp->resetting) 12891 ast_cli(a->fd, "Resetting "); 12892 if (tmp->call) 12893 ast_cli(a->fd, "Call "); 12894 if (tmp->bearer) 12895 ast_cli(a->fd, "Bearer "); 12896 ast_cli(a->fd, "\n"); 12897 if (tmp->logicalspan) 12898 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan); 12899 else 12900 ast_cli(a->fd, "PRI Logical Span: Implicit\n"); 12901 } 12902 12903 #endif 12904 memset(&ci, 0, sizeof(ci)); 12905 ps.channo = tmp->channel; 12906 if (tmp->subs[SUB_REAL].dfd > -1) { 12907 memset(&ci, 0, sizeof(ci)); 12908 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 12909 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode); 12910 } 12911 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) { 12912 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No"); 12913 } 12914 memset(&ps, 0, sizeof(ps)); 12915 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 12916 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno)); 12917 } else { 12918 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook"); 12919 } 12920 } 12921 if (ISTRUNK(tmp)) { 12922 ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no"); 12923 if (!ast_strlen_zero(progzone)) 12924 ast_cli(a->fd, "Progress Zone: %s\n", progzone); 12925 ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no"); 12926 if(tmp->busydetect) { 12927 ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount); 12928 if(tmp->busytonelength > 0) { 12929 ast_cli(a->fd, "Busy Pattern:\n"); 12930 ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength); 12931 if (tmp->busyquietlength > 0) 12932 ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength); 12933 else 12934 ast_cli(a->fd, " -- Detect Tone Only\n"); 12935 if(tmp->busyfuzziness > 0) 12936 ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness); 12937 } 12938 } 12939 } 12940 ast_mutex_unlock(lock); 12941 return CLI_SUCCESS; 12942 } 12943 tmp = tmp->next; 12944 } 12945 12946 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 12947 ast_mutex_unlock(lock); 12948 return CLI_FAILURE; 12949 }
static char* dahdi_show_channels | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12631 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.
12632 { 12633 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 12634 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 12635 unsigned int targetnum = 0; 12636 int filtertype = 0; 12637 struct dahdi_pvt *tmp = NULL; 12638 char tmps[20] = ""; 12639 char statestr[20] = ""; 12640 char blockstr[20] = ""; 12641 ast_mutex_t *lock; 12642 struct dahdi_pvt *start; 12643 #ifdef HAVE_PRI 12644 int trunkgroup; 12645 struct dahdi_pri *pri = NULL; 12646 int x; 12647 #endif 12648 switch (cmd) { 12649 case CLI_INIT: 12650 e->command = "dahdi show channels [trunkgroup|group|context]"; 12651 e->usage = 12652 "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n" 12653 " Shows a list of available channels with optional filtering\n" 12654 " <group> must be a number between 0 and 63\n"; 12655 return NULL; 12656 case CLI_GENERATE: 12657 return NULL; 12658 } 12659 12660 lock = &iflock; 12661 start = iflist; 12662 12663 /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */ 12664 12665 if (!((a->argc == 3) || (a->argc == 5))) 12666 return CLI_SHOWUSAGE; 12667 12668 if (a->argc == 5) { 12669 #ifdef HAVE_PRI 12670 if (!strcasecmp(a->argv[3], "trunkgroup")) { 12671 /* this option requires no special handling, so leave filtertype to zero */ 12672 if ((trunkgroup = atoi(a->argv[4])) < 1) 12673 return CLI_SHOWUSAGE; 12674 for (x = 0; x < NUM_SPANS; x++) { 12675 if (pris[x].trunkgroup == trunkgroup) { 12676 pri = pris + x; 12677 break; 12678 } 12679 } 12680 if (pri) { 12681 start = pri->crvs; 12682 lock = &pri->lock; 12683 } else { 12684 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup); 12685 return CLI_FAILURE; 12686 } 12687 } else 12688 #endif 12689 if (!strcasecmp(a->argv[3], "group")) { 12690 targetnum = atoi(a->argv[4]); 12691 if ((targetnum < 0) || (targetnum > 63)) 12692 return CLI_SHOWUSAGE; 12693 targetnum = 1 << targetnum; 12694 filtertype = 1; 12695 } else if (!strcasecmp(a->argv[3], "context")) { 12696 filtertype = 2; 12697 } 12698 } 12699 12700 ast_mutex_lock(lock); 12701 #ifdef HAVE_PRI 12702 ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State"); 12703 #else 12704 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State"); 12705 #endif 12706 12707 tmp = start; 12708 while (tmp) { 12709 if (filtertype) { 12710 switch(filtertype) { 12711 case 1: /* dahdi show channels group <group> */ 12712 if (tmp->group != targetnum) { 12713 tmp = tmp->next; 12714 continue; 12715 } 12716 break; 12717 case 2: /* dahdi show channels context <context> */ 12718 if (strcasecmp(tmp->context, a->argv[4])) { 12719 tmp = tmp->next; 12720 continue; 12721 } 12722 break; 12723 default: 12724 ; 12725 } 12726 } 12727 if (tmp->channel > 0) { 12728 snprintf(tmps, sizeof(tmps), "%d", tmp->channel); 12729 } else 12730 ast_copy_string(tmps, "pseudo", sizeof(tmps)); 12731 12732 if (tmp->locallyblocked) 12733 blockstr[0] = 'L'; 12734 else 12735 blockstr[0] = ' '; 12736 12737 if (tmp->remotelyblocked) 12738 blockstr[1] = 'R'; 12739 else 12740 blockstr[1] = ' '; 12741 12742 blockstr[2] = '\0'; 12743 12744 snprintf(statestr, sizeof(statestr), "%s", "In Service"); 12745 12746 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr); 12747 tmp = tmp->next; 12748 } 12749 ast_mutex_unlock(lock); 12750 return CLI_SUCCESS; 12751 #undef FORMAT 12752 #undef FORMAT2 12753 }
static char* dahdi_show_status | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12988 of file chan_dahdi.c.
References ast_cli(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, errno, ast_cli_args::fd, FORMAT, FORMAT2, and ast_cli_entry::usage.
12989 { 12990 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n" 12991 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n" 12992 int span; 12993 int res; 12994 char alarmstr[50]; 12995 12996 int ctl; 12997 struct dahdi_spaninfo s; 12998 12999 switch (cmd) { 13000 case CLI_INIT: 13001 e->command = "dahdi show status"; 13002 e->usage = 13003 "Usage: dahdi show status\n" 13004 " Shows a list of DAHDI cards with status\n"; 13005 return NULL; 13006 case CLI_GENERATE: 13007 return NULL; 13008 } 13009 ctl = open("/dev/dahdi/ctl", O_RDWR); 13010 if (ctl < 0) { 13011 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno)); 13012 return CLI_FAILURE; 13013 } 13014 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO"); 13015 13016 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 13017 s.spanno = span; 13018 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 13019 if (res) { 13020 continue; 13021 } 13022 alarmstr[0] = '\0'; 13023 if (s.alarms > 0) { 13024 if (s.alarms & DAHDI_ALARM_BLUE) 13025 strcat(alarmstr, "BLU/"); 13026 if (s.alarms & DAHDI_ALARM_YELLOW) 13027 strcat(alarmstr, "YEL/"); 13028 if (s.alarms & DAHDI_ALARM_RED) 13029 strcat(alarmstr, "RED/"); 13030 if (s.alarms & DAHDI_ALARM_LOOPBACK) 13031 strcat(alarmstr, "LB/"); 13032 if (s.alarms & DAHDI_ALARM_RECOVER) 13033 strcat(alarmstr, "REC/"); 13034 if (s.alarms & DAHDI_ALARM_NOTOPEN) 13035 strcat(alarmstr, "NOP/"); 13036 if (!strlen(alarmstr)) 13037 strcat(alarmstr, "UUU/"); 13038 if (strlen(alarmstr)) { 13039 /* Strip trailing / */ 13040 alarmstr[strlen(alarmstr) - 1] = '\0'; 13041 } 13042 } else { 13043 if (s.numchans) 13044 strcpy(alarmstr, "OK"); 13045 else 13046 strcpy(alarmstr, "UNCONFIGURED"); 13047 } 13048 13049 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count 13050 , s.lineconfig & DAHDI_CONFIG_D4 ? "D4" : 13051 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" : 13052 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" : 13053 "CAS" 13054 , s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" : 13055 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" : 13056 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" : 13057 "Unk" 13058 , s.lineconfig & DAHDI_CONFIG_CRC4 ? 13059 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL" 13060 , lbostr[s.lbo] 13061 ); 13062 } 13063 close(ctl); 13064 13065 return CLI_SUCCESS; 13066 #undef FORMAT 13067 #undef FORMAT2 13068 }
static char* dahdi_show_version | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 13070 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.
13071 { 13072 int pseudo_fd = -1; 13073 struct dahdi_versioninfo vi; 13074 13075 switch (cmd) { 13076 case CLI_INIT: 13077 e->command = "dahdi show version"; 13078 e->usage = 13079 "Usage: dahdi show version\n" 13080 " Shows the DAHDI version in use\n"; 13081 return NULL; 13082 case CLI_GENERATE: 13083 return NULL; 13084 } 13085 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) { 13086 ast_cli(a->fd, "Failed to open control file to get version.\n"); 13087 return CLI_SUCCESS; 13088 } 13089 13090 strcpy(vi.version, "Unknown"); 13091 strcpy(vi.echo_canceller, "Unknown"); 13092 13093 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) 13094 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno)); 13095 else 13096 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller); 13097 13098 close(pseudo_fd); 13099 13100 return CLI_SUCCESS; 13101 }
static char* dahdi_sig2str | ( | int | sig | ) | [static] |
Definition at line 1774 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.
01775 { 01776 static char buf[256]; 01777 switch (sig) { 01778 case SIG_EM: 01779 return "E & M Immediate"; 01780 case SIG_EMWINK: 01781 return "E & M Wink"; 01782 case SIG_EM_E1: 01783 return "E & M E1"; 01784 case SIG_FEATD: 01785 return "Feature Group D (DTMF)"; 01786 case SIG_FEATDMF: 01787 return "Feature Group D (MF)"; 01788 case SIG_FEATDMF_TA: 01789 return "Feature Groud D (MF) Tandem Access"; 01790 case SIG_FEATB: 01791 return "Feature Group B (MF)"; 01792 case SIG_E911: 01793 return "E911 (MF)"; 01794 case SIG_FGC_CAMA: 01795 return "FGC/CAMA (Dialpulse)"; 01796 case SIG_FGC_CAMAMF: 01797 return "FGC/CAMA (MF)"; 01798 case SIG_FXSLS: 01799 return "FXS Loopstart"; 01800 case SIG_FXSGS: 01801 return "FXS Groundstart"; 01802 case SIG_FXSKS: 01803 return "FXS Kewlstart"; 01804 case SIG_FXOLS: 01805 return "FXO Loopstart"; 01806 case SIG_FXOGS: 01807 return "FXO Groundstart"; 01808 case SIG_FXOKS: 01809 return "FXO Kewlstart"; 01810 case SIG_PRI: 01811 return "ISDN PRI"; 01812 case SIG_BRI: 01813 return "ISDN BRI Point to Point"; 01814 case SIG_BRI_PTMP: 01815 return "ISDN BRI Point to MultiPoint"; 01816 case SIG_SS7: 01817 return "SS7"; 01818 case SIG_SF: 01819 return "SF (Tone) Immediate"; 01820 case SIG_SFWINK: 01821 return "SF (Tone) Wink"; 01822 case SIG_SF_FEATD: 01823 return "SF (Tone) with Feature Group D (DTMF)"; 01824 case SIG_SF_FEATDMF: 01825 return "SF (Tone) with Feature Group D (MF)"; 01826 case SIG_SF_FEATB: 01827 return "SF (Tone) with Feature Group B (MF)"; 01828 case SIG_GR303FXOKS: 01829 return "GR-303 with FXOKS"; 01830 case SIG_GR303FXSKS: 01831 return "GR-303 with FXSKS"; 01832 case 0: 01833 return "Pseudo"; 01834 default: 01835 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig); 01836 return buf; 01837 } 01838 }
static void dahdi_softhangup_all | ( | void | ) | [static] |
Definition at line 12451 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().
12452 { 12453 struct dahdi_pvt *p; 12454 retry: 12455 ast_mutex_lock(&iflock); 12456 for (p = iflist; p; p = p->next) { 12457 ast_mutex_lock(&p->lock); 12458 if (p->owner && !p->restartpending) { 12459 if (ast_channel_trylock(p->owner)) { 12460 if (option_debug > 2) 12461 ast_verbose("Avoiding deadlock\n"); 12462 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */ 12463 ast_mutex_unlock(&p->lock); 12464 ast_mutex_unlock(&iflock); 12465 goto retry; 12466 } 12467 if (option_debug > 2) 12468 ast_verbose("Softhanging up on %s\n", p->owner->name); 12469 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT); 12470 p->restartpending = 1; 12471 num_restart_pending++; 12472 ast_channel_unlock(p->owner); 12473 } 12474 ast_mutex_unlock(&p->lock); 12475 } 12476 ast_mutex_unlock(&iflock); 12477 }
static void dahdi_train_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2056 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().
02057 { 02058 int x; 02059 int res; 02060 02061 if (p && p->echocanon && p->echotraining) { 02062 x = p->echotraining; 02063 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x); 02064 if (res) 02065 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno)); 02066 else 02067 ast_debug(1, "Engaged echo training on channel %d\n", p->channel); 02068 } else { 02069 ast_debug(1, "No echo training requested\n"); 02070 } 02071 }
static void dahdi_unlink | ( | struct dahdi_pvt * | slave, | |
struct dahdi_pvt * | master, | |||
int | needlock | |||
) | [static] |
Definition at line 4049 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().
04050 { 04051 /* Unlink a specific slave or all slaves/masters from a given master */ 04052 int x; 04053 int hasslaves; 04054 if (!master) 04055 return; 04056 if (needlock) { 04057 ast_mutex_lock(&master->lock); 04058 if (slave) { 04059 while (ast_mutex_trylock(&slave->lock)) { 04060 DEADLOCK_AVOIDANCE(&master->lock); 04061 } 04062 } 04063 } 04064 hasslaves = 0; 04065 for (x = 0; x < MAX_SLAVES; x++) { 04066 if (master->slaves[x]) { 04067 if (!slave || (master->slaves[x] == slave)) { 04068 /* Take slave out of the conference */ 04069 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel); 04070 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL); 04071 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL); 04072 master->slaves[x]->master = NULL; 04073 master->slaves[x] = NULL; 04074 } else 04075 hasslaves = 1; 04076 } 04077 if (!hasslaves) 04078 master->inconference = 0; 04079 } 04080 if (!slave) { 04081 if (master->master) { 04082 /* Take master out of the conference */ 04083 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL); 04084 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL); 04085 hasslaves = 0; 04086 for (x = 0; x < MAX_SLAVES; x++) { 04087 if (master->master->slaves[x] == master) 04088 master->master->slaves[x] = NULL; 04089 else if (master->master->slaves[x]) 04090 hasslaves = 1; 04091 } 04092 if (!hasslaves) 04093 master->master->inconference = 0; 04094 } 04095 master->master = NULL; 04096 } 04097 update_conf(master); 04098 if (needlock) { 04099 if (slave) 04100 ast_mutex_unlock(&slave->lock); 04101 ast_mutex_unlock(&master->lock); 04102 } 04103 }
static int dahdi_wait_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition at line 312 of file chan_dahdi.c.
Referenced by flash_exec(), and ss_thread().
00313 { 00314 int i, j = 0; 00315 i = DAHDI_IOMUX_SIGEVENT; 00316 if (ioctl(fd, DAHDI_IOMUX, &i) == -1) 00317 return -1; 00318 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) 00319 return -1; 00320 return j; 00321 }
static int dahdi_wink | ( | struct dahdi_pvt * | p, | |
int | idx | |||
) | [static] |
Definition at line 6490 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by ss_thread().
06491 { 06492 int j; 06493 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK); 06494 for (;;) 06495 { 06496 /* set bits of interest */ 06497 j = DAHDI_IOMUX_SIGEVENT; 06498 /* wait for some happening */ 06499 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1); 06500 /* exit loop if we have it */ 06501 if (j & DAHDI_IOMUX_SIGEVENT) break; 06502 } 06503 /* get the event info */ 06504 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1); 06505 return 0; 06506 }
static int dahdi_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 5967 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, ast_frame::ptr, PVT_TO_CHANNEL, dahdi_pvt::sig, SIG_PRI, dahdi_pvt::span, ast_frame::subclass, dahdi_pvt::subs, and ast_channel::tech_pvt.
05968 { 05969 struct dahdi_pvt *p = ast->tech_pvt; 05970 int res; 05971 int idx; 05972 idx = dahdi_get_index(ast, p, 0); 05973 if (idx < 0) { 05974 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name); 05975 return -1; 05976 } 05977 05978 #if 0 05979 #ifdef HAVE_PRI 05980 ast_mutex_lock(&p->lock); 05981 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { 05982 if (p->pri->pri) { 05983 if (!pri_grab(p, p->pri)) { 05984 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 05985 pri_rel(p->pri); 05986 } else 05987 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05988 } 05989 p->proceeding=1; 05990 } 05991 ast_mutex_unlock(&p->lock); 05992 #endif 05993 #endif 05994 /* Write a frame of (presumably voice) data */ 05995 if (frame->frametype != AST_FRAME_VOICE) { 05996 if (frame->frametype != AST_FRAME_IMAGE) 05997 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); 05998 return 0; 05999 } 06000 if ((frame->subclass != AST_FORMAT_SLINEAR) && 06001 (frame->subclass != AST_FORMAT_ULAW) && 06002 (frame->subclass != AST_FORMAT_ALAW)) { 06003 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass); 06004 return -1; 06005 } 06006 if (p->dialing) { 06007 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name); 06008 return 0; 06009 } 06010 if (!p->owner) { 06011 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name); 06012 return 0; 06013 } 06014 if (p->cidspill) { 06015 ast_debug(1, "Dropping frame since I've still got a callerid spill\n"); 06016 return 0; 06017 } 06018 /* Return if it's not valid data */ 06019 if (!frame->data.ptr || !frame->datalen) 06020 return 0; 06021 06022 if (frame->subclass == AST_FORMAT_SLINEAR) { 06023 if (!p->subs[idx].linear) { 06024 p->subs[idx].linear = 1; 06025 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 06026 if (res) 06027 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel); 06028 } 06029 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1); 06030 } else { 06031 /* x-law already */ 06032 if (p->subs[idx].linear) { 06033 p->subs[idx].linear = 0; 06034 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 06035 if (res) 06036 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel); 06037 } 06038 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0); 06039 } 06040 if (res < 0) { 06041 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 06042 return -1; 06043 } 06044 return 0; 06045 }
static void destroy_all_channels | ( | void | ) | [static] |
Definition at line 3233 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().
03234 { 03235 int x; 03236 struct dahdi_pvt *p, *pl; 03237 03238 while (num_restart_pending) { 03239 usleep(1); 03240 } 03241 03242 ast_mutex_lock(&iflock); 03243 /* Destroy all the interfaces and free their memory */ 03244 p = iflist; 03245 while (p) { 03246 /* Free any callerid */ 03247 if (p->cidspill) 03248 ast_free(p->cidspill); 03249 pl = p; 03250 p = p->next; 03251 x = pl->channel; 03252 /* Free associated memory */ 03253 if (pl) 03254 destroy_dahdi_pvt(&pl); 03255 if (option_verbose > 2) 03256 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x); 03257 } 03258 iflist = NULL; 03259 ifcount = 0; 03260 ast_mutex_unlock(&iflock); 03261 }
Definition at line 3183 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().
03184 { 03185 int owned = 0; 03186 int i = 0; 03187 03188 if (!now) { 03189 if (cur->owner) { 03190 owned = 1; 03191 } 03192 03193 for (i = 0; i < 3; i++) { 03194 if (cur->subs[i].owner) { 03195 owned = 1; 03196 } 03197 } 03198 if (!owned) { 03199 if (prev) { 03200 prev->next = cur->next; 03201 if (prev->next) 03202 prev->next->prev = prev; 03203 else 03204 ifend = prev; 03205 } else { 03206 iflist = cur->next; 03207 if (iflist) 03208 iflist->prev = NULL; 03209 else 03210 ifend = NULL; 03211 } 03212 destroy_dahdi_pvt(&cur); 03213 } 03214 } else { 03215 if (prev) { 03216 prev->next = cur->next; 03217 if (prev->next) 03218 prev->next->prev = prev; 03219 else 03220 ifend = prev; 03221 } else { 03222 iflist = cur->next; 03223 if (iflist) 03224 iflist->prev = NULL; 03225 else 03226 ifend = NULL; 03227 } 03228 destroy_dahdi_pvt(&cur); 03229 } 03230 return 0; 03231 }
static void destroy_dahdi_pvt | ( | struct dahdi_pvt ** | pvt | ) | [static] |
Definition at line 3161 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().
03162 { 03163 struct dahdi_pvt *p = *pvt; 03164 /* Remove channel from the list */ 03165 if (p->prev) 03166 p->prev->next = p->next; 03167 if (p->next) 03168 p->next->prev = p->prev; 03169 if (p->use_smdi) 03170 ast_smdi_interface_unref(p->smdi_iface); 03171 if (p->mwi_event_sub) 03172 ast_event_unsubscribe(p->mwi_event_sub); 03173 if (p->vars) 03174 ast_variables_destroy(p->vars); 03175 ast_mutex_destroy(&p->lock); 03176 dahdi_close_sub(p, SUB_REAL); 03177 if (p->owner) 03178 p->owner->tech_pvt = NULL; 03179 free(p); 03180 *pvt = NULL; 03181 }
static char* dialplan2str | ( | int | dialplan | ) | [static] |
Definition at line 1765 of file chan_dahdi.c.
Referenced by dahdi_call(), and mkintf().
01766 { 01767 if (dialplan == -1 || dialplan == -2) { 01768 return("Dynamically set dialplan in ISDN"); 01769 } 01770 return (pri_plan2str(dialplan)); 01771 }
static int digit_to_dtmfindex | ( | char | digit | ) | [static] |
Definition at line 1595 of file chan_dahdi.c.
Referenced by dahdi_digit_begin().
01596 { 01597 if (isdigit(digit)) 01598 return DAHDI_TONE_DTMF_BASE + (digit - '0'); 01599 else if (digit >= 'A' && digit <= 'D') 01600 return DAHDI_TONE_DTMF_A + (digit - 'A'); 01601 else if (digit >= 'a' && digit <= 'd') 01602 return DAHDI_TONE_DTMF_A + (digit - 'a'); 01603 else if (digit == '*') 01604 return DAHDI_TONE_DTMF_s; 01605 else if (digit == '#') 01606 return DAHDI_TONE_DTMF_p; 01607 else 01608 return -1; 01609 }
static void disable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4128 of file chan_dahdi.c.
References ast_dsp_set_features(), dahdi_pvt::dsp, DSP_FEATURE_DIGIT_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::hardwaredtmf, dahdi_pvt::ignoredtmf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_bridge().
04129 { 04130 int val; 04131 04132 p->ignoredtmf = 1; 04133 04134 val = 0; 04135 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 04136 04137 if (!p->hardwaredtmf && p->dsp) { 04138 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT; 04139 ast_dsp_set_features(p->dsp, p->dsp_features); 04140 } 04141 }
static void* do_idle_thread | ( | void * | vchan | ) | [static] |
Definition at line 10635 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().
10636 { 10637 struct ast_channel *chan = vchan; 10638 struct dahdi_pvt *pvt = chan->tech_pvt; 10639 struct ast_frame *f; 10640 char ex[80]; 10641 /* Wait up to 30 seconds for an answer */ 10642 int newms, ms = 30000; 10643 ast_verb(3, "Initiating idle call on channel %s\n", chan->name); 10644 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial); 10645 if (ast_call(chan, ex, 0)) { 10646 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex); 10647 ast_hangup(chan); 10648 return NULL; 10649 } 10650 while ((newms = ast_waitfor(chan, ms)) > 0) { 10651 f = ast_read(chan); 10652 if (!f) { 10653 /* Got hangup */ 10654 break; 10655 } 10656 if (f->frametype == AST_FRAME_CONTROL) { 10657 switch (f->subclass) { 10658 case AST_CONTROL_ANSWER: 10659 /* Launch the PBX */ 10660 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten)); 10661 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context)); 10662 chan->priority = 1; 10663 ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context); 10664 ast_pbx_run(chan); 10665 /* It's already hungup, return immediately */ 10666 return NULL; 10667 case AST_CONTROL_BUSY: 10668 ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name); 10669 break; 10670 case AST_CONTROL_CONGESTION: 10671 ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name); 10672 break; 10673 }; 10674 } 10675 ast_frfree(f); 10676 ms = newms; 10677 } 10678 /* Hangup the channel since nothing happend */ 10679 ast_hangup(chan); 10680 return NULL; 10681 }
static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 8306 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::mwisendactive, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::radio, dahdi_pvt::sig, SUB_REAL, and dahdi_pvt::subs.
Referenced by restart_monitor().
08307 { 08308 int count, res, res2, spoint, pollres=0; 08309 struct dahdi_pvt *i; 08310 struct dahdi_pvt *last = NULL; 08311 time_t thispass = 0, lastpass = 0; 08312 int found; 08313 char buf[1024]; 08314 struct pollfd *pfds=NULL; 08315 int lastalloc = -1; 08316 /* This thread monitors all the frame relay interfaces which are not yet in use 08317 (and thus do not have a separate thread) indefinitely */ 08318 /* From here on out, we die whenever asked */ 08319 #if 0 08320 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 08321 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 08322 return NULL; 08323 } 08324 ast_debug(1, "Monitor starting...\n"); 08325 #endif 08326 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08327 08328 for (;;) { 08329 /* Lock the interface list */ 08330 ast_mutex_lock(&iflock); 08331 if (!pfds || (lastalloc != ifcount)) { 08332 if (pfds) { 08333 ast_free(pfds); 08334 pfds = NULL; 08335 } 08336 if (ifcount) { 08337 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) { 08338 ast_mutex_unlock(&iflock); 08339 return NULL; 08340 } 08341 } 08342 lastalloc = ifcount; 08343 } 08344 /* Build the stuff we're going to poll on, that is the socket of every 08345 dahdi_pvt that does not have an associated owner channel */ 08346 count = 0; 08347 i = iflist; 08348 while (i) { 08349 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) { 08350 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive && !i->mwisendactive) { 08351 /* This needs to be watched, as it lacks an owner */ 08352 pfds[count].fd = i->subs[SUB_REAL].dfd; 08353 pfds[count].events = POLLPRI; 08354 pfds[count].revents = 0; 08355 /* If we are monitoring for VMWI or sending CID, we need to 08356 read from the channel as well */ 08357 if (i->cidspill || i->mwimonitor_fsk) 08358 pfds[count].events |= POLLIN; 08359 count++; 08360 } 08361 } 08362 i = i->next; 08363 } 08364 /* Okay, now that we know what to do, release the interface lock */ 08365 ast_mutex_unlock(&iflock); 08366 08367 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 08368 pthread_testcancel(); 08369 /* Wait at least a second for something to happen */ 08370 res = poll(pfds, count, 1000); 08371 pthread_testcancel(); 08372 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08373 08374 /* Okay, poll has finished. Let's see what happened. */ 08375 if (res < 0) { 08376 if ((errno != EAGAIN) && (errno != EINTR)) 08377 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno)); 08378 continue; 08379 } 08380 /* Alright, lock the interface list again, and let's look and see what has 08381 happened */ 08382 ast_mutex_lock(&iflock); 08383 found = 0; 08384 spoint = 0; 08385 lastpass = thispass; 08386 thispass = time(NULL); 08387 i = iflist; 08388 while (i) { 08389 if (thispass != lastpass) { 08390 if (!found && ((i == last) || ((i == iflist) && !last))) { 08391 last = i; 08392 if (last) { 08393 if (!last->mwisendactive && last->sig & __DAHDI_SIG_FXO) { 08394 res = has_voicemail(last); 08395 if (last->msgstate != res) { 08396 08397 /* This channel has a new voicemail state, 08398 * initiate a thread to send an MWI message 08399 */ 08400 pthread_attr_t attr; 08401 pthread_t threadid; 08402 struct mwi_thread_data *mtd; 08403 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res); 08404 if (res2) { 08405 /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */ 08406 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno)); 08407 } 08408 pthread_attr_init(&attr); 08409 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 08410 if ((mtd = ast_calloc(1, sizeof(*mtd)))) { 08411 last->msgstate = res; 08412 mtd->pvt = last; 08413 last->mwisendactive = 1; 08414 if (ast_pthread_create_background(&threadid, &attr, mwi_send_thread, mtd)) { 08415 ast_log(LOG_WARNING, "Unable to start mwi send thread on channel %d\n", last->channel); 08416 ast_free(mtd); 08417 last->mwisendactive = 0; 08418 } 08419 } 08420 found ++; 08421 } 08422 } 08423 last = last->next; 08424 } 08425 } 08426 } 08427 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) { 08428 if (i->radio && !i->owner) 08429 { 08430 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 08431 if (res) 08432 { 08433 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel); 08434 /* Don't hold iflock while handling init events */ 08435 ast_mutex_unlock(&iflock); 08436 handle_init_event(i, res); 08437 ast_mutex_lock(&iflock); 08438 } 08439 i = i->next; 08440 continue; 08441 } 08442 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint); 08443 if (pollres & POLLIN) { 08444 if (i->owner || i->subs[SUB_REAL].owner) { 08445 #ifdef HAVE_PRI 08446 if (!i->pri) 08447 #endif 08448 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd); 08449 i = i->next; 08450 continue; 08451 } 08452 if (!i->cidspill && !i->mwimonitor_fsk) { 08453 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd); 08454 i = i->next; 08455 continue; 08456 } 08457 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf)); 08458 if (res > 0) { 08459 if (i->mwimonitor_fsk) { 08460 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) { 08461 pthread_attr_t attr; 08462 pthread_t threadid; 08463 struct mwi_thread_data *mtd; 08464 08465 pthread_attr_init(&attr); 08466 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 08467 08468 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel); 08469 if ((mtd = ast_calloc(1, sizeof(*mtd)))) { 08470 mtd->pvt = i; 08471 memcpy(mtd->buf, buf, res); 08472 mtd->len = res; 08473 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) { 08474 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel); 08475 ast_free(mtd); 08476 } 08477 i->mwimonitoractive = 1; 08478 } 08479 } 08480 } 08481 } else { 08482 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno)); 08483 } 08484 } 08485 if (pollres & POLLPRI) { 08486 if (i->owner || i->subs[SUB_REAL].owner) { 08487 #ifdef HAVE_PRI 08488 if (!i->pri) 08489 #endif 08490 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd); 08491 i = i->next; 08492 continue; 08493 } 08494 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 08495 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel); 08496 /* Don't hold iflock while handling init events */ 08497 ast_mutex_unlock(&iflock); 08498 handle_init_event(i, res); 08499 ast_mutex_lock(&iflock); 08500 } 08501 } 08502 i=i->next; 08503 } 08504 ast_mutex_unlock(&iflock); 08505 } 08506 /* Never reached */ 08507 return NULL; 08508 08509 }
static void enable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4143 of file chan_dahdi.c.
References ast_dsp_set_features(), CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::dsp, DSP_FEATURE_DIGIT_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::hardwaredtmf, dahdi_pvt::ignoredtmf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_bridge().
04144 { 04145 int val; 04146 04147 if (p->channel == CHAN_PSEUDO) 04148 return; 04149 04150 p->ignoredtmf = 0; 04151 04152 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 04153 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 04154 04155 if (!p->hardwaredtmf && p->dsp) { 04156 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT; 04157 ast_dsp_set_features(p->dsp, p->dsp_features); 04158 } 04159 }
static char* event2str | ( | int | event | ) | [static] |
Definition at line 1755 of file chan_dahdi.c.
References ARRAY_LEN, and buf.
Referenced by __dahdi_exception(), dahdi_handle_event(), mwi_thread(), and ss_thread().
01756 { 01757 static char buf[256]; 01758 if ((event < (ARRAY_LEN(events))) && (event > -1)) 01759 return events[event]; 01760 sprintf(buf, "Event %d", event); /* safe */ 01761 return buf; 01762 }
static void fill_rxgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2125 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_rxgain().
02126 { 02127 int j; 02128 int k; 02129 float linear_gain = pow(10.0, gain / 20.0); 02130 02131 switch (law) { 02132 case DAHDI_LAW_ALAW: 02133 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 02134 if (gain) { 02135 k = (int) (((float) AST_ALAW(j)) * linear_gain); 02136 if (k > 32767) k = 32767; 02137 if (k < -32767) k = -32767; 02138 g->rxgain[j] = AST_LIN2A(k); 02139 } else { 02140 g->rxgain[j] = j; 02141 } 02142 } 02143 break; 02144 case DAHDI_LAW_MULAW: 02145 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 02146 if (gain) { 02147 k = (int) (((float) AST_MULAW(j)) * linear_gain); 02148 if (k > 32767) k = 32767; 02149 if (k < -32767) k = -32767; 02150 g->rxgain[j] = AST_LIN2MU(k); 02151 } else { 02152 g->rxgain[j] = j; 02153 } 02154 } 02155 break; 02156 } 02157 }
static void fill_txgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2091 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_txgain().
02092 { 02093 int j; 02094 int k; 02095 float linear_gain = pow(10.0, gain / 20.0); 02096 02097 switch (law) { 02098 case DAHDI_LAW_ALAW: 02099 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 02100 if (gain) { 02101 k = (int) (((float) AST_ALAW(j)) * linear_gain); 02102 if (k > 32767) k = 32767; 02103 if (k < -32767) k = -32767; 02104 g->txgain[j] = AST_LIN2A(k); 02105 } else { 02106 g->txgain[j] = j; 02107 } 02108 } 02109 break; 02110 case DAHDI_LAW_MULAW: 02111 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 02112 if (gain) { 02113 k = (int) (((float) AST_MULAW(j)) * linear_gain); 02114 if (k > 32767) k = 32767; 02115 if (k < -32767) k = -32767; 02116 g->txgain[j] = AST_LIN2MU(k); 02117 } else { 02118 g->txgain[j] = j; 02119 } 02120 } 02121 break; 02122 } 02123 }
static struct dahdi_pvt* find_channel | ( | int | channel | ) | [static] |
Definition at line 13335 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().
13336 { 13337 struct dahdi_pvt *p = iflist; 13338 while (p) { 13339 if (p->channel == channel) { 13340 break; 13341 } 13342 p = p->next; 13343 } 13344 return p; 13345 }
static int get_alarms | ( | struct dahdi_pvt * | p | ) | [static] |
Checks channel for alarms
p | a channel to check for alarms. |
Definition at line 4587 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().
04588 { 04589 int res; 04590 struct dahdi_spaninfo zi; 04591 struct dahdi_params params; 04592 04593 memset(&zi, 0, sizeof(zi)); 04594 zi.spanno = p->span; 04595 04596 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) { 04597 if (zi.alarms != DAHDI_ALARM_NONE) 04598 return zi.alarms; 04599 } else { 04600 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno)); 04601 return 0; 04602 } 04603 04604 /* No alarms on the span. Check for channel alarms. */ 04605 memset(¶ms, 0, sizeof(params)); 04606 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0) 04607 return params.chan_alarms; 04608 04609 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel); 04610 04611 return DAHDI_ALARM_NONE; 04612 }
static void handle_alarms | ( | struct dahdi_pvt * | p, | |
int | alms | |||
) | [static] |
Definition at line 4680 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().
04681 { 04682 const char *alarm_str = alarm2str(alms); 04683 04684 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); 04685 manager_event(EVENT_FLAG_SYSTEM, "Alarm", 04686 "Alarm: %s\r\n" 04687 "Channel: %d\r\n", 04688 alarm_str, p->channel); 04689 }
static char* handle_dahdi_show_cadences | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12951 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.
12952 { 12953 int i, j; 12954 switch (cmd) { 12955 case CLI_INIT: 12956 e->command = "dahdi show cadences"; 12957 e->usage = 12958 "Usage: dahdi show cadences\n" 12959 " Shows all cadences currently defined\n"; 12960 return NULL; 12961 case CLI_GENERATE: 12962 return NULL; 12963 } 12964 for (i = 0; i < num_cadence; i++) { 12965 char output[1024]; 12966 char tmp[16], tmp2[64]; 12967 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1); 12968 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output)); 12969 12970 for (j = 0; j < 16; j++) { 12971 if (cadences[i].ringcadence[j] == 0) 12972 break; 12973 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]); 12974 if (cidrings[i] * 2 - 1 == j) 12975 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1); 12976 else 12977 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1); 12978 if (j != 0) 12979 strncat(output, ",", sizeof(output) - strlen(output) - 1); 12980 strncat(output, tmp2, sizeof(output) - strlen(output) - 1); 12981 } 12982 ast_cli(a->fd,"%s\n",output); 12983 } 12984 return CLI_SUCCESS; 12985 }
static int handle_init_event | ( | struct dahdi_pvt * | i, | |
int | event | |||
) | [static] |
Definition at line 8075 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.
Referenced by mwi_send_thread().
08076 { 08077 int res; 08078 int thread_spawned = 0; 08079 pthread_t threadid; 08080 struct ast_channel *chan; 08081 08082 /* Handle an event on a given channel for the monitor thread. */ 08083 08084 switch (event) { 08085 case DAHDI_EVENT_NONE: 08086 case DAHDI_EVENT_BITSCHANGED: 08087 break; 08088 case DAHDI_EVENT_WINKFLASH: 08089 case DAHDI_EVENT_RINGOFFHOOK: 08090 if (i->inalarm) break; 08091 if (i->radio) break; 08092 /* Got a ring/answer. What kind of channel are we? */ 08093 switch (i->sig) { 08094 case SIG_FXOLS: 08095 case SIG_FXOGS: 08096 case SIG_FXOKS: 08097 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08098 if (res && (errno == EBUSY)) 08099 break; 08100 if (i->cidspill) { 08101 /* Cancel VMWI spill */ 08102 ast_free(i->cidspill); 08103 i->cidspill = NULL; 08104 } 08105 if (i->immediate) { 08106 dahdi_enable_ec(i); 08107 /* The channel is immediately up. Start right away */ 08108 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 08109 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0); 08110 if (!chan) { 08111 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel); 08112 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08113 if (res < 0) 08114 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08115 } 08116 } else { 08117 /* Check for callerid, digits, etc */ 08118 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0); 08119 if (chan) { 08120 if (has_voicemail(i)) 08121 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 08122 else 08123 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 08124 if (res < 0) 08125 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel); 08126 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 08127 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08128 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08129 if (res < 0) 08130 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08131 ast_hangup(chan); 08132 } else { 08133 thread_spawned = 1; 08134 } 08135 } else 08136 ast_log(LOG_WARNING, "Unable to create channel\n"); 08137 } 08138 break; 08139 case SIG_FXSLS: 08140 case SIG_FXSGS: 08141 case SIG_FXSKS: 08142 i->ringt = i->ringt_base; 08143 /* Fall through */ 08144 case SIG_EMWINK: 08145 case SIG_FEATD: 08146 case SIG_FEATDMF: 08147 case SIG_FEATDMF_TA: 08148 case SIG_E911: 08149 case SIG_FGC_CAMA: 08150 case SIG_FGC_CAMAMF: 08151 case SIG_FEATB: 08152 case SIG_EM: 08153 case SIG_EM_E1: 08154 case SIG_SFWINK: 08155 case SIG_SF_FEATD: 08156 case SIG_SF_FEATDMF: 08157 case SIG_SF_FEATB: 08158 case SIG_SF: 08159 /* Check for callerid, digits, etc */ 08160 if (i->cid_start == CID_START_POLARITY_IN) { 08161 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 08162 } else { 08163 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0); 08164 } 08165 08166 if (!chan) { 08167 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 08168 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 08169 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08170 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08171 if (res < 0) { 08172 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08173 } 08174 ast_hangup(chan); 08175 } else { 08176 thread_spawned = 1; 08177 } 08178 break; 08179 default: 08180 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 08181 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08182 if (res < 0) 08183 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08184 return -1; 08185 } 08186 break; 08187 case DAHDI_EVENT_NOALARM: 08188 i->inalarm = 0; 08189 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel); 08190 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 08191 "Channel: %d\r\n", i->channel); 08192 break; 08193 case DAHDI_EVENT_ALARM: 08194 i->inalarm = 1; 08195 res = get_alarms(i); 08196 handle_alarms(i, res); 08197 /* fall thru intentionally */ 08198 case DAHDI_EVENT_ONHOOK: 08199 if (i->radio) 08200 break; 08201 /* Back on hook. Hang up. */ 08202 switch (i->sig) { 08203 case SIG_FXOLS: 08204 case SIG_FXOGS: 08205 case SIG_FEATD: 08206 case SIG_FEATDMF: 08207 case SIG_FEATDMF_TA: 08208 case SIG_E911: 08209 case SIG_FGC_CAMA: 08210 case SIG_FGC_CAMAMF: 08211 case SIG_FEATB: 08212 case SIG_EM: 08213 case SIG_EM_E1: 08214 case SIG_EMWINK: 08215 case SIG_SF_FEATD: 08216 case SIG_SF_FEATDMF: 08217 case SIG_SF_FEATB: 08218 case SIG_SF: 08219 case SIG_SFWINK: 08220 case SIG_FXSLS: 08221 case SIG_FXSGS: 08222 case SIG_FXSKS: 08223 case SIG_GR303FXSKS: 08224 dahdi_disable_ec(i); 08225 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08226 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08227 break; 08228 case SIG_GR303FXOKS: 08229 case SIG_FXOKS: 08230 dahdi_disable_ec(i); 08231 /* Diddle the battery for the zhone */ 08232 #ifdef ZHONE_HACK 08233 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08234 usleep(1); 08235 #endif 08236 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08237 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08238 break; 08239 case SIG_PRI: 08240 case SIG_SS7: 08241 case SIG_BRI: 08242 case SIG_BRI_PTMP: 08243 dahdi_disable_ec(i); 08244 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08245 break; 08246 default: 08247 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 08248 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08249 return -1; 08250 } 08251 break; 08252 case DAHDI_EVENT_POLARITY: 08253 switch (i->sig) { 08254 case SIG_FXSLS: 08255 case SIG_FXSKS: 08256 case SIG_FXSGS: 08257 /* We have already got a PR before the channel was 08258 created, but it wasn't handled. We need polarity 08259 to be REV for remote hangup detection to work. 08260 At least in Spain */ 08261 if (i->hanguponpolarityswitch) 08262 i->polarity = POLARITY_REV; 08263 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) { 08264 i->polarity = POLARITY_REV; 08265 ast_verb(2, "Starting post polarity " 08266 "CID detection on channel %d\n", 08267 i->channel); 08268 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 08269 if (!chan) { 08270 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 08271 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 08272 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08273 } else { 08274 thread_spawned = 1; 08275 } 08276 } 08277 break; 08278 default: 08279 ast_log(LOG_WARNING, "handle_init_event detected " 08280 "polarity reversal on non-FXO (SIG_FXS) " 08281 "interface %d\n", i->channel); 08282 } 08283 break; 08284 case DAHDI_EVENT_REMOVED: /* destroy channel */ 08285 ast_log(LOG_NOTICE, 08286 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 08287 i->channel); 08288 dahdi_destroy_channel_bynum(i->channel); 08289 break; 08290 case DAHDI_EVENT_NEONMWI_ACTIVE: 08291 if (i->mwimonitor_neon) { 08292 notify_message(i->mailbox, 1); 08293 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox); 08294 } 08295 break; 08296 case DAHDI_EVENT_NEONMWI_INACTIVE: 08297 if (i->mwimonitor_neon) { 08298 notify_message(i->mailbox, 0); 08299 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox); 08300 } 08301 break; 08302 } 08303 return thread_spawned; 08304 }
static char* handle_pri_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12144 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.
12145 { 12146 int span; 12147 int x; 12148 switch (cmd) { 12149 case CLI_INIT: 12150 e->command = "pri debug span"; 12151 e->usage = 12152 "Usage: pri debug span <span>\n" 12153 " Enables debugging on a given PRI span\n"; 12154 return NULL; 12155 case CLI_GENERATE: 12156 return complete_span_4(a->line, a->word, a->pos, a->n); 12157 } 12158 if (a->argc < 4) { 12159 return CLI_SHOWUSAGE; 12160 } 12161 span = atoi(a->argv[3]); 12162 if ((span < 1) || (span > NUM_SPANS)) { 12163 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 12164 return CLI_SUCCESS; 12165 } 12166 if (!pris[span-1].pri) { 12167 ast_cli(a->fd, "No PRI running on span %d\n", span); 12168 return CLI_SUCCESS; 12169 } 12170 for (x = 0; x < NUM_DCHANS; x++) { 12171 if (pris[span-1].dchans[x]) 12172 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 12173 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 12174 PRI_DEBUG_Q921_STATE); 12175 } 12176 ast_cli(a->fd, "Enabled debugging on span %d\n", span); 12177 return CLI_SUCCESS; 12178 }
static char* handle_pri_no_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12182 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.
12183 { 12184 int span; 12185 int x; 12186 switch (cmd) { 12187 case CLI_INIT: 12188 e->command = "pri no debug span"; 12189 e->usage = 12190 "Usage: pri no debug span <span>\n" 12191 " Disables debugging on a given PRI span\n"; 12192 return NULL; 12193 case CLI_GENERATE: 12194 return complete_span_5(a->line, a->word, a->pos, a->n); 12195 } 12196 if (a->argc < 5) 12197 return CLI_SHOWUSAGE; 12198 12199 span = atoi(a->argv[4]); 12200 if ((span < 1) || (span > NUM_SPANS)) { 12201 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS); 12202 return CLI_SUCCESS; 12203 } 12204 if (!pris[span-1].pri) { 12205 ast_cli(a->fd, "No PRI running on span %d\n", span); 12206 return CLI_SUCCESS; 12207 } 12208 for (x = 0; x < NUM_DCHANS; x++) { 12209 if (pris[span-1].dchans[x]) 12210 pri_set_debug(pris[span-1].dchans[x], 0); 12211 } 12212 ast_cli(a->fd, "Disabled debugging on span %d\n", span); 12213 return CLI_SUCCESS; 12214 }
static char* handle_pri_really_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12216 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.
12217 { 12218 int span; 12219 int x; 12220 switch (cmd) { 12221 case CLI_INIT: 12222 e->command = "pri intensive debug span"; 12223 e->usage = 12224 "Usage: pri intensive debug span <span>\n" 12225 " Enables debugging down to the Q.921 level\n"; 12226 return NULL; 12227 case CLI_GENERATE: 12228 return complete_span_5(a->line, a->word, a->pos, a->n); 12229 } 12230 12231 if (a->argc < 5) 12232 return CLI_SHOWUSAGE; 12233 span = atoi(a->argv[4]); 12234 if ((span < 1) || (span > NUM_SPANS)) { 12235 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS); 12236 return CLI_SUCCESS; 12237 } 12238 if (!pris[span-1].pri) { 12239 ast_cli(a->fd, "No PRI running on span %d\n", span); 12240 return CLI_SUCCESS; 12241 } 12242 for (x = 0; x < NUM_DCHANS; x++) { 12243 if (pris[span-1].dchans[x]) 12244 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 12245 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 12246 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE); 12247 } 12248 ast_cli(a->fd, "Enabled EXTENSIVE debugging on span %d\n", span); 12249 return CLI_SUCCESS; 12250 }
static char* handle_pri_set_debug_file | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12108 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.
12109 { 12110 int myfd; 12111 switch (cmd) { 12112 case CLI_INIT: 12113 e->command = "pri set debug file"; 12114 e->usage = "Usage: pri set debug file [output-file]\n" 12115 " Sends PRI debug output to the specified output file\n"; 12116 return NULL; 12117 case CLI_GENERATE: 12118 return NULL; 12119 } 12120 if (a->argc < 5) 12121 return CLI_SHOWUSAGE; 12122 12123 if (ast_strlen_zero(a->argv[4])) 12124 return CLI_SHOWUSAGE; 12125 12126 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE); 12127 if (myfd < 0) { 12128 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]); 12129 return CLI_SUCCESS; 12130 } 12131 12132 ast_mutex_lock(&pridebugfdlock); 12133 12134 if (pridebugfd >= 0) 12135 close(pridebugfd); 12136 12137 pridebugfd = myfd; 12138 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename)); 12139 ast_mutex_unlock(&pridebugfdlock); 12140 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]); 12141 return CLI_SUCCESS; 12142 }
static char* handle_pri_show_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12356 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, pris, and ast_cli_entry::usage.
12357 { 12358 int x; 12359 int span; 12360 int count=0; 12361 int debug=0; 12362 12363 switch (cmd) { 12364 case CLI_INIT: 12365 e->command = "pri show debug"; 12366 e->usage = 12367 "Usage: pri show debug\n" 12368 " Show the debug state of pri spans\n"; 12369 return NULL; 12370 case CLI_GENERATE: 12371 return NULL; 12372 } 12373 12374 for (span = 0; span < NUM_SPANS; span++) { 12375 if (pris[span].pri) { 12376 for (x = 0; x < NUM_DCHANS; x++) { 12377 debug = 0; 12378 if (pris[span].dchans[x]) { 12379 debug = pri_get_debug(pris[span].dchans[x]); 12380 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" ); 12381 count++; 12382 } 12383 } 12384 } 12385 12386 } 12387 ast_mutex_lock(&pridebugfdlock); 12388 if (pridebugfd >= 0) 12389 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename); 12390 ast_mutex_unlock(&pridebugfdlock); 12391 12392 if (!count) 12393 ast_cli(a->fd, "No debug set or no PRI running\n"); 12394 return CLI_SUCCESS; 12395 }
static char* handle_pri_show_span | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12306 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.
12307 { 12308 int span; 12309 int x; 12310 char status[256]; 12311 switch (cmd) { 12312 case CLI_INIT: 12313 e->command = "pri show span"; 12314 e->usage = 12315 "Usage: pri show span <span>\n" 12316 " Displays PRI Information on a given PRI span\n"; 12317 return NULL; 12318 case CLI_GENERATE: 12319 return complete_span_4(a->line, a->word, a->pos, a->n); 12320 } 12321 12322 if (a->argc < 4) 12323 return CLI_SHOWUSAGE; 12324 span = atoi(a->argv[3]); 12325 if ((span < 1) || (span > NUM_SPANS)) { 12326 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS); 12327 return CLI_SUCCESS; 12328 } 12329 if (!pris[span-1].pri) { 12330 ast_cli(a->fd, "No PRI running on span %d\n", span); 12331 return CLI_SUCCESS; 12332 } 12333 for (x = 0; x < NUM_DCHANS; x++) { 12334 if (pris[span-1].dchannels[x]) { 12335 #ifdef PRI_DUMP_INFO_STR 12336 char *info_str = NULL; 12337 #endif 12338 ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]); 12339 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri); 12340 ast_cli(a->fd, "Status: %s\n", status); 12341 #ifdef PRI_DUMP_INFO_STR 12342 info_str = pri_dump_info_str(pris[span-1].pri); 12343 if (info_str) { 12344 ast_cli(a->fd, "%s", info_str); 12345 ast_free(info_str); 12346 } 12347 #else 12348 pri_dump_info(pris[span-1].pri); 12349 #endif 12350 ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No"); 12351 } 12352 } 12353 return CLI_SUCCESS; 12354 }
static char* handle_pri_show_spans | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12273 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.
12274 { 12275 int span; 12276 int x; 12277 char status[256]; 12278 12279 switch (cmd) { 12280 case CLI_INIT: 12281 e->command = "pri show spans"; 12282 e->usage = 12283 "Usage: pri show spans\n" 12284 " Displays PRI Information\n"; 12285 return NULL; 12286 case CLI_GENERATE: 12287 return NULL; 12288 } 12289 12290 if (a->argc != 3) 12291 return CLI_SHOWUSAGE; 12292 12293 for (span = 0; span < NUM_SPANS; span++) { 12294 if (pris[span].pri) { 12295 for (x = 0; x < NUM_DCHANS; x++) { 12296 if (pris[span].dchannels[x]) { 12297 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri); 12298 ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status); 12299 } 12300 } 12301 } 12302 } 12303 return CLI_SUCCESS; 12304 }
static char* handle_pri_unset_debug_file | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12087 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.
12088 { 12089 switch (cmd) { 12090 case CLI_INIT: 12091 e->command = "pri unset debug file"; 12092 e->usage = "Usage: pri unset debug file\n" 12093 " Stop sending debug output to the previously \n" 12094 " specified file\n"; 12095 return NULL; 12096 case CLI_GENERATE: 12097 return NULL; 12098 } 12099 /* Assume it is unset */ 12100 ast_mutex_lock(&pridebugfdlock); 12101 close(pridebugfd); 12102 pridebugfd = -1; 12103 ast_cli(a->fd, "PRI debug output to file disabled\n"); 12104 ast_mutex_unlock(&pridebugfdlock); 12105 return CLI_SUCCESS; 12106 }
static char* handle_pri_version | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12397 of file chan_dahdi.c.
References ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
12398 { 12399 switch (cmd) { 12400 case CLI_INIT: 12401 e->command = "pri show version"; 12402 e->usage = 12403 "Usage: pri show version\n" 12404 "Show libpri version information\n"; 12405 return NULL; 12406 case CLI_GENERATE: 12407 return NULL; 12408 } 12409 12410 ast_cli(a->fd, "libpri version: %s\n", pri_get_version()); 12411 12412 return CLI_SUCCESS; 12413 }
static int has_voicemail | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2365 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_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(), mwi_send_thread(), and vm_execmain().
02366 { 02367 int new_msgs; 02368 struct ast_event *event; 02369 char *mailbox, *context; 02370 02371 mailbox = context = ast_strdupa(p->mailbox); 02372 strsep(&context, "@"); 02373 if (ast_strlen_zero(context)) 02374 context = "default"; 02375 02376 event = ast_event_get_cached(AST_EVENT_MWI, 02377 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 02378 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 02379 AST_EVENT_IE_END); 02380 02381 if (event) { 02382 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 02383 ast_event_destroy(event); 02384 } else 02385 new_msgs = ast_app_has_voicemail(p->mailbox, NULL); 02386 02387 return new_msgs; 02388 }
static int isourconf | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c | |||
) | [static] |
Definition at line 1880 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::confno, and dahdi_subchannel::curconf.
Referenced by conf_del().
01881 { 01882 /* If they're listening to our channel, they're ours */ 01883 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON)) 01884 return 1; 01885 /* If they're a talker on our (allocated) conference, they're ours */ 01886 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER)) 01887 return 1; 01888 return 0; 01889 }
Definition at line 1910 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().
01911 { 01912 int x; 01913 int useslavenative; 01914 struct dahdi_pvt *slave = NULL; 01915 /* Start out optimistic */ 01916 useslavenative = 1; 01917 /* Update conference state in a stateless fashion */ 01918 for (x = 0; x < 3; x++) { 01919 /* Any three-way calling makes slave native mode *definitely* out 01920 of the question */ 01921 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) 01922 useslavenative = 0; 01923 } 01924 /* If we don't have any 3-way calls, check to see if we have 01925 precisely one slave */ 01926 if (useslavenative) { 01927 for (x = 0; x < MAX_SLAVES; x++) { 01928 if (p->slaves[x]) { 01929 if (slave) { 01930 /* Whoops already have a slave! No 01931 slave native and stop right away */ 01932 slave = NULL; 01933 useslavenative = 0; 01934 break; 01935 } else { 01936 /* We have one slave so far */ 01937 slave = p->slaves[x]; 01938 } 01939 } 01940 } 01941 } 01942 /* If no slave, slave native definitely out */ 01943 if (!slave) 01944 useslavenative = 0; 01945 else if (slave->law != p->law) { 01946 useslavenative = 0; 01947 slave = NULL; 01948 } 01949 if (out) 01950 *out = slave; 01951 return useslavenative; 01952 }
static int load_module | ( | void | ) | [static] |
Definition at line 15280 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().
15281 { 15282 int res; 15283 #if defined(HAVE_PRI) || defined(HAVE_SS7) 15284 int y, i; 15285 #endif 15286 15287 #ifdef HAVE_PRI 15288 memset(pris, 0, sizeof(pris)); 15289 for (y = 0; y < NUM_SPANS; y++) { 15290 ast_mutex_init(&pris[y].lock); 15291 pris[y].offset = -1; 15292 pris[y].master = AST_PTHREADT_NULL; 15293 for (i = 0; i < NUM_DCHANS; i++) 15294 pris[y].fds[i] = -1; 15295 } 15296 pri_set_error(dahdi_pri_error); 15297 pri_set_message(dahdi_pri_message); 15298 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec, 15299 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip); 15300 #endif 15301 #ifdef HAVE_SS7 15302 memset(linksets, 0, sizeof(linksets)); 15303 for (y = 0; y < NUM_SPANS; y++) { 15304 ast_mutex_init(&linksets[y].lock); 15305 linksets[y].master = AST_PTHREADT_NULL; 15306 for (i = 0; i < NUM_DCHANS; i++) 15307 linksets[y].fds[i] = -1; 15308 } 15309 ss7_set_error(dahdi_ss7_error); 15310 ss7_set_message(dahdi_ss7_message); 15311 #endif /* HAVE_SS7 */ 15312 res = setup_dahdi(0); 15313 /* Make sure we can register our DAHDI channel type */ 15314 if (res) 15315 return AST_MODULE_LOAD_DECLINE; 15316 if (ast_channel_register(&dahdi_tech)) { 15317 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n"); 15318 __unload_module(); 15319 return AST_MODULE_LOAD_FAILURE; 15320 } 15321 #ifdef HAVE_PRI 15322 ast_string_field_init(&inuse, 16); 15323 ast_string_field_set(&inuse, name, "GR-303InUse"); 15324 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 15325 #endif 15326 #ifdef HAVE_SS7 15327 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli)); 15328 #endif 15329 15330 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli)); 15331 15332 memset(round_robin, 0, sizeof(round_robin)); 15333 ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" ); 15334 ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" ); 15335 ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" ); 15336 ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" ); 15337 ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" ); 15338 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels"); 15339 ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)"); 15340 15341 ast_cond_init(&mwi_thread_complete, NULL); 15342 ast_cond_init(&ss_thread_complete, NULL); 15343 15344 return res; 15345 }
static struct dahdi_pvt* mkintf | ( | int | channel, | |
const struct dahdi_chan_conf * | conf, | |||
struct dahdi_pri * | pri, | |||
int | reloading | |||
) | [static] |
Definition at line 8695 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().
08696 { 08697 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */ 08698 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL; 08699 char fn[80]; 08700 struct dahdi_bufferinfo bi; 08701 08702 int res; 08703 int span = 0; 08704 int here = 0; 08705 int x; 08706 struct dahdi_pvt **wlist; 08707 struct dahdi_pvt **wend; 08708 struct dahdi_params p; 08709 08710 wlist = &iflist; 08711 wend = &ifend; 08712 08713 #ifdef HAVE_PRI 08714 if (pri) { 08715 wlist = &pri->crvs; 08716 wend = &pri->crvend; 08717 } 08718 #endif 08719 08720 tmp2 = *wlist; 08721 prev = NULL; 08722 08723 while (tmp2) { 08724 if (!tmp2->destroy) { 08725 if (tmp2->channel == channel) { 08726 tmp = tmp2; 08727 here = 1; 08728 break; 08729 } 08730 if (tmp2->channel > channel) { 08731 break; 08732 } 08733 } 08734 prev = tmp2; 08735 tmp2 = tmp2->next; 08736 } 08737 08738 if (!here && reloading != 1) { 08739 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { 08740 if (tmp) 08741 free(tmp); 08742 return NULL; 08743 } 08744 ast_mutex_init(&tmp->lock); 08745 ifcount++; 08746 for (x = 0; x < 3; x++) 08747 tmp->subs[x].dfd = -1; 08748 tmp->channel = channel; 08749 } 08750 08751 if (tmp) { 08752 int chan_sig = conf->chan.sig; 08753 if (!here) { 08754 if ((channel != CHAN_PSEUDO) && !pri) { 08755 int count = 0; 08756 snprintf(fn, sizeof(fn), "%d", channel); 08757 /* Open non-blocking */ 08758 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 08759 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 */ 08760 usleep(1); 08761 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 08762 count++; 08763 } 08764 /* Allocate a DAHDI structure */ 08765 if (tmp->subs[SUB_REAL].dfd < 0) { 08766 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); 08767 destroy_dahdi_pvt(&tmp); 08768 return NULL; 08769 } 08770 memset(&p, 0, sizeof(p)); 08771 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 08772 if (res < 0) { 08773 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno)); 08774 destroy_dahdi_pvt(&tmp); 08775 return NULL; 08776 } 08777 if (conf->is_sig_auto) 08778 chan_sig = sigtype_to_signalling(p.sigtype); 08779 if (p.sigtype != (chan_sig & 0x3ffff)) { 08780 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)); 08781 destroy_dahdi_pvt(&tmp); 08782 return NULL; 08783 } 08784 tmp->law = p.curlaw; 08785 tmp->span = p.spanno; 08786 span = p.spanno - 1; 08787 } else { 08788 if (channel == CHAN_PSEUDO) 08789 chan_sig = 0; 08790 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) { 08791 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n"); 08792 return NULL; 08793 } 08794 } 08795 #ifdef HAVE_SS7 08796 if (chan_sig == SIG_SS7) { 08797 struct dahdi_ss7 *ss7; 08798 int clear = 0; 08799 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) { 08800 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 08801 destroy_dahdi_pvt(&tmp); 08802 return NULL; 08803 } 08804 08805 ss7 = ss7_resolve_linkset(cur_linkset); 08806 if (!ss7) { 08807 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset); 08808 destroy_dahdi_pvt(&tmp); 08809 return NULL; 08810 } 08811 if (cur_cicbeginswith < 0) { 08812 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n"); 08813 destroy_dahdi_pvt(&tmp); 08814 return NULL; 08815 } 08816 08817 tmp->cic = cur_cicbeginswith++; 08818 08819 /* DB: Add CIC's DPC information */ 08820 tmp->dpc = cur_defaultdpc; 08821 08822 tmp->ss7 = ss7; 08823 tmp->ss7call = NULL; 08824 ss7->pvts[ss7->numchans++] = tmp; 08825 08826 ast_copy_string(linksets[span].internationalprefix, conf->ss7.internationalprefix, sizeof(linksets[span].internationalprefix)); 08827 ast_copy_string(linksets[span].nationalprefix, conf->ss7.nationalprefix, sizeof(linksets[span].nationalprefix)); 08828 ast_copy_string(linksets[span].subscriberprefix, conf->ss7.subscriberprefix, sizeof(linksets[span].subscriberprefix)); 08829 ast_copy_string(linksets[span].unknownprefix, conf->ss7.unknownprefix, sizeof(linksets[span].unknownprefix)); 08830 08831 linksets[span].called_nai = conf->ss7.called_nai; 08832 linksets[span].calling_nai = conf->ss7.calling_nai; 08833 } 08834 #endif 08835 #ifdef HAVE_PRI 08836 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) { 08837 int offset; 08838 int myswitchtype; 08839 int matchesdchan; 08840 int x,y; 08841 offset = 0; 08842 if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP)) 08843 && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) { 08844 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 08845 destroy_dahdi_pvt(&tmp); 08846 return NULL; 08847 } 08848 if (span >= NUM_SPANS) { 08849 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span); 08850 destroy_dahdi_pvt(&tmp); 08851 return NULL; 08852 } else { 08853 struct dahdi_spaninfo si; 08854 si.spanno = 0; 08855 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) { 08856 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); 08857 destroy_dahdi_pvt(&tmp); 08858 return NULL; 08859 } 08860 /* Store the logical span first based upon the real span */ 08861 tmp->logicalspan = pris[span].prilogicalspan; 08862 pri_resolve_span(&span, channel, (channel - p.chanpos), &si); 08863 if (span < 0) { 08864 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel); 08865 destroy_dahdi_pvt(&tmp); 08866 return NULL; 08867 } 08868 if ((chan_sig == SIG_PRI) || 08869 (chan_sig == SIG_BRI) || 08870 (chan_sig == SIG_BRI_PTMP)) 08871 myswitchtype = conf->pri.switchtype; 08872 else 08873 myswitchtype = PRI_SWITCH_GR303_TMC; 08874 /* Make sure this isn't a d-channel */ 08875 matchesdchan=0; 08876 for (x = 0; x < NUM_SPANS; x++) { 08877 for (y = 0; y < NUM_DCHANS; y++) { 08878 if (pris[x].dchannels[y] == tmp->channel) { 08879 matchesdchan = 1; 08880 break; 08881 } 08882 } 08883 } 08884 offset = p.chanpos; 08885 if (!matchesdchan) { 08886 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) { 08887 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype)); 08888 destroy_dahdi_pvt(&tmp); 08889 return NULL; 08890 } 08891 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) { 08892 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype)); 08893 destroy_dahdi_pvt(&tmp); 08894 return NULL; 08895 } 08896 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) { 08897 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan)); 08898 destroy_dahdi_pvt(&tmp); 08899 return NULL; 08900 } 08901 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) { 08902 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial); 08903 destroy_dahdi_pvt(&tmp); 08904 return NULL; 08905 } 08906 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) { 08907 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext); 08908 destroy_dahdi_pvt(&tmp); 08909 return NULL; 08910 } 08911 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) { 08912 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused); 08913 destroy_dahdi_pvt(&tmp); 08914 return NULL; 08915 } 08916 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) { 08917 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle); 08918 destroy_dahdi_pvt(&tmp); 08919 return NULL; 08920 } 08921 if (pris[span].numchans >= MAX_CHANNELS) { 08922 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, 08923 pris[span].trunkgroup); 08924 destroy_dahdi_pvt(&tmp); 08925 return NULL; 08926 } 08927 08928 pris[span].sig = chan_sig; 08929 pris[span].nodetype = conf->pri.nodetype; 08930 pris[span].switchtype = myswitchtype; 08931 pris[span].nsf = conf->pri.nsf; 08932 pris[span].dialplan = conf->pri.dialplan; 08933 pris[span].localdialplan = conf->pri.localdialplan; 08934 pris[span].pvts[pris[span].numchans++] = tmp; 08935 pris[span].minunused = conf->pri.minunused; 08936 pris[span].minidle = conf->pri.minidle; 08937 pris[span].overlapdial = conf->pri.overlapdial; 08938 #ifdef HAVE_PRI_INBANDDISCONNECT 08939 pris[span].inbanddisconnect = conf->pri.inbanddisconnect; 08940 #endif 08941 pris[span].facilityenable = conf->pri.facilityenable; 08942 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial)); 08943 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext)); 08944 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix)); 08945 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix)); 08946 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix)); 08947 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix)); 08948 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix)); 08949 pris[span].resetinterval = conf->pri.resetinterval; 08950 08951 tmp->pri = &pris[span]; 08952 tmp->prioffset = offset; 08953 tmp->call = NULL; 08954 } else { 08955 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset); 08956 destroy_dahdi_pvt(&tmp); 08957 return NULL; 08958 } 08959 } 08960 } else { 08961 tmp->prioffset = 0; 08962 } 08963 #endif 08964 } else { 08965 chan_sig = tmp->sig; 08966 if (tmp->subs[SUB_REAL].dfd > -1) { 08967 memset(&p, 0, sizeof(p)); 08968 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 08969 } 08970 } 08971 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */ 08972 switch (chan_sig) { 08973 case SIG_FXSKS: 08974 case SIG_FXSLS: 08975 case SIG_EM: 08976 case SIG_EM_E1: 08977 case SIG_EMWINK: 08978 case SIG_FEATD: 08979 case SIG_FEATDMF: 08980 case SIG_FEATDMF_TA: 08981 case SIG_FEATB: 08982 case SIG_E911: 08983 case SIG_SF: 08984 case SIG_SFWINK: 08985 case SIG_FGC_CAMA: 08986 case SIG_FGC_CAMAMF: 08987 case SIG_SF_FEATD: 08988 case SIG_SF_FEATDMF: 08989 case SIG_SF_FEATB: 08990 p.starttime = 250; 08991 break; 08992 } 08993 08994 if (tmp->radio) { 08995 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */ 08996 p.channo = channel; 08997 p.rxwinktime = 1; 08998 p.rxflashtime = 1; 08999 p.starttime = 1; 09000 p.debouncetime = 5; 09001 } 09002 if (!tmp->radio) { 09003 p.channo = channel; 09004 /* Override timing settings based on config file */ 09005 if (conf->timing.prewinktime >= 0) 09006 p.prewinktime = conf->timing.prewinktime; 09007 if (conf->timing.preflashtime >= 0) 09008 p.preflashtime = conf->timing.preflashtime; 09009 if (conf->timing.winktime >= 0) 09010 p.winktime = conf->timing.winktime; 09011 if (conf->timing.flashtime >= 0) 09012 p.flashtime = conf->timing.flashtime; 09013 if (conf->timing.starttime >= 0) 09014 p.starttime = conf->timing.starttime; 09015 if (conf->timing.rxwinktime >= 0) 09016 p.rxwinktime = conf->timing.rxwinktime; 09017 if (conf->timing.rxflashtime >= 0) 09018 p.rxflashtime = conf->timing.rxflashtime; 09019 if (conf->timing.debouncetime >= 0) 09020 p.debouncetime = conf->timing.debouncetime; 09021 } 09022 09023 /* dont set parms on a pseudo-channel (or CRV) */ 09024 if (tmp->subs[SUB_REAL].dfd >= 0) 09025 { 09026 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p); 09027 if (res < 0) { 09028 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno)); 09029 destroy_dahdi_pvt(&tmp); 09030 return NULL; 09031 } 09032 } 09033 #if 1 09034 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) { 09035 memset(&bi, 0, sizeof(bi)); 09036 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 09037 if (!res) { 09038 bi.txbufpolicy = conf->chan.buf_policy; 09039 bi.rxbufpolicy = conf->chan.buf_policy; 09040 bi.numbufs = conf->chan.buf_no; 09041 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 09042 if (res < 0) { 09043 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno)); 09044 } 09045 } else 09046 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno)); 09047 } 09048 #endif 09049 tmp->immediate = conf->chan.immediate; 09050 tmp->transfertobusy = conf->chan.transfertobusy; 09051 if (chan_sig & __DAHDI_SIG_FXS) { 09052 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk; 09053 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon; 09054 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas; 09055 } 09056 tmp->sig = chan_sig; 09057 tmp->outsigmod = conf->chan.outsigmod; 09058 tmp->ringt_base = ringt_base; 09059 tmp->firstradio = 0; 09060 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS)) 09061 tmp->permcallwaiting = conf->chan.callwaiting; 09062 else 09063 tmp->permcallwaiting = 0; 09064 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */ 09065 tmp->destroy = 0; 09066 tmp->drings = conf->chan.drings; 09067 09068 /* 10 is a nice default. */ 09069 if (tmp->drings.ringnum[0].range == 0) 09070 tmp->drings.ringnum[0].range = 10; 09071 if (tmp->drings.ringnum[1].range == 0) 09072 tmp->drings.ringnum[1].range = 10; 09073 if (tmp->drings.ringnum[2].range == 0) 09074 tmp->drings.ringnum[2].range = 10; 09075 09076 tmp->usedistinctiveringdetection = usedistinctiveringdetection; 09077 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid; 09078 tmp->threewaycalling = conf->chan.threewaycalling; 09079 tmp->adsi = conf->chan.adsi; 09080 tmp->use_smdi = conf->chan.use_smdi; 09081 tmp->permhidecallerid = conf->chan.hidecallerid; 09082 tmp->callreturn = conf->chan.callreturn; 09083 tmp->echocancel = conf->chan.echocancel; 09084 tmp->echotraining = conf->chan.echotraining; 09085 tmp->pulse = conf->chan.pulse; 09086 if (tmp->echocancel.head.tap_length) { 09087 tmp->echocanbridged = conf->chan.echocanbridged; 09088 } else { 09089 if (conf->chan.echocanbridged) 09090 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n"); 09091 tmp->echocanbridged = 0; 09092 } 09093 tmp->busydetect = conf->chan.busydetect; 09094 tmp->busycount = conf->chan.busycount; 09095 tmp->busycompare = conf->chan.busycompare; 09096 tmp->busytonelength = conf->chan.busytonelength; 09097 tmp->busyquietlength = conf->chan.busyquietlength; 09098 tmp->busyfuzziness = conf->chan.busyfuzziness; 09099 tmp->silencethreshold = conf->chan.silencethreshold; 09100 tmp->callprogress = conf->chan.callprogress; 09101 tmp->cancallforward = conf->chan.cancallforward; 09102 tmp->dtmfrelax = conf->chan.dtmfrelax; 09103 tmp->callwaiting = tmp->permcallwaiting; 09104 tmp->hidecallerid = tmp->permhidecallerid; 09105 tmp->channel = channel; 09106 tmp->stripmsd = conf->chan.stripmsd; 09107 tmp->use_callerid = conf->chan.use_callerid; 09108 tmp->cid_signalling = conf->chan.cid_signalling; 09109 tmp->cid_start = conf->chan.cid_start; 09110 tmp->dahditrcallerid = conf->chan.dahditrcallerid; 09111 tmp->restrictcid = conf->chan.restrictcid; 09112 tmp->use_callingpres = conf->chan.use_callingpres; 09113 tmp->priindication_oob = conf->chan.priindication_oob; 09114 tmp->priexclusive = conf->chan.priexclusive; 09115 if (tmp->usedistinctiveringdetection) { 09116 if (!tmp->use_callerid) { 09117 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n"); 09118 tmp->use_callerid = 1; 09119 } 09120 } 09121 09122 if (tmp->cid_signalling == CID_SIG_SMDI) { 09123 if (!tmp->use_smdi) { 09124 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n"); 09125 tmp->use_smdi = 1; 09126 } 09127 } 09128 if (tmp->use_smdi) { 09129 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port); 09130 if (!(tmp->smdi_iface)) { 09131 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n"); 09132 tmp->use_smdi = 0; 09133 } 09134 } 09135 09136 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode)); 09137 tmp->amaflags = conf->chan.amaflags; 09138 if (!here) { 09139 tmp->confno = -1; 09140 tmp->propconfno = -1; 09141 } 09142 tmp->canpark = conf->chan.canpark; 09143 tmp->transfer = conf->chan.transfer; 09144 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext)); 09145 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language)); 09146 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret)); 09147 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest)); 09148 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context)); 09149 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num)); 09150 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot)); 09151 tmp->cid_ton = 0; 09152 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name)); 09153 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox)); 09154 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) { 09155 char *mailbox, *context; 09156 mailbox = context = ast_strdupa(tmp->mailbox); 09157 strsep(&context, "@"); 09158 if (ast_strlen_zero(context)) 09159 context = "default"; 09160 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL, 09161 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 09162 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 09163 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, 09164 AST_EVENT_IE_END); 09165 } 09166 tmp->msgstate = -1; 09167 tmp->group = conf->chan.group; 09168 tmp->callgroup = conf->chan.callgroup; 09169 tmp->pickupgroup= conf->chan.pickupgroup; 09170 if (conf->chan.vars) { 09171 tmp->vars = conf->chan.vars; 09172 } 09173 tmp->cid_rxgain = conf->chan.cid_rxgain; 09174 tmp->rxgain = conf->chan.rxgain; 09175 tmp->txgain = conf->chan.txgain; 09176 tmp->tonezone = conf->chan.tonezone; 09177 tmp->onhooktime = time(NULL); 09178 if (tmp->subs[SUB_REAL].dfd > -1) { 09179 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law); 09180 if (tmp->dsp) 09181 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax); 09182 update_conf(tmp); 09183 if (!here) { 09184 if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI) && (chan_sig != SIG_SS7)) 09185 /* Hang it up to be sure it's good */ 09186 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 09187 } 09188 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone); 09189 #ifdef HAVE_PRI 09190 /* the dchannel is down so put the channel in alarm */ 09191 if (tmp->pri && !pri_is_up(tmp->pri)) 09192 tmp->inalarm = 1; 09193 #endif 09194 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) { 09195 tmp->inalarm = 1; 09196 handle_alarms(tmp, res); 09197 } 09198 } 09199 09200 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 09201 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 09202 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 09203 tmp->sendcalleridafter = conf->chan.sendcalleridafter; 09204 if (!here) { 09205 tmp->locallyblocked = tmp->remotelyblocked = 0; 09206 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7)) 09207 tmp->inservice = 0; 09208 else /* We default to in service on protocols that don't have a reset */ 09209 tmp->inservice = 1; 09210 } 09211 } 09212 if (tmp && !here) { 09213 /* nothing on the iflist */ 09214 if (!*wlist) { 09215 *wlist = tmp; 09216 tmp->prev = NULL; 09217 tmp->next = NULL; 09218 *wend = tmp; 09219 } else { 09220 /* at least one member on the iflist */ 09221 struct dahdi_pvt *working = *wlist; 09222 09223 /* check if we maybe have to put it on the begining */ 09224 if (working->channel > tmp->channel) { 09225 tmp->next = *wlist; 09226 tmp->prev = NULL; 09227 (*wlist)->prev = tmp; 09228 *wlist = tmp; 09229 } else { 09230 /* go through all the members and put the member in the right place */ 09231 while (working) { 09232 /* in the middle */ 09233 if (working->next) { 09234 if (working->channel < tmp->channel && working->next->channel > tmp->channel) { 09235 tmp->next = working->next; 09236 tmp->prev = working; 09237 working->next->prev = tmp; 09238 working->next = tmp; 09239 break; 09240 } 09241 } else { 09242 /* the last */ 09243 if (working->channel < tmp->channel) { 09244 working->next = tmp; 09245 tmp->next = NULL; 09246 tmp->prev = working; 09247 *wend = tmp; 09248 break; 09249 } 09250 } 09251 working = working->next; 09252 } 09253 } 09254 } 09255 } 09256 return tmp; 09257 }
static void mwi_event_cb | ( | const struct ast_event * | event, | |
void * | userdata | |||
) | [static] |
Definition at line 294 of file chan_dahdi.c.
Referenced by add_peer_mwi_subs(), build_device(), build_gateway(), and build_peer().
00295 { 00296 /* This module does not handle MWI in an event-based manner. However, it 00297 * subscribes to MWI for each mailbox that is configured so that the core 00298 * knows that we care about it. Then, chan_dahdi will get the MWI from the 00299 * event cache instead of checking the mailbox directly. */ 00300 }
static void* mwi_send_thread | ( | void * | data | ) | [static] |
Definition at line 7901 of file chan_dahdi.c.
References ast_calloc, ast_cond_signal(), ast_free, AST_LAW, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), mwi_thread_data::buf, CID_MWI_TYPE_MDMF_FULL, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_get_event(), dahdi_set_hook(), errno, handle_init_event(), has_voicemail(), MAX_CALLERID_SIZE, MWI_SEND_CLEANUP, MWI_SEND_PAUSE, MWI_SEND_SA, MWI_SEND_SA_WAIT, MWI_SEND_SPILL, mwi_thread_lock, dahdi_pvt::mwisendactive, mwi_thread_data::pvt, quit, SUB_REAL, dahdi_pvt::subs, and vmwi_generate().
07902 { 07903 struct mwi_thread_data *mtd = data; 07904 struct timeval timeout_basis, suspend, now; 07905 int x, i, res; 07906 int num_read; 07907 enum mwisend_states mwi_send_state = MWI_SEND_SPILL; /*Assume FSK only */ 07908 07909 ast_mutex_lock(&mwi_thread_lock); 07910 mwi_thread_count++; 07911 ast_mutex_unlock(&mwi_thread_lock); 07912 07913 /* Determine how this spill is to be sent */ 07914 if(mwisend_rpas) { 07915 mwi_send_state = MWI_SEND_SA; 07916 } 07917 07918 gettimeofday(&timeout_basis, NULL); 07919 07920 mtd->pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE); 07921 if (!mtd->pvt->cidspill) { 07922 mtd->pvt->mwisendactive = 0; 07923 ast_free(mtd); 07924 return NULL; 07925 } 07926 x = DAHDI_FLUSH_BOTH; 07927 res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 07928 x = 3000; 07929 ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x); 07930 mtd->pvt->cidlen = vmwi_generate(mtd->pvt->cidspill, has_voicemail(mtd->pvt), CID_MWI_TYPE_MDMF_FULL, 07931 AST_LAW(mtd->pvt), mtd->pvt->cid_name, mtd->pvt->cid_num, 0); 07932 mtd->pvt->cidpos = 0; 07933 07934 while (MWI_SEND_DONE != mwi_send_state) { 07935 num_read = 0; 07936 gettimeofday(&now, NULL); 07937 if ( 10 < (now.tv_sec - timeout_basis.tv_sec)) { 07938 ast_log(LOG_WARNING, "MWI Send TIMEOUT in state %d\n", mwi_send_state); 07939 goto quit; 07940 } 07941 07942 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07943 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) { 07944 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07945 goto quit; 07946 } 07947 07948 if (i & DAHDI_IOMUX_SIGEVENT) { 07949 /* If we get an event, screen out events that we do not act on. 07950 * Otherwise, let handle_init_event determine what is needed 07951 */ 07952 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd); 07953 switch (res) { 07954 case DAHDI_EVENT_RINGEROFF: 07955 if(mwi_send_state == MWI_SEND_SA_WAIT) { 07956 if (dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) { 07957 ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s\n", strerror(errno)); 07958 goto quit; 07959 } 07960 mwi_send_state = MWI_SEND_PAUSE; 07961 gettimeofday(&suspend, NULL); 07962 } 07963 break; 07964 case DAHDI_EVENT_RINGERON: 07965 case DAHDI_EVENT_HOOKCOMPLETE: 07966 break; 07967 default: 07968 /* Got to the default init event handler */ 07969 if (0 < handle_init_event(mtd->pvt, res)) { 07970 /* I've spawned a thread, get out */ 07971 goto quit; 07972 } 07973 break; 07974 } 07975 } else if (i & DAHDI_IOMUX_READ) { 07976 if ((num_read = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) { 07977 if (errno != ELAST) { 07978 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07979 goto quit; 07980 } 07981 break; 07982 } 07983 } 07984 /* Perform mwi send action */ 07985 switch ( mwi_send_state) { 07986 case MWI_SEND_SA: 07987 /* Send the Ring Pulse Signal Alert */ 07988 res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence); 07989 if (res) { 07990 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno)); 07991 goto quit; 07992 } 07993 dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RING); 07994 mwi_send_state = MWI_SEND_SA_WAIT; 07995 break; 07996 case MWI_SEND_SA_WAIT: /* do nothing until I get RINGEROFF event */ 07997 break; 07998 case MWI_SEND_PAUSE: /* Wait between alert and spill - min of 500 mS*/ 07999 gettimeofday(&now, NULL); 08000 if ((int)(now.tv_sec - suspend.tv_sec) * 1000000 + (int)now.tv_usec - (int)suspend.tv_usec > 500000) { 08001 mwi_send_state = MWI_SEND_SPILL; 08002 } 08003 break; 08004 case MWI_SEND_SPILL: 08005 /* We read some number of bytes. Write an equal amount of data */ 08006 if(0 < num_read) { 08007 if (num_read > mtd->pvt->cidlen - mtd->pvt->cidpos) 08008 num_read = mtd->pvt->cidlen - mtd->pvt->cidpos; 08009 res = write(mtd->pvt->subs[SUB_REAL].dfd, mtd->pvt->cidspill + mtd->pvt->cidpos, num_read); 08010 if (res > 0) { 08011 mtd->pvt->cidpos += res; 08012 if (mtd->pvt->cidpos >= mtd->pvt->cidlen) { 08013 ast_free(mtd->pvt->cidspill); 08014 mtd->pvt->cidspill = NULL; 08015 mtd->pvt->cidpos = 0; 08016 mtd->pvt->cidlen = 0; 08017 mwi_send_state = MWI_SEND_CLEANUP; 08018 } 08019 } else { 08020 ast_log(LOG_WARNING, "MWI Send Write failed: %s\n", strerror(errno)); 08021 goto quit; 08022 } 08023 } 08024 break; 08025 case MWI_SEND_CLEANUP: 08026 /* For now, do nothing */ 08027 mwi_send_state = MWI_SEND_DONE; 08028 break; 08029 default: 08030 /* Should not get here, punt*/ 08031 goto quit; 08032 break; 08033 } 08034 } 08035 08036 quit: 08037 if(mtd->pvt->cidspill) { 08038 ast_free(mtd->pvt->cidspill); 08039 mtd->pvt->cidspill = NULL; 08040 } 08041 mtd->pvt->mwisendactive = 0; 08042 ast_free(mtd); 08043 08044 ast_mutex_lock(&mwi_thread_lock); 08045 mwi_thread_count--; 08046 ast_cond_signal(&mwi_thread_complete); 08047 ast_mutex_unlock(&mwi_thread_lock); 08048 08049 return NULL; 08050 }
static void* mwi_thread | ( | void * | data | ) | [static] |
Definition at line 7758 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.
07759 { 07760 struct mwi_thread_data *mtd = data; 07761 struct callerid_state *cs; 07762 pthread_t threadid; 07763 int samples = 0; 07764 char *name, *number; 07765 int flags; 07766 int i, res; 07767 unsigned int spill_done = 0; 07768 int spill_result = -1; 07769 07770 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) { 07771 mtd->pvt->mwimonitoractive = 0; 07772 07773 return NULL; 07774 } 07775 07776 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt)); 07777 07778 bump_gains(mtd->pvt); 07779 07780 for (;;) { 07781 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07782 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) { 07783 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07784 goto quit; 07785 } 07786 07787 if (i & DAHDI_IOMUX_SIGEVENT) { 07788 struct ast_channel *chan; 07789 07790 /* If we get an event, screen out events that we do not act on. 07791 * Otherwise, cancel and go to the simple switch to let it deal with it. 07792 */ 07793 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd); 07794 07795 switch (res) { 07796 case DAHDI_EVENT_NEONMWI_ACTIVE: 07797 case DAHDI_EVENT_NEONMWI_INACTIVE: 07798 case DAHDI_EVENT_NONE: 07799 case DAHDI_EVENT_BITSCHANGED: 07800 break; 07801 case DAHDI_EVENT_NOALARM: 07802 mtd->pvt->inalarm = 0; 07803 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel); 07804 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 07805 "Channel: %d\r\n", mtd->pvt->channel); 07806 break; 07807 case DAHDI_EVENT_ALARM: 07808 mtd->pvt->inalarm = 1; 07809 res = get_alarms(mtd->pvt); 07810 handle_alarms(mtd->pvt, res); 07811 break; /* What to do on channel alarm ???? -- fall thru intentionally?? */ 07812 default: 07813 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to ss_thread\n", res, event2str(res)); 07814 callerid_free(cs); 07815 07816 restore_gains(mtd->pvt); 07817 mtd->pvt->ringt = mtd->pvt->ringt_base; 07818 07819 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) { 07820 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 07821 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel); 07822 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07823 if (res < 0) 07824 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel); 07825 ast_hangup(chan); 07826 goto quit; 07827 } 07828 goto quit_no_clean; 07829 07830 } else { 07831 ast_log(LOG_WARNING, "Could not create channel to handle call\n"); 07832 } 07833 } 07834 } else if (i & DAHDI_IOMUX_READ) { 07835 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) { 07836 if (errno != ELAST) { 07837 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07838 goto quit; 07839 } 07840 break; 07841 } 07842 samples += res; 07843 if (!spill_done) { 07844 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) { 07845 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno)); 07846 break; 07847 } else if (spill_result) { 07848 spill_done = 1; 07849 } 07850 } else { 07851 /* keep reading data until the energy level drops below the threshold 07852 so we don't get another 'trigger' on the remaining carrier signal 07853 */ 07854 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel) 07855 break; 07856 } 07857 if (samples > (8000 * 4)) /*Termination case - time to give up*/ 07858 break; 07859 } 07860 } 07861 07862 if (spill_result == 1) { 07863 callerid_get(cs, &name, &number, &flags); 07864 if (flags & CID_MSGWAITING) { 07865 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel); 07866 notify_message(mtd->pvt->mailbox, 1); 07867 } else if (flags & CID_NOMSGWAITING) { 07868 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel); 07869 notify_message(mtd->pvt->mailbox, 0); 07870 } else { 07871 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel); 07872 } 07873 } 07874 07875 07876 quit: 07877 callerid_free(cs); 07878 07879 restore_gains(mtd->pvt); 07880 07881 quit_no_clean: 07882 mtd->pvt->mwimonitoractive = 0; 07883 07884 ast_free(mtd); 07885 07886 return NULL; 07887 }
static int my_dahdi_write | ( | struct dahdi_pvt * | p, | |
unsigned char * | buf, | |||
int | len, | |||
int | idx, | |||
int | linear | |||
) | [static] |
Definition at line 5945 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().
05946 { 05947 int sent=0; 05948 int size; 05949 int res; 05950 int fd; 05951 fd = p->subs[idx].dfd; 05952 while (len) { 05953 size = len; 05954 if (size > (linear ? READ_SIZE * 2 : READ_SIZE)) 05955 size = (linear ? READ_SIZE * 2 : READ_SIZE); 05956 res = write(fd, buf, size); 05957 if (res != size) { 05958 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 05959 return sent; 05960 } 05961 len -= size; 05962 buf += size; 05963 } 05964 return sent; 05965 }
static int my_getsigstr | ( | struct ast_channel * | chan, | |
char * | str, | |||
const char * | term, | |||
int | ms | |||
) | [static] |
Definition at line 6471 of file chan_dahdi.c.
References ast_waitfordigit(), and chan.
Referenced by ss_thread().
06472 { 06473 char c; 06474 06475 *str = 0; /* start with empty output buffer */ 06476 for (;;) 06477 { 06478 /* Wait for the first digit (up to specified ms). */ 06479 c = ast_waitfordigit(chan, ms); 06480 /* if timeout, hangup or error, return as such */ 06481 if (c < 1) 06482 return c; 06483 *str++ = c; 06484 *str = 0; 06485 if (strchr(term, c)) 06486 return 1; 06487 } 06488 }
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 2304 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().
02305 { 02306 char s[sizeof(mwimonitornotify) + 80]; 02307 struct ast_event *event; 02308 char *mailbox, *context; 02309 02310 /* Strip off @default */ 02311 context = mailbox = ast_strdupa(mailbox_full); 02312 strsep(&context, "@"); 02313 if (ast_strlen_zero(context)) 02314 context = "default"; 02315 02316 if (!(event = ast_event_new(AST_EVENT_MWI, 02317 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 02318 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 02319 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 02320 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 02321 AST_EVENT_IE_END))) { 02322 return; 02323 } 02324 02325 ast_event_queue_and_cache(event); 02326 02327 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) { 02328 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot); 02329 ast_safe_system(s); 02330 } 02331 }
static int pri_active_dchan_fd | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3352 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().
03353 { 03354 int x = -1; 03355 03356 for (x = 0; x < NUM_DCHANS; x++) { 03357 if ((pri->dchans[x] == pri->pri)) 03358 break; 03359 } 03360 03361 return pri->fds[x]; 03362 }
static int pri_assign_bearer | ( | struct dahdi_pvt * | crv, | |
struct dahdi_pri * | pri, | |||
struct dahdi_pvt * | bearer | |||
) | [static] |
Definition at line 3322 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().
03323 { 03324 bearer->owner = &inuse; 03325 bearer->realcall = crv; 03326 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd; 03327 if (crv->subs[SUB_REAL].owner) 03328 ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd); 03329 crv->bearer = bearer; 03330 crv->call = bearer->call; 03331 crv->pri = pri; 03332 return 0; 03333 }
static int pri_check_restart | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 10764 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().
10765 { 10766 do { 10767 pri->resetpos++; 10768 } while ((pri->resetpos < pri->numchans) && 10769 (!pri->pvts[pri->resetpos] || 10770 pri->pvts[pri->resetpos]->call || 10771 pri->pvts[pri->resetpos]->resetting)); 10772 if (pri->resetpos < pri->numchans) { 10773 /* Mark the channel as resetting and restart it */ 10774 pri->pvts[pri->resetpos]->resetting = 1; 10775 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos])); 10776 } else { 10777 pri->resetting = 0; 10778 time(&pri->lastreset); 10779 } 10780 return 0; 10781 }
static int pri_create_spanmap | ( | int | span, | |
int | trunkgroup, | |||
int | logicalspan | |||
) | [static] |
Definition at line 8647 of file chan_dahdi.c.
References ast_log(), dahdi_pri::mastertrunkgroup, dahdi_pri::prilogicalspan, and pris.
Referenced by setup_dahdi().
08648 { 08649 if (pris[span].mastertrunkgroup) { 08650 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); 08651 return -1; 08652 } 08653 pris[span].mastertrunkgroup = trunkgroup; 08654 pris[span].prilogicalspan = logicalspan; 08655 return 0; 08656 }
static int pri_create_trunkgroup | ( | int | trunkgroup, | |
int * | channels | |||
) | [static] |
Definition at line 8584 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().
08585 { 08586 struct dahdi_spaninfo si; 08587 struct dahdi_params p; 08588 int fd; 08589 int span; 08590 int ospan=0; 08591 int x,y; 08592 for (x = 0; x < NUM_SPANS; x++) { 08593 if (pris[x].trunkgroup == trunkgroup) { 08594 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]); 08595 return -1; 08596 } 08597 } 08598 for (y = 0; y < NUM_DCHANS; y++) { 08599 if (!channels[y]) 08600 break; 08601 memset(&si, 0, sizeof(si)); 08602 memset(&p, 0, sizeof(p)); 08603 fd = open("/dev/dahdi/channel", O_RDWR); 08604 if (fd < 0) { 08605 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno)); 08606 return -1; 08607 } 08608 x = channels[y]; 08609 if (ioctl(fd, DAHDI_SPECIFY, &x)) { 08610 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno)); 08611 close(fd); 08612 return -1; 08613 } 08614 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) { 08615 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno)); 08616 return -1; 08617 } 08618 if (ioctl(fd, DAHDI_SPANSTAT, &si)) { 08619 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno)); 08620 close(fd); 08621 return -1; 08622 } 08623 span = p.spanno - 1; 08624 if (pris[span].trunkgroup) { 08625 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup); 08626 close(fd); 08627 return -1; 08628 } 08629 if (pris[span].pvts[0]) { 08630 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1); 08631 close(fd); 08632 return -1; 08633 } 08634 if (!y) { 08635 pris[span].trunkgroup = trunkgroup; 08636 pris[span].offset = channels[y] - p.chanpos; 08637 ospan = span; 08638 } 08639 pris[ospan].dchannels[y] = channels[y]; 08640 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED; 08641 pris[span].span = span + 1; 08642 close(fd); 08643 } 08644 return 0; 08645 }
static void* pri_dchannel | ( | void * | vpri | ) | [static] |
Definition at line 10858 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.
10859 { 10860 struct dahdi_pri *pri = vpri; 10861 pri_event *e; 10862 struct pollfd fds[NUM_DCHANS]; 10863 int res; 10864 int chanpos = 0; 10865 int x; 10866 int haveidles; 10867 int activeidles; 10868 int nextidle = -1; 10869 struct ast_channel *c; 10870 struct timeval tv, lowest, *next; 10871 struct timeval lastidle = ast_tvnow(); 10872 int doidling=0; 10873 char *cc; 10874 char idlen[80]; 10875 struct ast_channel *idle; 10876 pthread_t p; 10877 time_t t; 10878 int i, which=-1; 10879 int numdchans; 10880 int cause=0; 10881 struct dahdi_pvt *crv; 10882 pthread_t threadid; 10883 char ani2str[6]; 10884 char plancallingnum[256]; 10885 char plancallingani[256]; 10886 char calledtonstr[10]; 10887 10888 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 10889 10890 gettimeofday(&lastidle, NULL); 10891 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) { 10892 /* Need to do idle dialing, check to be sure though */ 10893 cc = strchr(pri->idleext, '@'); 10894 if (cc) { 10895 *cc = '\0'; 10896 cc++; 10897 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext)); 10898 #if 0 10899 /* Extensions may not be loaded yet */ 10900 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL)) 10901 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext); 10902 else 10903 #endif 10904 doidling = 1; 10905 } else 10906 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext); 10907 } 10908 for (;;) { 10909 for (i = 0; i < NUM_DCHANS; i++) { 10910 if (!pri->dchannels[i]) 10911 break; 10912 fds[i].fd = pri->fds[i]; 10913 fds[i].events = POLLIN | POLLPRI; 10914 fds[i].revents = 0; 10915 } 10916 numdchans = i; 10917 time(&t); 10918 ast_mutex_lock(&pri->lock); 10919 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) { 10920 if (pri->resetting && pri_is_up(pri)) { 10921 if (pri->resetpos < 0) 10922 pri_check_restart(pri); 10923 } else { 10924 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) { 10925 pri->resetting = 1; 10926 pri->resetpos = -1; 10927 } 10928 } 10929 } 10930 /* Look for any idle channels if appropriate */ 10931 if (doidling && pri_is_up(pri)) { 10932 nextidle = -1; 10933 haveidles = 0; 10934 activeidles = 0; 10935 for (x = pri->numchans; x >= 0; x--) { 10936 if (pri->pvts[x] && !pri->pvts[x]->owner && 10937 !pri->pvts[x]->call) { 10938 if (haveidles < pri->minunused) { 10939 haveidles++; 10940 } else if (!pri->pvts[x]->resetting) { 10941 nextidle = x; 10942 break; 10943 } 10944 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) 10945 activeidles++; 10946 } 10947 if (nextidle > -1) { 10948 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) { 10949 /* Don't create a new idle call more than once per second */ 10950 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial); 10951 idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause); 10952 if (idle) { 10953 pri->pvts[nextidle]->isidlecall = 1; 10954 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) { 10955 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name); 10956 dahdi_hangup(idle); 10957 } 10958 } else 10959 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen); 10960 lastidle = ast_tvnow(); 10961 } 10962 } else if ((haveidles < pri->minunused) && 10963 (activeidles > pri->minidle)) { 10964 /* Mark something for hangup if there is something 10965 that can be hungup */ 10966 for (x = pri->numchans; x >= 0; x--) { 10967 /* find a candidate channel */ 10968 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) { 10969 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10970 haveidles++; 10971 /* Stop if we have enough idle channels or 10972 can't spare any more active idle ones */ 10973 if ((haveidles >= pri->minunused) || 10974 (activeidles <= pri->minidle)) 10975 break; 10976 } 10977 } 10978 } 10979 } 10980 /* Start with reasonable max */ 10981 lowest = ast_tv(60, 0); 10982 for (i = 0; i < NUM_DCHANS; i++) { 10983 /* Find lowest available d-channel */ 10984 if (!pri->dchannels[i]) 10985 break; 10986 if ((next = pri_schedule_next(pri->dchans[i]))) { 10987 /* We need relative time here */ 10988 tv = ast_tvsub(*next, ast_tvnow()); 10989 if (tv.tv_sec < 0) { 10990 tv = ast_tv(0,0); 10991 } 10992 if (doidling || pri->resetting) { 10993 if (tv.tv_sec > 1) { 10994 tv = ast_tv(1, 0); 10995 } 10996 } else { 10997 if (tv.tv_sec > 60) { 10998 tv = ast_tv(60, 0); 10999 } 11000 } 11001 } else if (doidling || pri->resetting) { 11002 /* Make sure we stop at least once per second if we're 11003 monitoring idle channels */ 11004 tv = ast_tv(1,0); 11005 } else { 11006 /* Don't poll for more than 60 seconds */ 11007 tv = ast_tv(60, 0); 11008 } 11009 if (!i || ast_tvcmp(tv, lowest) < 0) { 11010 lowest = tv; 11011 } 11012 } 11013 ast_mutex_unlock(&pri->lock); 11014 11015 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 11016 pthread_testcancel(); 11017 e = NULL; 11018 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000); 11019 pthread_testcancel(); 11020 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 11021 11022 ast_mutex_lock(&pri->lock); 11023 if (!res) { 11024 for (which = 0; which < NUM_DCHANS; which++) { 11025 if (!pri->dchans[which]) 11026 break; 11027 /* Just a timeout, run the scheduler */ 11028 e = pri_schedule_run(pri->dchans[which]); 11029 if (e) 11030 break; 11031 } 11032 } else if (res > -1) { 11033 for (which = 0; which < NUM_DCHANS; which++) { 11034 if (!pri->dchans[which]) 11035 break; 11036 if (fds[which].revents & POLLPRI) { 11037 /* Check for an event */ 11038 x = 0; 11039 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x); 11040 if (x) { 11041 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); 11042 manager_event(EVENT_FLAG_SYSTEM, "PRIEvent", 11043 "PRIEvent: %s\r\n" 11044 "PRIEventCode: %d\r\n" 11045 "D-channel: %s\r\n" 11046 "Span: %d\r\n", 11047 event2str(x), 11048 x, 11049 pri_order(which), 11050 pri->span 11051 ); 11052 } 11053 /* Keep track of alarm state */ 11054 if (x == DAHDI_EVENT_ALARM) { 11055 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP); 11056 pri_find_dchan(pri); 11057 } else if (x == DAHDI_EVENT_NOALARM) { 11058 pri->dchanavail[which] |= DCHAN_NOTINALARM; 11059 pri_restart(pri->dchans[which]); 11060 } 11061 11062 ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span); 11063 } else if (fds[which].revents & POLLIN) { 11064 e = pri_check_event(pri->dchans[which]); 11065 } 11066 if (e) 11067 break; 11068 } 11069 } else if (errno != EINTR) 11070 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno)); 11071 11072 if (e) { 11073 if (pri->debug) 11074 pri_dump_event(pri->dchans[which], e); 11075 11076 if (e->e != PRI_EVENT_DCHAN_DOWN) { 11077 if (!(pri->dchanavail[which] & DCHAN_UP)) { 11078 ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span); 11079 } 11080 pri->dchanavail[which] |= DCHAN_UP; 11081 } else { 11082 if (pri->dchanavail[which] & DCHAN_UP) { 11083 ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span); 11084 } 11085 pri->dchanavail[which] &= ~DCHAN_UP; 11086 } 11087 11088 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which])) 11089 /* Must be an NFAS group that has the secondary dchan active */ 11090 pri->pri = pri->dchans[which]; 11091 11092 switch (e->e) { 11093 case PRI_EVENT_DCHAN_UP: 11094 if (!pri->pri) pri_find_dchan(pri); 11095 11096 /* Note presense of D-channel */ 11097 time(&pri->lastreset); 11098 11099 /* Restart in 5 seconds */ 11100 if (pri->resetinterval > -1) { 11101 pri->lastreset -= pri->resetinterval; 11102 pri->lastreset += 5; 11103 } 11104 pri->resetting = 0; 11105 /* Take the channels from inalarm condition */ 11106 for (i = 0; i < pri->numchans; i++) 11107 if (pri->pvts[i]) { 11108 pri->pvts[i]->inalarm = 0; 11109 } 11110 break; 11111 case PRI_EVENT_DCHAN_DOWN: 11112 pri_find_dchan(pri); 11113 if (!pri_is_up(pri)) { 11114 pri->resetting = 0; 11115 /* Hangup active channels and put them in alarm mode */ 11116 for (i = 0; i < pri->numchans; i++) { 11117 struct dahdi_pvt *p = pri->pvts[i]; 11118 if (p) { 11119 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 11120 /* T309 is not enabled : hangup calls when alarm occurs */ 11121 if (p->call) { 11122 if (p->pri && p->pri->pri) { 11123 pri_hangup(p->pri->pri, p->call, -1); 11124 pri_destroycall(p->pri->pri, p->call); 11125 p->call = NULL; 11126 } else 11127 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n"); 11128 } 11129 if (p->realcall) { 11130 pri_hangup_all(p->realcall, pri); 11131 } else if (p->owner) 11132 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11133 } 11134 p->inalarm = 1; 11135 } 11136 } 11137 } 11138 break; 11139 case PRI_EVENT_RESTART: 11140 if (e->restart.channel > -1) { 11141 chanpos = pri_find_principle(pri, e->restart.channel); 11142 if (chanpos < 0) 11143 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 11144 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 11145 else { 11146 ast_verb(3, "B-channel %d/%d restarted on span %d\n", 11147 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 11148 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11149 if (pri->pvts[chanpos]->call) { 11150 pri_destroycall(pri->pri, pri->pvts[chanpos]->call); 11151 pri->pvts[chanpos]->call = NULL; 11152 } 11153 /* Force soft hangup if appropriate */ 11154 if (pri->pvts[chanpos]->realcall) 11155 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11156 else if (pri->pvts[chanpos]->owner) 11157 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11158 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11159 } 11160 } else { 11161 ast_verb(3, "Restart on requested on entire span %d\n", pri->span); 11162 for (x = 0; x < pri->numchans; x++) 11163 if (pri->pvts[x]) { 11164 ast_mutex_lock(&pri->pvts[x]->lock); 11165 if (pri->pvts[x]->call) { 11166 pri_destroycall(pri->pri, pri->pvts[x]->call); 11167 pri->pvts[x]->call = NULL; 11168 } 11169 if (pri->pvts[chanpos]->realcall) 11170 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11171 else if (pri->pvts[x]->owner) 11172 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11173 ast_mutex_unlock(&pri->pvts[x]->lock); 11174 } 11175 } 11176 break; 11177 case PRI_EVENT_KEYPAD_DIGIT: 11178 chanpos = pri_find_principle(pri, e->digit.channel); 11179 if (chanpos < 0) { 11180 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 11181 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span); 11182 } else { 11183 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call); 11184 if (chanpos > -1) { 11185 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11186 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */ 11187 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) { 11188 /* how to do that */ 11189 int digitlen = strlen(e->digit.digits); 11190 char digit; 11191 int i; 11192 for (i = 0; i < digitlen; i++) { 11193 digit = e->digit.digits[i]; 11194 { 11195 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 11196 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11197 } 11198 } 11199 } 11200 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11201 } 11202 } 11203 break; 11204 11205 case PRI_EVENT_INFO_RECEIVED: 11206 chanpos = pri_find_principle(pri, e->ring.channel); 11207 if (chanpos < 0) { 11208 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 11209 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11210 } else { 11211 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call); 11212 if (chanpos > -1) { 11213 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11214 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */ 11215 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) { 11216 /* how to do that */ 11217 int digitlen = strlen(e->ring.callednum); 11218 char digit; 11219 int i; 11220 for (i = 0; i < digitlen; i++) { 11221 digit = e->ring.callednum[i]; 11222 { 11223 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 11224 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11225 } 11226 } 11227 } 11228 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11229 } 11230 } 11231 break; 11232 case PRI_EVENT_RING: 11233 crv = NULL; 11234 if (e->ring.channel == -1) 11235 chanpos = pri_find_empty_chan(pri, 1); 11236 else 11237 chanpos = pri_find_principle(pri, e->ring.channel); 11238 /* if no channel specified find one empty */ 11239 if (chanpos < 0) { 11240 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 11241 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11242 } else { 11243 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11244 if (pri->pvts[chanpos]->owner) { 11245 if (pri->pvts[chanpos]->call == e->ring.call) { 11246 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 11247 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11248 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11249 break; 11250 } else { 11251 /* This is where we handle initial glare */ 11252 ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n", 11253 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11254 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11255 chanpos = -1; 11256 } 11257 } 11258 if (chanpos > -1) 11259 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11260 } 11261 if ((chanpos < 0) && (e->ring.flexible)) 11262 chanpos = pri_find_empty_chan(pri, 1); 11263 if (chanpos > -1) { 11264 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11265 if (pri->switchtype == PRI_SWITCH_GR303_TMC) { 11266 /* Should be safe to lock CRV AFAIK while bearer is still locked */ 11267 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL)); 11268 if (crv) 11269 ast_mutex_lock(&crv->lock); 11270 if (!crv || crv->owner) { 11271 pri->pvts[chanpos]->call = NULL; 11272 if (crv) { 11273 if (crv->owner) 11274 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11275 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); 11276 } else 11277 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); 11278 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE); 11279 if (crv) 11280 ast_mutex_unlock(&crv->lock); 11281 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11282 break; 11283 } 11284 } 11285 pri->pvts[chanpos]->call = e->ring.call; 11286 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan); 11287 if (pri->pvts[chanpos]->use_callerid) { 11288 ast_shrink_phone_number(plancallingnum); 11289 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num)); 11290 #ifdef PRI_ANI 11291 if (!ast_strlen_zero(e->ring.callingani)) { 11292 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani); 11293 ast_shrink_phone_number(plancallingani); 11294 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani)); 11295 } else { 11296 pri->pvts[chanpos]->cid_ani[0] = '\0'; 11297 } 11298 #endif 11299 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name)); 11300 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */ 11301 } else { 11302 pri->pvts[chanpos]->cid_num[0] = '\0'; 11303 pri->pvts[chanpos]->cid_ani[0] = '\0'; 11304 pri->pvts[chanpos]->cid_name[0] = '\0'; 11305 pri->pvts[chanpos]->cid_ton = 0; 11306 } 11307 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri, 11308 e->ring.redirectingnum, e->ring.callingplanrdnis); 11309 /* If immediate=yes go to s|1 */ 11310 if (pri->pvts[chanpos]->immediate) { 11311 ast_verb(3, "Going to extension s|1 because of immediate=yes\n"); 11312 pri->pvts[chanpos]->exten[0] = 's'; 11313 pri->pvts[chanpos]->exten[1] = '\0'; 11314 } 11315 /* Get called number */ 11316 else if (!ast_strlen_zero(e->ring.callednum)) { 11317 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten)); 11318 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 11319 } else if (pri->overlapdial) 11320 pri->pvts[chanpos]->exten[0] = '\0'; 11321 else { 11322 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */ 11323 pri->pvts[chanpos]->exten[0] = 's'; 11324 pri->pvts[chanpos]->exten[1] = '\0'; 11325 } 11326 /* Set DNID on all incoming calls -- even immediate */ 11327 if (!ast_strlen_zero(e->ring.callednum)) 11328 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 11329 /* No number yet, but received "sending complete"? */ 11330 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) { 11331 ast_verb(3, "Going to extension s|1 because of Complete received\n"); 11332 pri->pvts[chanpos]->exten[0] = 's'; 11333 pri->pvts[chanpos]->exten[1] = '\0'; 11334 } 11335 /* Make sure extension exists (or in overlap dial mode, can exist) */ 11336 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) || 11337 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 11338 /* Setup law */ 11339 int law; 11340 if (pri->switchtype != PRI_SWITCH_GR303_TMC) { 11341 /* Set to audio mode at this point */ 11342 law = 1; 11343 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1) 11344 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno)); 11345 } 11346 if (e->ring.layer1 == PRI_LAYER_1_ALAW) 11347 law = DAHDI_LAW_ALAW; 11348 else 11349 law = DAHDI_LAW_MULAW; 11350 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law); 11351 if (res < 0) 11352 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel); 11353 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law); 11354 if (res < 0) 11355 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel); 11356 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 11357 /* Just announce proceeding */ 11358 pri->pvts[chanpos]->proceeding = 1; 11359 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0); 11360 } else { 11361 if (pri->switchtype != PRI_SWITCH_GR303_TMC) 11362 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 11363 else 11364 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 11365 } 11366 /* Get the use_callingpres state */ 11367 pri->pvts[chanpos]->callingpres = e->ring.callingpres; 11368 11369 /* Start PBX */ 11370 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)) { 11371 /* Release the PRI lock while we create the channel */ 11372 ast_mutex_unlock(&pri->lock); 11373 if (crv) { 11374 /* Set bearer and such */ 11375 pri_assign_bearer(crv, pri, pri->pvts[chanpos]); 11376 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 11377 pri->pvts[chanpos]->owner = &inuse; 11378 ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel); 11379 } else { 11380 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 11381 } 11382 11383 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11384 11385 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 11386 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 11387 } 11388 if (e->ring.ani2 >= 0) { 11389 snprintf(ani2str, 5, "%.2d", e->ring.ani2); 11390 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 11391 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2; 11392 } 11393 11394 #ifdef SUPPORT_USERUSER 11395 if (!ast_strlen_zero(e->ring.useruserinfo)) { 11396 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 11397 } 11398 #endif 11399 11400 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 11401 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 11402 if (e->ring.redirectingreason >= 0) 11403 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 11404 11405 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11406 ast_mutex_lock(&pri->lock); 11407 if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) { 11408 ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n", 11409 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"), 11410 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11411 } else { 11412 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 11413 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11414 if (c) 11415 ast_hangup(c); 11416 else { 11417 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 11418 pri->pvts[chanpos]->call = NULL; 11419 } 11420 } 11421 } else { 11422 ast_mutex_unlock(&pri->lock); 11423 /* Release PRI lock while we create the channel */ 11424 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype); 11425 if (c) { 11426 char calledtonstr[10]; 11427 11428 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11429 11430 if (e->ring.ani2 >= 0) { 11431 snprintf(ani2str, 5, "%d", e->ring.ani2); 11432 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 11433 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2; 11434 } 11435 11436 #ifdef SUPPORT_USERUSER 11437 if (!ast_strlen_zero(e->ring.useruserinfo)) { 11438 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 11439 } 11440 #endif 11441 11442 if (e->ring.redirectingreason >= 0) 11443 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 11444 11445 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 11446 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 11447 11448 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11449 ast_mutex_lock(&pri->lock); 11450 11451 ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n", 11452 plancallingnum, pri->pvts[chanpos]->exten, 11453 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11454 11455 dahdi_enable_ec(pri->pvts[chanpos]); 11456 } else { 11457 11458 ast_mutex_lock(&pri->lock); 11459 11460 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 11461 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11462 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 11463 pri->pvts[chanpos]->call = NULL; 11464 } 11465 } 11466 } else { 11467 ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n", 11468 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 11469 pri->pvts[chanpos]->prioffset, pri->span); 11470 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED); 11471 pri->pvts[chanpos]->call = NULL; 11472 pri->pvts[chanpos]->exten[0] = '\0'; 11473 } 11474 if (crv) 11475 ast_mutex_unlock(&crv->lock); 11476 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11477 } else { 11478 if (e->ring.flexible) 11479 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION); 11480 else 11481 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL); 11482 } 11483 break; 11484 case PRI_EVENT_RINGING: 11485 chanpos = pri_find_principle(pri, e->ringing.channel); 11486 if (chanpos < 0) { 11487 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 11488 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 11489 } else { 11490 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call); 11491 if (chanpos < 0) { 11492 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 11493 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 11494 } else { 11495 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11496 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 11497 dahdi_enable_ec(pri->pvts[chanpos]); 11498 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1; 11499 pri->pvts[chanpos]->alerting = 1; 11500 } else 11501 ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n"); 11502 11503 #ifdef PRI_PROGRESS_MASK 11504 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) { 11505 #else 11506 if (e->ringing.progress == 8) { 11507 #endif 11508 /* Now we can do call progress detection */ 11509 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11510 /* RINGING detection isn't required because we got ALERTING signal */ 11511 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING); 11512 pri->pvts[chanpos]->dsp_features = 0; 11513 } 11514 } 11515 11516 #ifdef SUPPORT_USERUSER 11517 if (!ast_strlen_zero(e->ringing.useruserinfo)) { 11518 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11519 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11520 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo); 11521 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11522 } 11523 #endif 11524 11525 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11526 } 11527 } 11528 break; 11529 case PRI_EVENT_PROGRESS: 11530 /* Get chan value if e->e is not PRI_EVNT_RINGING */ 11531 chanpos = pri_find_principle(pri, e->proceeding.channel); 11532 if (chanpos > -1) { 11533 #ifdef PRI_PROGRESS_MASK 11534 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) { 11535 #else 11536 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) { 11537 #endif 11538 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, }; 11539 11540 if (e->proceeding.cause > -1) { 11541 ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause); 11542 11543 /* Work around broken, out of spec USER_BUSY cause in a progress message */ 11544 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) { 11545 if (pri->pvts[chanpos]->owner) { 11546 ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n"); 11547 11548 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause; 11549 f.subclass = AST_CONTROL_BUSY; 11550 } 11551 } 11552 } 11553 11554 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11555 ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n", 11556 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 11557 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11558 #ifdef PRI_PROGRESS_MASK 11559 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 11560 #else 11561 if (e->proceeding.progress == 8) { 11562 #endif 11563 /* Now we can do call progress detection */ 11564 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11565 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 11566 pri->pvts[chanpos]->dsp_features = 0; 11567 } 11568 /* Bring voice path up */ 11569 f.subclass = AST_CONTROL_PROGRESS; 11570 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11571 } 11572 pri->pvts[chanpos]->progress = 1; 11573 pri->pvts[chanpos]->dialing = 0; 11574 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11575 } 11576 } 11577 break; 11578 case PRI_EVENT_PROCEEDING: 11579 chanpos = pri_find_principle(pri, e->proceeding.channel); 11580 if (chanpos > -1) { 11581 if (!pri->pvts[chanpos]->proceeding) { 11582 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, }; 11583 11584 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11585 ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n", 11586 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 11587 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11588 #ifdef PRI_PROGRESS_MASK 11589 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 11590 #else 11591 if (e->proceeding.progress == 8) { 11592 #endif 11593 /* Now we can do call progress detection */ 11594 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11595 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 11596 pri->pvts[chanpos]->dsp_features = 0; 11597 } 11598 /* Bring voice path up */ 11599 f.subclass = AST_CONTROL_PROGRESS; 11600 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11601 } 11602 pri->pvts[chanpos]->proceeding = 1; 11603 pri->pvts[chanpos]->dialing = 0; 11604 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11605 } 11606 } 11607 break; 11608 case PRI_EVENT_FACNAME: 11609 chanpos = pri_find_principle(pri, e->facname.channel); 11610 if (chanpos < 0) { 11611 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 11612 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 11613 } else { 11614 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call); 11615 if (chanpos < 0) { 11616 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 11617 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 11618 } else { 11619 /* Re-use *69 field for PRI */ 11620 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11621 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num)); 11622 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name)); 11623 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1; 11624 dahdi_enable_ec(pri->pvts[chanpos]); 11625 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11626 } 11627 } 11628 break; 11629 case PRI_EVENT_ANSWER: 11630 chanpos = pri_find_principle(pri, e->answer.channel); 11631 if (chanpos < 0) { 11632 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 11633 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 11634 } else { 11635 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call); 11636 if (chanpos < 0) { 11637 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 11638 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 11639 } else { 11640 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11641 /* Now we can do call progress detection */ 11642 11643 /* We changed this so it turns on the DSP no matter what... progress or no progress. 11644 * By this time, we need DTMF detection and other features that were previously disabled 11645 * -- Matt F */ 11646 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11647 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 11648 pri->pvts[chanpos]->dsp_features = 0; 11649 } 11650 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) { 11651 ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n"); 11652 x = DAHDI_START; 11653 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 11654 if (res < 0) { 11655 if (errno != EINPROGRESS) { 11656 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 11657 } 11658 } 11659 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 11660 pri->pvts[chanpos]->dialing = 1; 11661 /* Send any "w" waited stuff */ 11662 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop); 11663 if (res < 0) { 11664 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno)); 11665 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 11666 } else 11667 ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr); 11668 11669 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 11670 } else if (pri->pvts[chanpos]->confirmanswer) { 11671 ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel); 11672 } else { 11673 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1; 11674 /* Enable echo cancellation if it's not on already */ 11675 dahdi_enable_ec(pri->pvts[chanpos]); 11676 } 11677 11678 #ifdef SUPPORT_USERUSER 11679 if (!ast_strlen_zero(e->answer.useruserinfo)) { 11680 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11681 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11682 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo); 11683 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11684 } 11685 #endif 11686 11687 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11688 } 11689 } 11690 break; 11691 case PRI_EVENT_HANGUP: 11692 chanpos = pri_find_principle(pri, e->hangup.channel); 11693 if (chanpos < 0) { 11694 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 11695 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11696 } else { 11697 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 11698 if (chanpos > -1) { 11699 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11700 if (!pri->pvts[chanpos]->alreadyhungup) { 11701 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */ 11702 pri->pvts[chanpos]->alreadyhungup = 1; 11703 if (pri->pvts[chanpos]->realcall) 11704 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11705 else if (pri->pvts[chanpos]->owner) { 11706 /* Queue a BUSY instead of a hangup if our cause is appropriate */ 11707 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 11708 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP) 11709 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11710 else { 11711 switch (e->hangup.cause) { 11712 case PRI_CAUSE_USER_BUSY: 11713 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 11714 break; 11715 case PRI_CAUSE_CALL_REJECTED: 11716 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 11717 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 11718 case PRI_CAUSE_SWITCH_CONGESTION: 11719 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 11720 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 11721 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 11722 break; 11723 default: 11724 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11725 } 11726 } 11727 } 11728 ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n", 11729 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause); 11730 } else { 11731 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 11732 pri->pvts[chanpos]->call = NULL; 11733 } 11734 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 11735 ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 11736 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11737 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 11738 pri->pvts[chanpos]->resetting = 1; 11739 } 11740 if (e->hangup.aoc_units > -1) 11741 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 11742 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 11743 11744 #ifdef SUPPORT_USERUSER 11745 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) { 11746 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11747 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11748 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 11749 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11750 } 11751 #endif 11752 11753 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11754 } else { 11755 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 11756 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11757 } 11758 } 11759 break; 11760 #ifndef PRI_EVENT_HANGUP_REQ 11761 #error please update libpri 11762 #endif 11763 case PRI_EVENT_HANGUP_REQ: 11764 chanpos = pri_find_principle(pri, e->hangup.channel); 11765 if (chanpos < 0) { 11766 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 11767 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11768 } else { 11769 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 11770 if (chanpos > -1) { 11771 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11772 if (pri->pvts[chanpos]->realcall) 11773 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11774 else if (pri->pvts[chanpos]->owner) { 11775 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 11776 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP) 11777 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11778 else { 11779 switch (e->hangup.cause) { 11780 case PRI_CAUSE_USER_BUSY: 11781 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 11782 break; 11783 case PRI_CAUSE_CALL_REJECTED: 11784 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 11785 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 11786 case PRI_CAUSE_SWITCH_CONGESTION: 11787 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 11788 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 11789 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 11790 break; 11791 default: 11792 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11793 } 11794 } 11795 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); 11796 if (e->hangup.aoc_units > -1) 11797 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 11798 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 11799 } else { 11800 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 11801 pri->pvts[chanpos]->call = NULL; 11802 } 11803 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 11804 ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n", 11805 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11806 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 11807 pri->pvts[chanpos]->resetting = 1; 11808 } 11809 11810 #ifdef SUPPORT_USERUSER 11811 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 11812 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11813 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11814 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 11815 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11816 } 11817 #endif 11818 11819 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11820 } else { 11821 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); 11822 } 11823 } 11824 break; 11825 case PRI_EVENT_HANGUP_ACK: 11826 chanpos = pri_find_principle(pri, e->hangup.channel); 11827 if (chanpos < 0) { 11828 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 11829 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11830 } else { 11831 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 11832 if (chanpos > -1) { 11833 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11834 pri->pvts[chanpos]->call = NULL; 11835 pri->pvts[chanpos]->resetting = 0; 11836 if (pri->pvts[chanpos]->owner) { 11837 ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11838 } 11839 11840 #ifdef SUPPORT_USERUSER 11841 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 11842 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11843 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11844 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 11845 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11846 } 11847 #endif 11848 11849 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11850 } 11851 } 11852 break; 11853 case PRI_EVENT_CONFIG_ERR: 11854 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err); 11855 break; 11856 case PRI_EVENT_RESTART_ACK: 11857 chanpos = pri_find_principle(pri, e->restartack.channel); 11858 if (chanpos < 0) { 11859 /* Sometime switches (e.g. I421 / British Telecom) don't give us the 11860 channel number, so we have to figure it out... This must be why 11861 everybody resets exactly a channel at a time. */ 11862 for (x = 0; x < pri->numchans; x++) { 11863 if (pri->pvts[x] && pri->pvts[x]->resetting) { 11864 chanpos = x; 11865 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11866 ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 11867 pri->pvts[chanpos]->prioffset, pri->span); 11868 if (pri->pvts[chanpos]->realcall) 11869 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11870 else if (pri->pvts[chanpos]->owner) { 11871 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 11872 pri->pvts[chanpos]->prioffset, pri->span); 11873 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11874 } 11875 pri->pvts[chanpos]->resetting = 0; 11876 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 11877 pri->pvts[chanpos]->prioffset, pri->span); 11878 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11879 if (pri->resetting) 11880 pri_check_restart(pri); 11881 break; 11882 } 11883 } 11884 if (chanpos < 0) { 11885 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 11886 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 11887 } 11888 } else { 11889 if (pri->pvts[chanpos]) { 11890 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11891 if (pri->pvts[chanpos]->realcall) 11892 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11893 else if (pri->pvts[chanpos]->owner) { 11894 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n", 11895 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 11896 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11897 } 11898 pri->pvts[chanpos]->resetting = 0; 11899 pri->pvts[chanpos]->inservice = 1; 11900 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 11901 pri->pvts[chanpos]->prioffset, pri->span); 11902 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11903 if (pri->resetting) 11904 pri_check_restart(pri); 11905 } 11906 } 11907 break; 11908 case PRI_EVENT_SETUP_ACK: 11909 chanpos = pri_find_principle(pri, e->setup_ack.channel); 11910 if (chanpos < 0) { 11911 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 11912 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span); 11913 } else { 11914 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call); 11915 if (chanpos > -1) { 11916 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11917 pri->pvts[chanpos]->setup_ack = 1; 11918 /* Send any queued digits */ 11919 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) { 11920 ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]); 11921 pri_information(pri->pri, pri->pvts[chanpos]->call, 11922 pri->pvts[chanpos]->dialdest[x]); 11923 } 11924 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11925 } else 11926 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel); 11927 } 11928 break; 11929 case PRI_EVENT_NOTIFY: 11930 chanpos = pri_find_principle(pri, e->notify.channel); 11931 if (chanpos < 0) { 11932 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n", 11933 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span); 11934 } else { 11935 struct ast_frame f = { AST_FRAME_CONTROL, }; 11936 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11937 switch (e->notify.info) { 11938 case PRI_NOTIFY_REMOTE_HOLD: 11939 f.subclass = AST_CONTROL_HOLD; 11940 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11941 break; 11942 case PRI_NOTIFY_REMOTE_RETRIEVAL: 11943 f.subclass = AST_CONTROL_UNHOLD; 11944 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11945 break; 11946 } 11947 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11948 } 11949 break; 11950 default: 11951 ast_debug(1, "Event: %d\n", e->e); 11952 } 11953 } 11954 ast_mutex_unlock(&pri->lock); 11955 } 11956 /* Never reached */ 11957 return NULL; 11958 }
Definition at line 10511 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pri::crvs, dahdi_pvt::next, and dahdi_pvt::pri.
10512 { 10513 struct dahdi_pvt *p; 10514 p = pri->crvs; 10515 while (p) { 10516 if (p->channel == crv) 10517 return p; 10518 p = p->next; 10519 } 10520 return NULL; 10521 }
static int pri_find_dchan | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3364 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, dahdi_pri::dchans, NUM_DCHANS, and dahdi_pri::pri.
03365 { 03366 int oldslot = -1; 03367 struct pri *old; 03368 int newslot = -1; 03369 int x; 03370 old = pri->pri; 03371 for (x = 0; x < NUM_DCHANS; x++) { 03372 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0)) 03373 newslot = x; 03374 if (pri->dchans[x] == old) { 03375 oldslot = x; 03376 } 03377 } 03378 if (newslot < 0) { 03379 newslot = 0; 03380 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n", 03381 pri->dchannels[newslot]); 03382 } 03383 if (old && (oldslot != newslot)) 03384 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n", 03385 pri->dchannels[oldslot], pri->dchannels[newslot]); 03386 pri->pri = pri->dchans[newslot]; 03387 return 0; 03388 }
static int pri_find_empty_chan | ( | struct dahdi_pri * | pri, | |
int | backwards | |||
) | [static] |
Definition at line 9415 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().
09416 { 09417 int x; 09418 if (backwards) 09419 x = pri->numchans; 09420 else 09421 x = 0; 09422 for (;;) { 09423 if (backwards && (x < 0)) 09424 break; 09425 if (!backwards && (x >= pri->numchans)) 09426 break; 09427 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) { 09428 ast_debug(1, "Found empty available channel %d/%d\n", 09429 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset); 09430 return x; 09431 } 09432 if (backwards) 09433 x--; 09434 else 09435 x++; 09436 } 09437 return -1; 09438 }
static int pri_find_principle | ( | struct dahdi_pri * | pri, | |
int | channel | |||
) | [static] |
Definition at line 10524 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.
10525 { 10526 int x; 10527 int span = PRI_SPAN(channel); 10528 int spanfd; 10529 struct dahdi_params param; 10530 int principle = -1; 10531 int explicit = PRI_EXPLICIT(channel); 10532 channel = PRI_CHANNEL(channel); 10533 10534 if (!explicit) { 10535 spanfd = pri_active_dchan_fd(pri); 10536 memset(¶m, 0, sizeof(param)); 10537 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m)) 10538 return -1; 10539 span = pris[param.spanno - 1].prilogicalspan; 10540 } 10541 10542 for (x = 0; x < pri->numchans; x++) { 10543 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) { 10544 principle = x; 10545 break; 10546 } 10547 } 10548 10549 return principle; 10550 }
static int pri_fixup_principle | ( | struct dahdi_pri * | pri, | |
int | principle, | |||
q931_call * | c | |||
) | [static] |
Definition at line 10552 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.
10553 { 10554 int x; 10555 struct dahdi_pvt *crv; 10556 if (!c) { 10557 if (principle < 0) 10558 return -1; 10559 return principle; 10560 } 10561 if ((principle > -1) && 10562 (principle < pri->numchans) && 10563 (pri->pvts[principle]) && 10564 (pri->pvts[principle]->call == c)) 10565 return principle; 10566 /* First, check for other bearers */ 10567 for (x = 0; x < pri->numchans; x++) { 10568 if (!pri->pvts[x]) 10569 continue; 10570 if (pri->pvts[x]->call == c) { 10571 /* Found our call */ 10572 if (principle != x) { 10573 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x]; 10574 10575 ast_verb(3, "Moving call from channel %d to channel %d\n", 10576 old->channel, new->channel); 10577 if (new->owner) { 10578 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n", 10579 old->channel, new->channel, new->channel); 10580 return -1; 10581 } 10582 /* Fix it all up now */ 10583 new->owner = old->owner; 10584 old->owner = NULL; 10585 if (new->owner) { 10586 ast_string_field_build(new->owner, name, 10587 "DAHDI/%d:%d-%d", pri->trunkgroup, 10588 new->channel, 1); 10589 new->owner->tech_pvt = new; 10590 ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd); 10591 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner; 10592 old->subs[SUB_REAL].owner = NULL; 10593 } else 10594 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); 10595 new->call = old->call; 10596 old->call = NULL; 10597 10598 /* Copy any DSP that may be present */ 10599 new->dsp = old->dsp; 10600 new->dsp_features = old->dsp_features; 10601 old->dsp = NULL; 10602 old->dsp_features = 0; 10603 } 10604 return principle; 10605 } 10606 } 10607 /* Now check for a CRV with no bearer */ 10608 crv = pri->crvs; 10609 while (crv) { 10610 if (crv->call == c) { 10611 /* This is our match... Perform some basic checks */ 10612 if (crv->bearer) 10613 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n"); 10614 else if (pri->pvts[principle]->owner) 10615 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n"); 10616 else { 10617 /* Looks good. Drop the pseudo channel now, clear up the assignment, and 10618 wakeup the potential sleeper */ 10619 dahdi_close_sub(crv, SUB_REAL); 10620 pri->pvts[principle]->call = crv->call; 10621 pri_assign_bearer(crv, pri, pri->pvts[principle]); 10622 ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n", 10623 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset, 10624 pri->trunkgroup, crv->channel); 10625 wakeup_sub(crv, SUB_REAL, pri); 10626 } 10627 return principle; 10628 } 10629 crv = crv->next; 10630 } 10631 ast_log(LOG_WARNING, "Call specified, but not found?\n"); 10632 return -1; 10633 }
Definition at line 1247 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().
01248 { 01249 int res; 01250 /* Grab the lock first */ 01251 do { 01252 res = ast_mutex_trylock(&pri->lock); 01253 if (res) { 01254 DEADLOCK_AVOIDANCE(&pvt->lock); 01255 } 01256 } while (res); 01257 /* Then break the poll */ 01258 if (pri->master != AST_PTHREADT_NULL) 01259 pthread_kill(pri->master, SIGURG); 01260 return 0; 01261 }
Definition at line 10783 of file chan_dahdi.c.
References AST_CAUSE_PRE_EMPTED, ast_channel_trylock, ast_channel_unlock, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_hangup_with_cause(), DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_pri::lock, dahdi_subchannel::owner, and dahdi_pvt::subs.
10784 { 10785 int x; 10786 int redo; 10787 ast_mutex_unlock(&pri->lock); 10788 ast_mutex_lock(&p->lock); 10789 do { 10790 redo = 0; 10791 for (x = 0; x < 3; x++) { 10792 while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) { 10793 redo++; 10794 DEADLOCK_AVOIDANCE(&p->lock); 10795 } 10796 if (p->subs[x].owner) { 10797 ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED); 10798 ast_channel_unlock(p->subs[x].owner); 10799 } 10800 } 10801 } while (redo); 10802 ast_mutex_unlock(&p->lock); 10803 ast_mutex_lock(&pri->lock); 10804 return 0; 10805 }
static int pri_is_up | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3312 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, NUM_DCHANS, and dahdi_pvt::pri.
Referenced by pri_dchannel().
03313 { 03314 int x; 03315 for (x = 0; x < NUM_DCHANS; x++) { 03316 if (pri->dchanavail[x] == DCHAN_AVAILABLE) 03317 return 1; 03318 } 03319 return 0; 03320 }
static char* pri_order | ( | int | level | ) | [static] |
Definition at line 3335 of file chan_dahdi.c.
Referenced by handle_pri_show_span().
03336 { 03337 switch (level) { 03338 case 0: 03339 return "Primary"; 03340 case 1: 03341 return "Secondary"; 03342 case 2: 03343 return "Tertiary"; 03344 case 3: 03345 return "Quaternary"; 03346 default: 03347 return "<Unknown>"; 03348 } 03349 }
static void pri_rel | ( | struct dahdi_pri * | pri | ) | [inline, static] |
Definition at line 455 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().
00456 { 00457 ast_mutex_unlock(&pri->lock); 00458 }
static int pri_resolve_span | ( | int * | span, | |
int | channel, | |||
int | offset, | |||
struct dahdi_spaninfo * | si | |||
) | [static] |
Definition at line 8538 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().
08539 { 08540 int x; 08541 int trunkgroup; 08542 /* Get appropriate trunk group if there is one */ 08543 trunkgroup = pris[*span].mastertrunkgroup; 08544 if (trunkgroup) { 08545 /* Select a specific trunk group */ 08546 for (x = 0; x < NUM_SPANS; x++) { 08547 if (pris[x].trunkgroup == trunkgroup) { 08548 *span = x; 08549 return 0; 08550 } 08551 } 08552 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup); 08553 *span = -1; 08554 } else { 08555 if (pris[*span].trunkgroup) { 08556 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup); 08557 *span = -1; 08558 } else if (pris[*span].mastertrunkgroup) { 08559 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup); 08560 *span = -1; 08561 } else { 08562 if (si->totalchans == 31) { 08563 /* E1 */ 08564 pris[*span].dchannels[0] = 16 + offset; 08565 } else if (si->totalchans == 24) { 08566 /* T1 or J1 */ 08567 pris[*span].dchannels[0] = 24 + offset; 08568 } else if (si->totalchans == 3) { 08569 /* BRI */ 08570 pris[*span].dchannels[0] = 3 + offset; 08571 } else { 08572 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); 08573 *span = -1; 08574 return 0; 08575 } 08576 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED; 08577 pris[*span].offset = offset; 08578 pris[*span].span = *span + 1; 08579 } 08580 } 08581 return 0; 08582 }
static int process_dahdi | ( | struct dahdi_chan_conf * | confp, | |
const char * | cat, | |||
struct ast_variable * | v, | |||
int | reload, | |||
int | options | |||
) | [static] |
Definition at line 14234 of file chan_dahdi.c.
References ast_copy_string(), ast_jb_read_conf(), ast_log(), build_channels(), dahdi_chan_conf::chan, global_jbconf, HAVE_PRI, ast_variable::lineno, LOG_DEBUG, MAX_CHANLIST_LEN, ast_variable::name, ast_variable::next, dahdi_pvt::parkinglot, PROC_DAHDI_OPT_NOCHAN, and ast_variable::value.
Referenced by setup_dahdi().
14235 { 14236 struct dahdi_pvt *tmp; 14237 int y; 14238 int found_pseudo = 0; 14239 char dahdichan[MAX_CHANLIST_LEN] = {}; 14240 14241 for (; v; v = v->next) { 14242 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 14243 continue; 14244 14245 /* must have parkinglot in confp before build_channels is called */ 14246 if (!strcasecmp(v->name, "parkinglot")) { 14247 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot)); 14248 } 14249 14250 /* Create the interface list */ 14251 if (!strcasecmp(v->name, "channel") 14252 #ifdef HAVE_PRI 14253 || !strcasecmp(v->name, "crv") 14254 #endif 14255 ) { 14256 int iscrv; 14257 if (options & PROC_DAHDI_OPT_NOCHAN) { 14258 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value); 14259 continue; 14260 } 14261 iscrv = !strcasecmp(v->name, "crv"); 14262 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo)) 14263 return -1; 14264 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value); 14265 } else if (!strcasecmp(v->name, "buffers")) { 14266 int res; 14267 char policy[21] = ""; 14268 14269 res = sscanf(v->value, "%d,%20s", &confp->chan.buf_no, policy); 14270 if (res != 2) { 14271 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n"); 14272 confp->chan.buf_no = numbufs; 14273 continue; 14274 } 14275 if (confp->chan.buf_no < 0) 14276 confp->chan.buf_no = numbufs; 14277 if (!strcasecmp(policy, "full")) { 14278 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL; 14279 } else if (!strcasecmp(policy, "immediate")) { 14280 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE; 14281 } else { 14282 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy); 14283 } 14284 } else if (!strcasecmp(v->name, "dahdichan")) { 14285 ast_copy_string(dahdichan, v->value, sizeof(dahdichan)); 14286 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) { 14287 usedistinctiveringdetection = ast_true(v->value); 14288 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) { 14289 distinctiveringaftercid = ast_true(v->value); 14290 } else if (!strcasecmp(v->name, "dring1context")) { 14291 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData)); 14292 } else if (!strcasecmp(v->name, "dring2context")) { 14293 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData)); 14294 } else if (!strcasecmp(v->name, "dring3context")) { 14295 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData)); 14296 } else if (!strcasecmp(v->name, "dring1range")) { 14297 confp->chan.drings.ringnum[0].range = atoi(v->value); 14298 } else if (!strcasecmp(v->name, "dring2range")) { 14299 confp->chan.drings.ringnum[1].range = atoi(v->value); 14300 } else if (!strcasecmp(v->name, "dring3range")) { 14301 confp->chan.drings.ringnum[2].range = atoi(v->value); 14302 } else if (!strcasecmp(v->name, "dring1")) { 14303 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]); 14304 } else if (!strcasecmp(v->name, "dring2")) { 14305 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]); 14306 } else if (!strcasecmp(v->name, "dring3")) { 14307 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]); 14308 } else if (!strcasecmp(v->name, "usecallerid")) { 14309 confp->chan.use_callerid = ast_true(v->value); 14310 } else if (!strcasecmp(v->name, "cidsignalling")) { 14311 if (!strcasecmp(v->value, "bell")) 14312 confp->chan.cid_signalling = CID_SIG_BELL; 14313 else if (!strcasecmp(v->value, "v23")) 14314 confp->chan.cid_signalling = CID_SIG_V23; 14315 else if (!strcasecmp(v->value, "dtmf")) 14316 confp->chan.cid_signalling = CID_SIG_DTMF; 14317 else if (!strcasecmp(v->value, "smdi")) 14318 confp->chan.cid_signalling = CID_SIG_SMDI; 14319 else if (!strcasecmp(v->value, "v23_jp")) 14320 confp->chan.cid_signalling = CID_SIG_V23_JP; 14321 else if (ast_true(v->value)) 14322 confp->chan.cid_signalling = CID_SIG_BELL; 14323 } else if (!strcasecmp(v->name, "cidstart")) { 14324 if (!strcasecmp(v->value, "ring")) 14325 confp->chan.cid_start = CID_START_RING; 14326 else if (!strcasecmp(v->value, "polarity_in")) 14327 confp->chan.cid_start = CID_START_POLARITY_IN; 14328 else if (!strcasecmp(v->value, "polarity")) 14329 confp->chan.cid_start = CID_START_POLARITY; 14330 else if (ast_true(v->value)) 14331 confp->chan.cid_start = CID_START_RING; 14332 } else if (!strcasecmp(v->name, "threewaycalling")) { 14333 confp->chan.threewaycalling = ast_true(v->value); 14334 } else if (!strcasecmp(v->name, "cancallforward")) { 14335 confp->chan.cancallforward = ast_true(v->value); 14336 } else if (!strcasecmp(v->name, "relaxdtmf")) { 14337 if (ast_true(v->value)) 14338 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 14339 else 14340 confp->chan.dtmfrelax = 0; 14341 } else if (!strcasecmp(v->name, "mailbox")) { 14342 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox)); 14343 } else if (!strcasecmp(v->name, "hasvoicemail")) { 14344 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) { 14345 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox)); 14346 } 14347 } else if (!strcasecmp(v->name, "adsi")) { 14348 confp->chan.adsi = ast_true(v->value); 14349 } else if (!strcasecmp(v->name, "usesmdi")) { 14350 confp->chan.use_smdi = ast_true(v->value); 14351 } else if (!strcasecmp(v->name, "smdiport")) { 14352 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port)); 14353 } else if (!strcasecmp(v->name, "transfer")) { 14354 confp->chan.transfer = ast_true(v->value); 14355 } else if (!strcasecmp(v->name, "canpark")) { 14356 confp->chan.canpark = ast_true(v->value); 14357 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) { 14358 confp->chan.echocanbridged = ast_true(v->value); 14359 } else if (!strcasecmp(v->name, "busydetect")) { 14360 confp->chan.busydetect = ast_true(v->value); 14361 } else if (!strcasecmp(v->name, "busycount")) { 14362 confp->chan.busycount = atoi(v->value); 14363 } else if (!strcasecmp(v->name, "silencethreshold")) { 14364 confp->chan.silencethreshold = atoi(v->value); 14365 } else if (!strcasecmp(v->name, "busycompare")) { 14366 confp->chan.busycompare = ast_true(v->value); 14367 } else if (!strcasecmp(v->name, "busypattern")) { 14368 if (sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) { 14369 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno); 14370 } 14371 int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength); 14372 if (count == 1) 14373 confp->chan.busyquietlength = 0; 14374 else if (count < 1) 14375 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno); 14376 } else if (!strcasecmp(v->name, "busyfuzziness")) { 14377 confp->chan.busyfuzziness = atoi(v->value); 14378 } else if (!strcasecmp(v->name, "callprogress")) { 14379 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS; 14380 if (ast_true(v->value)) 14381 confp->chan.callprogress |= CALLPROGRESS_PROGRESS; 14382 } else if (!strcasecmp(v->name, "faxdetect")) { 14383 confp->chan.callprogress &= ~CALLPROGRESS_FAX; 14384 if (!strcasecmp(v->value, "incoming")) { 14385 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING; 14386 } else if (!strcasecmp(v->value, "outgoing")) { 14387 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING; 14388 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) 14389 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING; 14390 } else if (!strcasecmp(v->name, "echocancel")) { 14391 process_echocancel(confp, v->value, v->lineno); 14392 } else if (!strcasecmp(v->name, "echotraining")) { 14393 if (sscanf(v->value, "%d", &y) == 1) { 14394 if ((y < 10) || (y > 4000)) { 14395 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno); 14396 } else { 14397 confp->chan.echotraining = y; 14398 } 14399 } else if (ast_true(v->value)) { 14400 confp->chan.echotraining = 400; 14401 } else 14402 confp->chan.echotraining = 0; 14403 } else if (!strcasecmp(v->name, "hidecallerid")) { 14404 confp->chan.hidecallerid = ast_true(v->value); 14405 } else if (!strcasecmp(v->name, "hidecalleridname")) { 14406 confp->chan.hidecalleridname = ast_true(v->value); 14407 } else if (!strcasecmp(v->name, "pulsedial")) { 14408 confp->chan.pulse = ast_true(v->value); 14409 } else if (!strcasecmp(v->name, "callreturn")) { 14410 confp->chan.callreturn = ast_true(v->value); 14411 } else if (!strcasecmp(v->name, "callwaiting")) { 14412 confp->chan.callwaiting = ast_true(v->value); 14413 } else if (!strcasecmp(v->name, "callwaitingcallerid")) { 14414 confp->chan.callwaitingcallerid = ast_true(v->value); 14415 } else if (!strcasecmp(v->name, "context")) { 14416 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context)); 14417 } else if (!strcasecmp(v->name, "language")) { 14418 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language)); 14419 } else if (!strcasecmp(v->name, "progzone")) { 14420 ast_copy_string(progzone, v->value, sizeof(progzone)); 14421 } else if (!strcasecmp(v->name, "mohinterpret") 14422 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) { 14423 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret)); 14424 } else if (!strcasecmp(v->name, "mohsuggest")) { 14425 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest)); 14426 } else if (!strcasecmp(v->name, "parkinglot")) { 14427 ast_copy_string(parkinglot, v->value, sizeof(parkinglot)); 14428 } else if (!strcasecmp(v->name, "stripmsd")) { 14429 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name); 14430 confp->chan.stripmsd = atoi(v->value); 14431 } else if (!strcasecmp(v->name, "jitterbuffers")) { 14432 numbufs = atoi(v->value); 14433 } else if (!strcasecmp(v->name, "group")) { 14434 confp->chan.group = ast_get_group(v->value); 14435 } else if (!strcasecmp(v->name, "callgroup")) { 14436 if (!strcasecmp(v->value, "none")) 14437 confp->chan.callgroup = 0; 14438 else 14439 confp->chan.callgroup = ast_get_group(v->value); 14440 } else if (!strcasecmp(v->name, "pickupgroup")) { 14441 if (!strcasecmp(v->value, "none")) 14442 confp->chan.pickupgroup = 0; 14443 else 14444 confp->chan.pickupgroup = ast_get_group(v->value); 14445 } else if (!strcasecmp(v->name, "setvar")) { 14446 char *varname = ast_strdupa(v->value), *varval = NULL; 14447 struct ast_variable *tmpvar; 14448 if (varname && (varval = strchr(varname, '='))) { 14449 *varval++ = '\0'; 14450 if ((tmpvar = ast_variable_new(varname, varval, ""))) { 14451 tmpvar->next = confp->chan.vars; 14452 confp->chan.vars = tmpvar; 14453 } 14454 } 14455 } else if (!strcasecmp(v->name, "immediate")) { 14456 confp->chan.immediate = ast_true(v->value); 14457 } else if (!strcasecmp(v->name, "transfertobusy")) { 14458 confp->chan.transfertobusy = ast_true(v->value); 14459 } else if (!strcasecmp(v->name, "mwimonitor")) { 14460 confp->chan.mwimonitor_neon = 0; 14461 confp->chan.mwimonitor_fsk = 0; 14462 confp->chan.mwimonitor_rpas = 0; 14463 if (strcasestr(v->value, "fsk")) { 14464 confp->chan.mwimonitor_fsk = 1; 14465 } 14466 if (strcasestr(v->value, "rpas")) { 14467 confp->chan.mwimonitor_rpas = 1; 14468 } 14469 if (strcasestr(v->value, "neon")) { 14470 confp->chan.mwimonitor_neon = 1; 14471 } 14472 /* If set to true or yes, assume that simple fsk is desired */ 14473 if (ast_true(v->value)) { 14474 confp->chan.mwimonitor_fsk = 1; 14475 } 14476 } else if (!strcasecmp(v->name, "cid_rxgain")) { 14477 if (sscanf(v->value, "%f", &confp->chan.cid_rxgain) != 1) { 14478 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno); 14479 } 14480 } else if (!strcasecmp(v->name, "rxgain")) { 14481 if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) { 14482 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno); 14483 } 14484 } else if (!strcasecmp(v->name, "txgain")) { 14485 if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) { 14486 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno); 14487 } 14488 } else if (!strcasecmp(v->name, "tonezone")) { 14489 if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) { 14490 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno); 14491 } 14492 } else if (!strcasecmp(v->name, "callerid")) { 14493 if (!strcasecmp(v->value, "asreceived")) { 14494 confp->chan.cid_num[0] = '\0'; 14495 confp->chan.cid_name[0] = '\0'; 14496 } else { 14497 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num)); 14498 } 14499 } else if (!strcasecmp(v->name, "fullname")) { 14500 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name)); 14501 } else if (!strcasecmp(v->name, "cid_number")) { 14502 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num)); 14503 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) { 14504 confp->chan.dahditrcallerid = ast_true(v->value); 14505 } else if (!strcasecmp(v->name, "restrictcid")) { 14506 confp->chan.restrictcid = ast_true(v->value); 14507 } else if (!strcasecmp(v->name, "usecallingpres")) { 14508 confp->chan.use_callingpres = ast_true(v->value); 14509 } else if (!strcasecmp(v->name, "accountcode")) { 14510 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode)); 14511 } else if (!strcasecmp(v->name, "amaflags")) { 14512 y = ast_cdr_amaflags2int(v->value); 14513 if (y < 0) 14514 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno); 14515 else 14516 confp->chan.amaflags = y; 14517 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) { 14518 confp->chan.polarityonanswerdelay = atoi(v->value); 14519 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) { 14520 confp->chan.answeronpolarityswitch = ast_true(v->value); 14521 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) { 14522 confp->chan.hanguponpolarityswitch = ast_true(v->value); 14523 } else if (!strcasecmp(v->name, "sendcalleridafter")) { 14524 confp->chan.sendcalleridafter = atoi(v->value); 14525 } else if (!strcasecmp(v->name, "mwimonitornotify")) { 14526 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify)); 14527 } else if (!strcasecmp(v->name, "mwisendtype")) { 14528 if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */ 14529 mwisend_rpas = 1; 14530 } else { 14531 mwisend_rpas = 0; 14532 } 14533 } else if (reload != 1) { 14534 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) { 14535 int orig_radio = confp->chan.radio; 14536 int orig_outsigmod = confp->chan.outsigmod; 14537 int orig_auto = confp->is_sig_auto; 14538 14539 confp->chan.radio = 0; 14540 confp->chan.outsigmod = -1; 14541 confp->is_sig_auto = 0; 14542 if (!strcasecmp(v->value, "em")) { 14543 confp->chan.sig = SIG_EM; 14544 } else if (!strcasecmp(v->value, "em_e1")) { 14545 confp->chan.sig = SIG_EM_E1; 14546 } else if (!strcasecmp(v->value, "em_w")) { 14547 confp->chan.sig = SIG_EMWINK; 14548 } else if (!strcasecmp(v->value, "fxs_ls")) { 14549 confp->chan.sig = SIG_FXSLS; 14550 } else if (!strcasecmp(v->value, "fxs_gs")) { 14551 confp->chan.sig = SIG_FXSGS; 14552 } else if (!strcasecmp(v->value, "fxs_ks")) { 14553 confp->chan.sig = SIG_FXSKS; 14554 } else if (!strcasecmp(v->value, "fxo_ls")) { 14555 confp->chan.sig = SIG_FXOLS; 14556 } else if (!strcasecmp(v->value, "fxo_gs")) { 14557 confp->chan.sig = SIG_FXOGS; 14558 } else if (!strcasecmp(v->value, "fxo_ks")) { 14559 confp->chan.sig = SIG_FXOKS; 14560 } else if (!strcasecmp(v->value, "fxs_rx")) { 14561 confp->chan.sig = SIG_FXSKS; 14562 confp->chan.radio = 1; 14563 } else if (!strcasecmp(v->value, "fxo_rx")) { 14564 confp->chan.sig = SIG_FXOLS; 14565 confp->chan.radio = 1; 14566 } else if (!strcasecmp(v->value, "fxs_tx")) { 14567 confp->chan.sig = SIG_FXSLS; 14568 confp->chan.radio = 1; 14569 } else if (!strcasecmp(v->value, "fxo_tx")) { 14570 confp->chan.sig = SIG_FXOGS; 14571 confp->chan.radio = 1; 14572 } else if (!strcasecmp(v->value, "em_rx")) { 14573 confp->chan.sig = SIG_EM; 14574 confp->chan.radio = 1; 14575 } else if (!strcasecmp(v->value, "em_tx")) { 14576 confp->chan.sig = SIG_EM; 14577 confp->chan.radio = 1; 14578 } else if (!strcasecmp(v->value, "em_rxtx")) { 14579 confp->chan.sig = SIG_EM; 14580 confp->chan.radio = 2; 14581 } else if (!strcasecmp(v->value, "em_txrx")) { 14582 confp->chan.sig = SIG_EM; 14583 confp->chan.radio = 2; 14584 } else if (!strcasecmp(v->value, "sf")) { 14585 confp->chan.sig = SIG_SF; 14586 } else if (!strcasecmp(v->value, "sf_w")) { 14587 confp->chan.sig = SIG_SFWINK; 14588 } else if (!strcasecmp(v->value, "sf_featd")) { 14589 confp->chan.sig = SIG_FEATD; 14590 } else if (!strcasecmp(v->value, "sf_featdmf")) { 14591 confp->chan.sig = SIG_FEATDMF; 14592 } else if (!strcasecmp(v->value, "sf_featb")) { 14593 confp->chan.sig = SIG_SF_FEATB; 14594 } else if (!strcasecmp(v->value, "sf")) { 14595 confp->chan.sig = SIG_SF; 14596 } else if (!strcasecmp(v->value, "sf_rx")) { 14597 confp->chan.sig = SIG_SF; 14598 confp->chan.radio = 1; 14599 } else if (!strcasecmp(v->value, "sf_tx")) { 14600 confp->chan.sig = SIG_SF; 14601 confp->chan.radio = 1; 14602 } else if (!strcasecmp(v->value, "sf_rxtx")) { 14603 confp->chan.sig = SIG_SF; 14604 confp->chan.radio = 2; 14605 } else if (!strcasecmp(v->value, "sf_txrx")) { 14606 confp->chan.sig = SIG_SF; 14607 confp->chan.radio = 2; 14608 } else if (!strcasecmp(v->value, "featd")) { 14609 confp->chan.sig = SIG_FEATD; 14610 } else if (!strcasecmp(v->value, "featdmf")) { 14611 confp->chan.sig = SIG_FEATDMF; 14612 } else if (!strcasecmp(v->value, "featdmf_ta")) { 14613 confp->chan.sig = SIG_FEATDMF_TA; 14614 } else if (!strcasecmp(v->value, "e911")) { 14615 confp->chan.sig = SIG_E911; 14616 } else if (!strcasecmp(v->value, "fgccama")) { 14617 confp->chan.sig = SIG_FGC_CAMA; 14618 } else if (!strcasecmp(v->value, "fgccamamf")) { 14619 confp->chan.sig = SIG_FGC_CAMAMF; 14620 } else if (!strcasecmp(v->value, "featb")) { 14621 confp->chan.sig = SIG_FEATB; 14622 #ifdef HAVE_PRI 14623 } else if (!strcasecmp(v->value, "pri_net")) { 14624 confp->chan.sig = SIG_PRI; 14625 confp->pri.nodetype = PRI_NETWORK; 14626 } else if (!strcasecmp(v->value, "pri_cpe")) { 14627 confp->chan.sig = SIG_PRI; 14628 confp->pri.nodetype = PRI_CPE; 14629 } else if (!strcasecmp(v->value, "bri_cpe")) { 14630 confp->chan.sig = SIG_BRI; 14631 confp->pri.nodetype = PRI_CPE; 14632 } else if (!strcasecmp(v->value, "bri_net")) { 14633 confp->chan.sig = SIG_BRI; 14634 confp->pri.nodetype = PRI_NETWORK; 14635 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) { 14636 confp->chan.sig = SIG_BRI_PTMP; 14637 confp->pri.nodetype = PRI_CPE; 14638 } else if (!strcasecmp(v->value, "bri_net_ptmp")) { 14639 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno); 14640 } else if (!strcasecmp(v->value, "gr303fxoks_net")) { 14641 confp->chan.sig = SIG_GR303FXOKS; 14642 confp->pri.nodetype = PRI_NETWORK; 14643 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) { 14644 confp->chan.sig = SIG_GR303FXSKS; 14645 confp->pri.nodetype = PRI_CPE; 14646 #endif 14647 #ifdef HAVE_SS7 14648 } else if (!strcasecmp(v->value, "ss7")) { 14649 confp->chan.sig = SIG_SS7; 14650 #endif 14651 } else if (!strcasecmp(v->value, "auto")) { 14652 confp->is_sig_auto = 1; 14653 } else { 14654 confp->chan.outsigmod = orig_outsigmod; 14655 confp->chan.radio = orig_radio; 14656 confp->is_sig_auto = orig_auto; 14657 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 14658 } 14659 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) { 14660 if (!strcasecmp(v->value, "em")) { 14661 confp->chan.outsigmod = SIG_EM; 14662 } else if (!strcasecmp(v->value, "em_e1")) { 14663 confp->chan.outsigmod = SIG_EM_E1; 14664 } else if (!strcasecmp(v->value, "em_w")) { 14665 confp->chan.outsigmod = SIG_EMWINK; 14666 } else if (!strcasecmp(v->value, "sf")) { 14667 confp->chan.outsigmod = SIG_SF; 14668 } else if (!strcasecmp(v->value, "sf_w")) { 14669 confp->chan.outsigmod = SIG_SFWINK; 14670 } else if (!strcasecmp(v->value, "sf_featd")) { 14671 confp->chan.outsigmod = SIG_FEATD; 14672 } else if (!strcasecmp(v->value, "sf_featdmf")) { 14673 confp->chan.outsigmod = SIG_FEATDMF; 14674 } else if (!strcasecmp(v->value, "sf_featb")) { 14675 confp->chan.outsigmod = SIG_SF_FEATB; 14676 } else if (!strcasecmp(v->value, "sf")) { 14677 confp->chan.outsigmod = SIG_SF; 14678 } else if (!strcasecmp(v->value, "featd")) { 14679 confp->chan.outsigmod = SIG_FEATD; 14680 } else if (!strcasecmp(v->value, "featdmf")) { 14681 confp->chan.outsigmod = SIG_FEATDMF; 14682 } else if (!strcasecmp(v->value, "featdmf_ta")) { 14683 confp->chan.outsigmod = SIG_FEATDMF_TA; 14684 } else if (!strcasecmp(v->value, "e911")) { 14685 confp->chan.outsigmod = SIG_E911; 14686 } else if (!strcasecmp(v->value, "fgccama")) { 14687 confp->chan.outsigmod = SIG_FGC_CAMA; 14688 } else if (!strcasecmp(v->value, "fgccamamf")) { 14689 confp->chan.outsigmod = SIG_FGC_CAMAMF; 14690 } else if (!strcasecmp(v->value, "featb")) { 14691 confp->chan.outsigmod = SIG_FEATB; 14692 } else { 14693 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 14694 } 14695 #ifdef HAVE_PRI 14696 } else if (!strcasecmp(v->name, "pridialplan")) { 14697 if (!strcasecmp(v->value, "national")) { 14698 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1; 14699 } else if (!strcasecmp(v->value, "unknown")) { 14700 confp->pri.dialplan = PRI_UNKNOWN + 1; 14701 } else if (!strcasecmp(v->value, "private")) { 14702 confp->pri.dialplan = PRI_PRIVATE + 1; 14703 } else if (!strcasecmp(v->value, "international")) { 14704 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1; 14705 } else if (!strcasecmp(v->value, "local")) { 14706 confp->pri.dialplan = PRI_LOCAL_ISDN + 1; 14707 } else if (!strcasecmp(v->value, "dynamic")) { 14708 confp->pri.dialplan = -1; 14709 } else if (!strcasecmp(v->value, "redundant")) { 14710 confp->pri.dialplan = -2; 14711 } else { 14712 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 14713 } 14714 } else if (!strcasecmp(v->name, "prilocaldialplan")) { 14715 if (!strcasecmp(v->value, "national")) { 14716 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1; 14717 } else if (!strcasecmp(v->value, "unknown")) { 14718 confp->pri.localdialplan = PRI_UNKNOWN + 1; 14719 } else if (!strcasecmp(v->value, "private")) { 14720 confp->pri.localdialplan = PRI_PRIVATE + 1; 14721 } else if (!strcasecmp(v->value, "international")) { 14722 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1; 14723 } else if (!strcasecmp(v->value, "local")) { 14724 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1; 14725 } else if (!strcasecmp(v->value, "dynamic")) { 14726 confp->pri.localdialplan = -1; 14727 } else if (!strcasecmp(v->value, "redundant")) { 14728 confp->pri.localdialplan = -2; 14729 } else { 14730 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno); 14731 } 14732 } else if (!strcasecmp(v->name, "switchtype")) { 14733 if (!strcasecmp(v->value, "national")) 14734 confp->pri.switchtype = PRI_SWITCH_NI2; 14735 else if (!strcasecmp(v->value, "ni1")) 14736 confp->pri.switchtype = PRI_SWITCH_NI1; 14737 else if (!strcasecmp(v->value, "dms100")) 14738 confp->pri.switchtype = PRI_SWITCH_DMS100; 14739 else if (!strcasecmp(v->value, "4ess")) 14740 confp->pri.switchtype = PRI_SWITCH_ATT4ESS; 14741 else if (!strcasecmp(v->value, "5ess")) 14742 confp->pri.switchtype = PRI_SWITCH_LUCENT5E; 14743 else if (!strcasecmp(v->value, "euroisdn")) 14744 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1; 14745 else if (!strcasecmp(v->value, "qsig")) 14746 confp->pri.switchtype = PRI_SWITCH_QSIG; 14747 else { 14748 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno); 14749 return -1; 14750 } 14751 } else if (!strcasecmp(v->name, "nsf")) { 14752 if (!strcasecmp(v->value, "sdn")) 14753 confp->pri.nsf = PRI_NSF_SDN; 14754 else if (!strcasecmp(v->value, "megacom")) 14755 confp->pri.nsf = PRI_NSF_MEGACOM; 14756 else if (!strcasecmp(v->value, "tollfreemegacom")) 14757 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM; 14758 else if (!strcasecmp(v->value, "accunet")) 14759 confp->pri.nsf = PRI_NSF_ACCUNET; 14760 else if (!strcasecmp(v->value, "none")) 14761 confp->pri.nsf = PRI_NSF_NONE; 14762 else { 14763 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno); 14764 confp->pri.nsf = PRI_NSF_NONE; 14765 } 14766 } else if (!strcasecmp(v->name, "priindication")) { 14767 if (!strcasecmp(v->value, "outofband")) 14768 confp->chan.priindication_oob = 1; 14769 else if (!strcasecmp(v->value, "inband")) 14770 confp->chan.priindication_oob = 0; 14771 else 14772 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n", 14773 v->value, v->lineno); 14774 } else if (!strcasecmp(v->name, "priexclusive")) { 14775 confp->chan.priexclusive = ast_true(v->value); 14776 } else if (!strcasecmp(v->name, "internationalprefix")) { 14777 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix)); 14778 } else if (!strcasecmp(v->name, "nationalprefix")) { 14779 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix)); 14780 } else if (!strcasecmp(v->name, "localprefix")) { 14781 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix)); 14782 } else if (!strcasecmp(v->name, "privateprefix")) { 14783 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix)); 14784 } else if (!strcasecmp(v->name, "unknownprefix")) { 14785 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix)); 14786 } else if (!strcasecmp(v->name, "resetinterval")) { 14787 if (!strcasecmp(v->value, "never")) 14788 confp->pri.resetinterval = -1; 14789 else if (atoi(v->value) >= 60) 14790 confp->pri.resetinterval = atoi(v->value); 14791 else 14792 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n", 14793 v->value, v->lineno); 14794 } else if (!strcasecmp(v->name, "minunused")) { 14795 confp->pri.minunused = atoi(v->value); 14796 } else if (!strcasecmp(v->name, "minidle")) { 14797 confp->pri.minidle = atoi(v->value); 14798 } else if (!strcasecmp(v->name, "idleext")) { 14799 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext)); 14800 } else if (!strcasecmp(v->name, "idledial")) { 14801 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial)); 14802 } else if (!strcasecmp(v->name, "overlapdial")) { 14803 if (ast_true(v->value)) { 14804 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 14805 } else if (!strcasecmp(v->value, "incoming")) { 14806 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING; 14807 } else if (!strcasecmp(v->value, "outgoing")) { 14808 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING; 14809 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) { 14810 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 14811 } else { 14812 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE; 14813 } 14814 #ifdef HAVE_PRI_INBANDDISCONNECT 14815 } else if (!strcasecmp(v->name, "inbanddisconnect")) { 14816 confp->pri.inbanddisconnect = ast_true(v->value); 14817 #endif 14818 } else if (!strcasecmp(v->name, "pritimer")) { 14819 #ifdef PRI_GETSET_TIMERS 14820 char tmp[20], *timerc, *c = tmp; 14821 int timer, timeridx; 14822 ast_copy_string(tmp, v->value, sizeof(tmp)); 14823 timerc = strsep(&c, ","); 14824 if (timerc) { 14825 timer = atoi(c); 14826 if (!timer) 14827 ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer at line %d.\n", timerc, v->lineno); 14828 else { 14829 if ((timeridx = pri_timer2idx(timerc)) >= 0) 14830 pritimers[timeridx] = timer; 14831 else 14832 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer at line %d.\n", timerc, v->lineno); 14833 } 14834 } else 14835 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string at line %d.\n", v->value, v->lineno); 14836 14837 } else if (!strcasecmp(v->name, "facilityenable")) { 14838 confp->pri.facilityenable = ast_true(v->value); 14839 #endif /* PRI_GETSET_TIMERS */ 14840 #endif /* HAVE_PRI */ 14841 #ifdef HAVE_SS7 14842 } else if (!strcasecmp(v->name, "ss7type")) { 14843 if (!strcasecmp(v->value, "itu")) { 14844 cur_ss7type = SS7_ITU; 14845 } else if (!strcasecmp(v->value, "ansi")) { 14846 cur_ss7type = SS7_ANSI; 14847 } else 14848 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno); 14849 } else if (!strcasecmp(v->name, "linkset")) { 14850 cur_linkset = atoi(v->value); 14851 } else if (!strcasecmp(v->name, "pointcode")) { 14852 cur_pointcode = parse_pointcode(v->value); 14853 } else if (!strcasecmp(v->name, "adjpointcode")) { 14854 cur_adjpointcode = parse_pointcode(v->value); 14855 } else if (!strcasecmp(v->name, "defaultdpc")) { 14856 cur_defaultdpc = parse_pointcode(v->value); 14857 } else if (!strcasecmp(v->name, "cicbeginswith")) { 14858 cur_cicbeginswith = atoi(v->value); 14859 } else if (!strcasecmp(v->name, "networkindicator")) { 14860 if (!strcasecmp(v->value, "national")) 14861 cur_networkindicator = SS7_NI_NAT; 14862 else if (!strcasecmp(v->value, "national_spare")) 14863 cur_networkindicator = SS7_NI_NAT_SPARE; 14864 else if (!strcasecmp(v->value, "international")) 14865 cur_networkindicator = SS7_NI_INT; 14866 else if (!strcasecmp(v->value, "international_spare")) 14867 cur_networkindicator = SS7_NI_INT_SPARE; 14868 else 14869 cur_networkindicator = -1; 14870 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) { 14871 ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix)); 14872 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) { 14873 ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix)); 14874 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) { 14875 ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix)); 14876 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) { 14877 ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix)); 14878 } else if (!strcasecmp(v->name, "ss7_called_nai")) { 14879 if (!strcasecmp(v->value, "national")) { 14880 confp->ss7.called_nai = SS7_NAI_NATIONAL; 14881 } else if (!strcasecmp(v->value, "international")) { 14882 confp->ss7.called_nai = SS7_NAI_INTERNATIONAL; 14883 } else if (!strcasecmp(v->value, "subscriber")) { 14884 confp->ss7.called_nai = SS7_NAI_SUBSCRIBER; 14885 } else if (!strcasecmp(v->value, "dynamic")) { 14886 confp->ss7.called_nai = SS7_NAI_DYNAMIC; 14887 } else { 14888 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno); 14889 } 14890 } else if (!strcasecmp(v->name, "ss7_calling_nai")) { 14891 if (!strcasecmp(v->value, "national")) { 14892 confp->ss7.calling_nai = SS7_NAI_NATIONAL; 14893 } else if (!strcasecmp(v->value, "international")) { 14894 confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL; 14895 } else if (!strcasecmp(v->value, "subscriber")) { 14896 confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER; 14897 } else if (!strcasecmp(v->value, "dynamic")) { 14898 confp->ss7.calling_nai = SS7_NAI_DYNAMIC; 14899 } else { 14900 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno); 14901 } 14902 } else if (!strcasecmp(v->name, "sigchan")) { 14903 int sigchan, res; 14904 sigchan = atoi(v->value); 14905 res = linkset_addsigchan(sigchan); 14906 if (res < 0) 14907 return -1; 14908 14909 } else if (!strcasecmp(v->name, "ss7_explicitacm")) { 14910 struct dahdi_ss7 *link; 14911 link = ss7_resolve_linkset(cur_linkset); 14912 if (!link) { 14913 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1); 14914 return -1; 14915 } 14916 if (ast_true(v->value)) 14917 link->flags |= LINKSET_FLAG_EXPLICITACM; 14918 14919 #endif /* HAVE_SS7 */ 14920 } else if (!strcasecmp(v->name, "cadence")) { 14921 /* setup to scan our argument */ 14922 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 14923 int i; 14924 struct dahdi_ring_cadence new_cadence; 14925 int cid_location = -1; 14926 int firstcadencepos = 0; 14927 char original_args[80]; 14928 int cadence_is_ok = 1; 14929 14930 ast_copy_string(original_args, v->value, sizeof(original_args)); 14931 /* 16 cadences allowed (8 pairs) */ 14932 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]); 14933 14934 /* Cadence must be even (on/off) */ 14935 if (element_count % 2 == 1) { 14936 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno); 14937 cadence_is_ok = 0; 14938 } 14939 14940 /* Ring cadences cannot be negative */ 14941 for (i = 0; i < element_count; i++) { 14942 if (c[i] == 0) { 14943 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno); 14944 cadence_is_ok = 0; 14945 break; 14946 } else if (c[i] < 0) { 14947 if (i % 2 == 1) { 14948 /* Silence duration, negative possibly okay */ 14949 if (cid_location == -1) { 14950 cid_location = i; 14951 c[i] *= -1; 14952 } else { 14953 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno); 14954 cadence_is_ok = 0; 14955 break; 14956 } 14957 } else { 14958 if (firstcadencepos == 0) { 14959 firstcadencepos = i; /* only recorded to avoid duplicate specification */ 14960 /* duration will be passed negative to the DAHDI driver */ 14961 } else { 14962 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno); 14963 cadence_is_ok = 0; 14964 break; 14965 } 14966 } 14967 } 14968 } 14969 14970 /* Substitute our scanned cadence */ 14971 for (i = 0; i < 16; i++) { 14972 new_cadence.ringcadence[i] = c[i]; 14973 } 14974 14975 if (cadence_is_ok) { 14976 /* ---we scanned it without getting annoyed; now some sanity checks--- */ 14977 if (element_count < 2) { 14978 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno); 14979 } else { 14980 if (cid_location == -1) { 14981 /* user didn't say; default to first pause */ 14982 cid_location = 1; 14983 } else { 14984 /* convert element_index to cidrings value */ 14985 cid_location = (cid_location + 1) / 2; 14986 } 14987 /* ---we like their cadence; try to install it--- */ 14988 if (!user_has_defined_cadences++) 14989 /* this is the first user-defined cadence; clear the default user cadences */ 14990 num_cadence = 0; 14991 if ((num_cadence+1) >= NUM_CADENCE_MAX) 14992 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno); 14993 else { 14994 cadences[num_cadence] = new_cadence; 14995 cidrings[num_cadence++] = cid_location; 14996 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args); 14997 } 14998 } 14999 } 15000 } else if (!strcasecmp(v->name, "ringtimeout")) { 15001 ringt_base = (atoi(v->value) * 8) / READ_SIZE; 15002 } else if (!strcasecmp(v->name, "prewink")) { 15003 confp->timing.prewinktime = atoi(v->value); 15004 } else if (!strcasecmp(v->name, "preflash")) { 15005 confp->timing.preflashtime = atoi(v->value); 15006 } else if (!strcasecmp(v->name, "wink")) { 15007 confp->timing.winktime = atoi(v->value); 15008 } else if (!strcasecmp(v->name, "flash")) { 15009 confp->timing.flashtime = atoi(v->value); 15010 } else if (!strcasecmp(v->name, "start")) { 15011 confp->timing.starttime = atoi(v->value); 15012 } else if (!strcasecmp(v->name, "rxwink")) { 15013 confp->timing.rxwinktime = atoi(v->value); 15014 } else if (!strcasecmp(v->name, "rxflash")) { 15015 confp->timing.rxflashtime = atoi(v->value); 15016 } else if (!strcasecmp(v->name, "debounce")) { 15017 confp->timing.debouncetime = atoi(v->value); 15018 } else if (!strcasecmp(v->name, "toneduration")) { 15019 int toneduration; 15020 int ctlfd; 15021 int res; 15022 struct dahdi_dialparams dps; 15023 15024 ctlfd = open("/dev/dahdi/ctl", O_RDWR); 15025 if (ctlfd == -1) { 15026 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno); 15027 return -1; 15028 } 15029 15030 toneduration = atoi(v->value); 15031 if (toneduration > -1) { 15032 memset(&dps, 0, sizeof(dps)); 15033 15034 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration; 15035 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps); 15036 if (res < 0) { 15037 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno)); 15038 return -1; 15039 } 15040 } 15041 close(ctlfd); 15042 } else if (!strcasecmp(v->name, "defaultcic")) { 15043 ast_copy_string(defaultcic, v->value, sizeof(defaultcic)); 15044 } else if (!strcasecmp(v->name, "defaultozz")) { 15045 ast_copy_string(defaultozz, v->value, sizeof(defaultozz)); 15046 } else if (!strcasecmp(v->name, "mwilevel")) { 15047 mwilevel = atoi(v->value); 15048 } 15049 } else if (!(options & PROC_DAHDI_OPT_NOWARN) ) 15050 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno); 15051 } 15052 if (dahdichan[0]) { 15053 /* The user has set 'dahdichan' */ 15054 /*< \todo pass proper line number instead of 0 */ 15055 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) { 15056 return -1; 15057 } 15058 } 15059 /*< \todo why check for the pseudo in the per-channel section. 15060 * Any actual use for manual setup of the pseudo channel? */ 15061 if (!found_pseudo && reload == 0) { 15062 /* use the default configuration for a channel, so 15063 that any settings from real configured channels 15064 don't "leak" into the pseudo channel config 15065 */ 15066 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 15067 15068 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload); 15069 15070 if (tmp) { 15071 ast_verb(3, "Automatically generated pseudo channel\n"); 15072 } else { 15073 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n"); 15074 } 15075 } 15076 return 0; 15077 }
static void process_echocancel | ( | struct dahdi_chan_conf * | confp, | |
const char * | data, | |||
unsigned int | line | |||
) | [static] |
Definition at line 14178 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().
14179 { 14180 char *parse = ast_strdupa(data); 14181 char *params[DAHDI_MAX_ECHOCANPARAMS + 1]; 14182 unsigned int param_count; 14183 unsigned int x; 14184 14185 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params)))) 14186 return; 14187 14188 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel)); 14189 14190 /* first parameter is tap length, process it here */ 14191 14192 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]); 14193 14194 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024)) 14195 confp->chan.echocancel.head.tap_length = x; 14196 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0]))) 14197 confp->chan.echocancel.head.tap_length = 128; 14198 14199 /* now process any remaining parameters */ 14200 14201 for (x = 1; x < param_count; x++) { 14202 struct { 14203 char *name; 14204 char *value; 14205 } param; 14206 14207 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) { 14208 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]); 14209 continue; 14210 } 14211 14212 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) { 14213 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name); 14214 continue; 14215 } 14216 14217 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name); 14218 14219 if (param.value) { 14220 if (sscanf(param.value, "%d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) { 14221 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value); 14222 continue; 14223 } 14224 } 14225 confp->chan.echocancel.head.param_count++; 14226 } 14227 }
static char* redirectingreason2str | ( | int | redirectingreason | ) | [static] |
Definition at line 10807 of file chan_dahdi.c.
Referenced by __oh323_new().
10808 { 10809 switch (redirectingreason) { 10810 case 0: 10811 return "UNKNOWN"; 10812 case 1: 10813 return "BUSY"; 10814 case 2: 10815 return "NO_REPLY"; 10816 case 0xF: 10817 return "UNCONDITIONAL"; 10818 default: 10819 return "NOREDIRECT"; 10820 } 10821 }
static int reload | ( | void | ) | [static] |
Definition at line 15447 of file chan_dahdi.c.
References ast_log(), and setup_dahdi().
15448 { 15449 int res = 0; 15450 15451 res = setup_dahdi(1); 15452 if (res) { 15453 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n"); 15454 return -1; 15455 } 15456 return 0; 15457 }
static int reset_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1954 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().
01955 { 01956 p->confno = -1; 01957 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf)); 01958 if (p->subs[SUB_REAL].dfd > -1) { 01959 struct dahdi_confinfo zi; 01960 01961 memset(&zi, 0, sizeof(zi)); 01962 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi)) 01963 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno)); 01964 } 01965 return 0; 01966 }
static int restart_monitor | ( | void | ) | [static] |
Definition at line 8511 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().
08512 { 08513 /* If we're supposed to be stopped -- stay stopped */ 08514 if (monitor_thread == AST_PTHREADT_STOP) 08515 return 0; 08516 ast_mutex_lock(&monlock); 08517 if (monitor_thread == pthread_self()) { 08518 ast_mutex_unlock(&monlock); 08519 ast_log(LOG_WARNING, "Cannot kill myself\n"); 08520 return -1; 08521 } 08522 if (monitor_thread != AST_PTHREADT_NULL) { 08523 /* Wake up the thread */ 08524 pthread_kill(monitor_thread, SIGURG); 08525 } else { 08526 /* Start a new monitor */ 08527 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 08528 ast_mutex_unlock(&monlock); 08529 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 08530 return -1; 08531 } 08532 } 08533 ast_mutex_unlock(&monlock); 08534 return 0; 08535 }
static int restore_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2333 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().
02334 { 02335 int res; 02336 if (p->saveconf.confmode) { 02337 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf); 02338 p->saveconf.confmode = 0; 02339 if (res) { 02340 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno)); 02341 return -1; 02342 } 02343 } 02344 ast_debug(1, "Restored conferencing\n"); 02345 return 0; 02346 }
static int restore_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2214 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().
02215 { 02216 int res; 02217 02218 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02219 if (res) { 02220 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno)); 02221 return -1; 02222 } 02223 02224 return 0; 02225 }
static int save_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2260 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().
02261 { 02262 struct dahdi_confinfo c; 02263 int res; 02264 if (p->saveconf.confmode) { 02265 ast_log(LOG_WARNING, "Can't save conference -- already in use\n"); 02266 return -1; 02267 } 02268 p->saveconf.chan = 0; 02269 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf); 02270 if (res) { 02271 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno)); 02272 p->saveconf.confmode = 0; 02273 return -1; 02274 } 02275 memset(&c, 0, sizeof(c)); 02276 c.confmode = DAHDI_CONF_NORMAL; 02277 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c); 02278 if (res) { 02279 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno)); 02280 return -1; 02281 } 02282 ast_debug(1, "Disabled conferencing\n"); 02283 return 0; 02284 }
static int send_callerid | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2390 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().
02391 { 02392 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */ 02393 int res; 02394 /* Take out of linear mode if necessary */ 02395 if (p->subs[SUB_REAL].linear) { 02396 p->subs[SUB_REAL].linear = 0; 02397 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 02398 } 02399 while (p->cidpos < p->cidlen) { 02400 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos); 02401 if (res < 0) { 02402 if (errno == EAGAIN) 02403 return 0; 02404 else { 02405 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 02406 return -1; 02407 } 02408 } 02409 if (!res) 02410 return 0; 02411 p->cidpos += res; 02412 } 02413 ast_free(p->cidspill); 02414 p->cidspill = NULL; 02415 if (p->callwaitcas) { 02416 /* Wait for CID/CW to expire */ 02417 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES; 02418 } else 02419 restore_conference(p); 02420 return 0; 02421 }
static int send_cwcidspill | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2350 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().
02351 { 02352 p->callwaitcas = 0; 02353 p->cidcwexpire = 0; 02354 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) 02355 return -1; 02356 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p)); 02357 /* Make sure we account for the end */ 02358 p->cidlen += READ_SIZE * 4; 02359 p->cidpos = 0; 02360 send_callerid(p); 02361 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num); 02362 return 0; 02363 }
static int set_actual_gain | ( | int | fd, | |
int | chan, | |||
float | rxgain, | |||
float | txgain, | |||
int | law | |||
) | [static] |
Definition at line 2195 of file chan_dahdi.c.
References set_actual_rxgain(), and set_actual_txgain().
Referenced by bump_gains(), dahdi_call(), and restore_gains().
02196 { 02197 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law); 02198 }
static int set_actual_rxgain | ( | int | fd, | |
int | chan, | |||
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2177 of file chan_dahdi.c.
References ast_debug, errno, and fill_rxgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
02178 { 02179 struct dahdi_gains g; 02180 int res; 02181 02182 memset(&g, 0, sizeof(g)); 02183 g.chan = chan; 02184 res = ioctl(fd, DAHDI_GETGAINS, &g); 02185 if (res) { 02186 ast_debug(1, "Failed to read gains: %s\n", strerror(errno)); 02187 return res; 02188 } 02189 02190 fill_rxgain(&g, gain, law); 02191 02192 return ioctl(fd, DAHDI_SETGAINS, &g); 02193 }
static int set_actual_txgain | ( | int | fd, | |
int | chan, | |||
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2159 of file chan_dahdi.c.
References ast_debug, errno, and fill_txgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
02160 { 02161 struct dahdi_gains g; 02162 int res; 02163 02164 memset(&g, 0, sizeof(g)); 02165 g.chan = chan; 02166 res = ioctl(fd, DAHDI_GETGAINS, &g); 02167 if (res) { 02168 ast_debug(1, "Failed to read gains: %s\n", strerror(errno)); 02169 return res; 02170 } 02171 02172 fill_txgain(&g, gain, law); 02173 02174 return ioctl(fd, DAHDI_SETGAINS, &g); 02175 }
static int setup_dahdi | ( | int | reload | ) | [static] |
Definition at line 15079 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_flags, 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, PROC_DAHDI_OPT_NOCHAN, PROC_DAHDI_OPT_NOWARN, process_dahdi(), pvts, restart_monitor(), start_pri(), and ast_variable::value.
Referenced by dahdi_restart(), load_module(), and reload().
15080 { 15081 struct ast_config *cfg, *ucfg; 15082 struct ast_variable *v; 15083 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default(); 15084 struct dahdi_chan_conf conf; 15085 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 15086 const char *cat; 15087 int res; 15088 15089 #ifdef HAVE_PRI 15090 char *c; 15091 int spanno; 15092 int i; 15093 int logicalspan; 15094 int trunkgroup; 15095 int dchannels[NUM_DCHANS]; 15096 #endif 15097 15098 cfg = ast_config_load(config, config_flags); 15099 15100 /* Error if we have no config file */ 15101 if (!cfg) { 15102 ast_log(LOG_ERROR, "Unable to load config %s\n", config); 15103 return 0; 15104 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 15105 ucfg = ast_config_load("users.conf", config_flags); 15106 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) 15107 return 0; 15108 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 15109 cfg = ast_config_load(config, config_flags); 15110 } else { 15111 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 15112 ucfg = ast_config_load("users.conf", config_flags); 15113 } 15114 15115 /* It's a little silly to lock it, but we mind as well just to be sure */ 15116 ast_mutex_lock(&iflock); 15117 #ifdef HAVE_PRI 15118 if (reload != 1) { 15119 /* Process trunkgroups first */ 15120 v = ast_variable_browse(cfg, "trunkgroups"); 15121 while (v) { 15122 if (!strcasecmp(v->name, "trunkgroup")) { 15123 trunkgroup = atoi(v->value); 15124 if (trunkgroup > 0) { 15125 if ((c = strchr(v->value, ','))) { 15126 i = 0; 15127 memset(dchannels, 0, sizeof(dchannels)); 15128 while (c && (i < NUM_DCHANS)) { 15129 dchannels[i] = atoi(c + 1); 15130 if (dchannels[i] < 0) { 15131 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); 15132 } else 15133 i++; 15134 c = strchr(c + 1, ','); 15135 } 15136 if (i) { 15137 if (pri_create_trunkgroup(trunkgroup, dchannels)) { 15138 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); 15139 } else 15140 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"); 15141 } else 15142 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 15143 } else 15144 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 15145 } else 15146 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno); 15147 } else if (!strcasecmp(v->name, "spanmap")) { 15148 spanno = atoi(v->value); 15149 if (spanno > 0) { 15150 if ((c = strchr(v->value, ','))) { 15151 trunkgroup = atoi(c + 1); 15152 if (trunkgroup > 0) { 15153 if ((c = strchr(c + 1, ','))) 15154 logicalspan = atoi(c + 1); 15155 else 15156 logicalspan = 0; 15157 if (logicalspan >= 0) { 15158 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { 15159 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 15160 } else 15161 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 15162 } else 15163 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); 15164 } else 15165 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno); 15166 } else 15167 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno); 15168 } else 15169 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno); 15170 } else { 15171 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); 15172 } 15173 v = v->next; 15174 } 15175 } 15176 #endif 15177 15178 /* Copy the default jb config over global_jbconf */ 15179 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf)); 15180 15181 mwimonitornotify[0] = '\0'; 15182 15183 v = ast_variable_browse(cfg, "channels"); 15184 if ((res = process_dahdi(&base_conf, "", v, reload, 0))) { 15185 ast_mutex_unlock(&iflock); 15186 ast_config_destroy(cfg); 15187 if (ucfg) { 15188 ast_config_destroy(ucfg); 15189 } 15190 return res; 15191 } 15192 15193 /* Now get configuration from all normal sections in chan_dahdi.conf: */ 15194 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) { 15195 /* [channels] and [trunkgroups] are used. Let's also reserve 15196 * [globals] and [general] for future use 15197 */ 15198 if (!strcasecmp(cat, "general") || 15199 !strcasecmp(cat, "trunkgroups") || 15200 !strcasecmp(cat, "globals") || 15201 !strcasecmp(cat, "channels")) { 15202 continue; 15203 } 15204 15205 memcpy(&conf, &base_conf, sizeof(conf)); 15206 15207 if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) { 15208 ast_mutex_unlock(&iflock); 15209 ast_config_destroy(cfg); 15210 if (ucfg) { 15211 ast_config_destroy(cfg); 15212 } 15213 return res; 15214 } 15215 } 15216 15217 ast_config_destroy(cfg); 15218 15219 if (ucfg) { 15220 const char *chans; 15221 15222 process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0); 15223 15224 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) { 15225 if (!strcasecmp(cat, "general")) { 15226 continue; 15227 } 15228 15229 chans = ast_variable_retrieve(ucfg, cat, "dahdichan"); 15230 15231 if (ast_strlen_zero(chans)) { 15232 continue; 15233 } 15234 15235 memcpy(&conf, &base_conf, sizeof(conf)); 15236 15237 if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) { 15238 ast_config_destroy(ucfg); 15239 ast_mutex_unlock(&iflock); 15240 return res; 15241 } 15242 } 15243 ast_config_destroy(ucfg); 15244 } 15245 ast_mutex_unlock(&iflock); 15246 15247 #ifdef HAVE_PRI 15248 if (reload != 1) { 15249 int x; 15250 for (x = 0; x < NUM_SPANS; x++) { 15251 if (pris[x].pvts[0]) { 15252 if (start_pri(pris + x)) { 15253 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1); 15254 return -1; 15255 } else 15256 ast_verb(2, "Starting D-Channel on span %d\n", x + 1); 15257 } 15258 } 15259 } 15260 #endif 15261 #ifdef HAVE_SS7 15262 if (reload != 1) { 15263 int x; 15264 for (x = 0; x < NUM_SPANS; x++) { 15265 if (linksets[x].ss7) { 15266 if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) { 15267 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1); 15268 return -1; 15269 } else 15270 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1); 15271 } 15272 } 15273 } 15274 #endif 15275 /* And start the monitor for the first time */ 15276 restart_monitor(); 15277 return 0; 15278 }
static int sigtype_to_signalling | ( | int | sigtype | ) | [static] |
static void * ss_thread | ( | void * | data | ) | [static] |
Definition at line 6530 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_digitreset(), ast_dsp_free(), ast_dsp_set_digitmode(), 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().
06531 { 06532 struct ast_channel *chan = data; 06533 struct dahdi_pvt *p = chan->tech_pvt; 06534 char exten[AST_MAX_EXTENSION] = ""; 06535 char exten2[AST_MAX_EXTENSION] = ""; 06536 unsigned char buf[256]; 06537 char dtmfcid[300]; 06538 char dtmfbuf[300]; 06539 struct callerid_state *cs = NULL; 06540 char *name = NULL, *number = NULL; 06541 int distMatches; 06542 int curRingData[3]; 06543 int receivedRingT; 06544 int counter1; 06545 int counter; 06546 int samples = 0; 06547 struct ast_smdi_md_message *smdi_msg = NULL; 06548 int flags; 06549 int i; 06550 int timeout; 06551 int getforward = 0; 06552 char *s1, *s2; 06553 int len = 0; 06554 int res; 06555 int idx; 06556 06557 ast_mutex_lock(&ss_thread_lock); 06558 ss_thread_count++; 06559 ast_mutex_unlock(&ss_thread_lock); 06560 /* in the bizarre case where the channel has become a zombie before we 06561 even get started here, abort safely 06562 */ 06563 if (!p) { 06564 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name); 06565 ast_hangup(chan); 06566 goto quit; 06567 } 06568 ast_verb(3, "Starting simple switch on '%s'\n", chan->name); 06569 idx = dahdi_get_index(chan, p, 1); 06570 if (idx < 0) { 06571 ast_log(LOG_WARNING, "Huh?\n"); 06572 ast_hangup(chan); 06573 goto quit; 06574 } 06575 if (p->dsp) 06576 ast_dsp_digitreset(p->dsp); 06577 switch (p->sig) { 06578 #ifdef HAVE_PRI 06579 case SIG_PRI: 06580 case SIG_BRI: 06581 case SIG_BRI_PTMP: 06582 /* Now loop looking for an extension */ 06583 ast_copy_string(exten, p->exten, sizeof(exten)); 06584 len = strlen(exten); 06585 res = 0; 06586 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 06587 if (len && !ast_ignore_pattern(chan->context, exten)) 06588 tone_zone_play_tone(p->subs[idx].dfd, -1); 06589 else 06590 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 06591 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) 06592 timeout = matchdigittimeout; 06593 else 06594 timeout = gendigittimeout; 06595 res = ast_waitfordigit(chan, timeout); 06596 if (res < 0) { 06597 ast_debug(1, "waitfordigit returned < 0...\n"); 06598 ast_hangup(chan); 06599 goto quit; 06600 } else if (res) { 06601 exten[len++] = res; 06602 exten[len] = '\0'; 06603 } else 06604 break; 06605 } 06606 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */ 06607 if (ast_strlen_zero(exten)) { 06608 ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n"); 06609 exten[0] = 's'; 06610 exten[1] = '\0'; 06611 } 06612 tone_zone_play_tone(p->subs[idx].dfd, -1); 06613 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) { 06614 /* Start the real PBX */ 06615 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06616 if (p->dsp) ast_dsp_digitreset(p->dsp); 06617 dahdi_enable_ec(p); 06618 ast_setstate(chan, AST_STATE_RING); 06619 res = ast_pbx_run(chan); 06620 if (res) { 06621 ast_log(LOG_WARNING, "PBX exited non-zero!\n"); 06622 } 06623 } else { 06624 ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context); 06625 chan->hangupcause = AST_CAUSE_UNALLOCATED; 06626 ast_hangup(chan); 06627 p->exten[0] = '\0'; 06628 /* Since we send release complete here, we won't get one */ 06629 p->call = NULL; 06630 } 06631 goto quit; 06632 break; 06633 #endif 06634 case SIG_FEATD: 06635 case SIG_FEATDMF: 06636 case SIG_FEATDMF_TA: 06637 case SIG_E911: 06638 case SIG_FGC_CAMAMF: 06639 case SIG_FEATB: 06640 case SIG_EMWINK: 06641 case SIG_SF_FEATD: 06642 case SIG_SF_FEATDMF: 06643 case SIG_SF_FEATB: 06644 case SIG_SFWINK: 06645 if (dahdi_wink(p, idx)) 06646 goto quit; 06647 /* Fall through */ 06648 case SIG_EM: 06649 case SIG_EM_E1: 06650 case SIG_SF: 06651 case SIG_FGC_CAMA: 06652 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 06653 if (p->dsp) 06654 ast_dsp_digitreset(p->dsp); 06655 /* set digit mode appropriately */ 06656 if (p->dsp) { 06657 if (NEED_MFDETECT(p)) 06658 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 06659 else 06660 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 06661 } 06662 memset(dtmfbuf, 0, sizeof(dtmfbuf)); 06663 /* Wait for the first digit only if immediate=no */ 06664 if (!p->immediate) 06665 /* Wait for the first digit (up to 5 seconds). */ 06666 res = ast_waitfordigit(chan, 5000); 06667 else 06668 res = 0; 06669 if (res > 0) { 06670 /* save first char */ 06671 dtmfbuf[0] = res; 06672 switch (p->sig) { 06673 case SIG_FEATD: 06674 case SIG_SF_FEATD: 06675 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06676 if (res > 0) 06677 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06678 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06679 break; 06680 case SIG_FEATDMF_TA: 06681 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06682 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06683 if (dahdi_wink(p, idx)) goto quit; 06684 dtmfbuf[0] = 0; 06685 /* Wait for the first digit (up to 5 seconds). */ 06686 res = ast_waitfordigit(chan, 5000); 06687 if (res <= 0) break; 06688 dtmfbuf[0] = res; 06689 /* fall through intentionally */ 06690 case SIG_FEATDMF: 06691 case SIG_E911: 06692 case SIG_FGC_CAMAMF: 06693 case SIG_SF_FEATDMF: 06694 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06695 /* if international caca, do it again to get real ANO */ 06696 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14)) 06697 { 06698 if (dahdi_wink(p, idx)) goto quit; 06699 dtmfbuf[0] = 0; 06700 /* Wait for the first digit (up to 5 seconds). */ 06701 res = ast_waitfordigit(chan, 5000); 06702 if (res <= 0) break; 06703 dtmfbuf[0] = res; 06704 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06705 } 06706 if (res > 0) { 06707 /* if E911, take off hook */ 06708 if (p->sig == SIG_E911) 06709 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06710 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000); 06711 } 06712 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06713 break; 06714 case SIG_FEATB: 06715 case SIG_SF_FEATB: 06716 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06717 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06718 break; 06719 case SIG_EMWINK: 06720 /* if we received a '*', we are actually receiving Feature Group D 06721 dial syntax, so use that mode; otherwise, fall through to normal 06722 mode 06723 */ 06724 if (res == '*') { 06725 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06726 if (res > 0) 06727 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06728 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06729 break; 06730 } 06731 default: 06732 /* If we got the first digit, get the rest */ 06733 len = 1; 06734 dtmfbuf[len] = '\0'; 06735 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06736 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06737 timeout = matchdigittimeout; 06738 } else { 06739 timeout = gendigittimeout; 06740 } 06741 res = ast_waitfordigit(chan, timeout); 06742 if (res < 0) { 06743 ast_debug(1, "waitfordigit returned < 0...\n"); 06744 ast_hangup(chan); 06745 goto quit; 06746 } else if (res) { 06747 dtmfbuf[len++] = res; 06748 dtmfbuf[len] = '\0'; 06749 } else { 06750 break; 06751 } 06752 } 06753 break; 06754 } 06755 } 06756 if (res == -1) { 06757 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno)); 06758 ast_hangup(chan); 06759 goto quit; 06760 } else if (res < 0) { 06761 ast_debug(1, "Got hung up before digits finished\n"); 06762 ast_hangup(chan); 06763 goto quit; 06764 } 06765 06766 if (p->sig == SIG_FGC_CAMA) { 06767 char anibuf[100]; 06768 06769 if (ast_safe_sleep(chan,1000) == -1) { 06770 ast_hangup(chan); 06771 goto quit; 06772 } 06773 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06774 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 06775 res = my_getsigstr(chan, anibuf, "#", 10000); 06776 if ((res > 0) && (strlen(anibuf) > 2)) { 06777 if (anibuf[strlen(anibuf) - 1] == '#') 06778 anibuf[strlen(anibuf) - 1] = 0; 06779 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2); 06780 } 06781 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 06782 } 06783 06784 ast_copy_string(exten, dtmfbuf, sizeof(exten)); 06785 if (ast_strlen_zero(exten)) 06786 ast_copy_string(exten, "s", sizeof(exten)); 06787 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) { 06788 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */ 06789 if (exten[0] == '*') { 06790 char *stringp=NULL; 06791 ast_copy_string(exten2, exten, sizeof(exten2)); 06792 /* Parse out extension and callerid */ 06793 stringp=exten2 +1; 06794 s1 = strsep(&stringp, "*"); 06795 s2 = strsep(&stringp, "*"); 06796 if (s2) { 06797 if (!ast_strlen_zero(p->cid_num)) 06798 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 06799 else 06800 ast_set_callerid(chan, s1, NULL, s1); 06801 ast_copy_string(exten, s2, sizeof(exten)); 06802 } else 06803 ast_copy_string(exten, s1, sizeof(exten)); 06804 } else if (p->sig == SIG_FEATD) 06805 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 06806 } 06807 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 06808 if (exten[0] == '*') { 06809 char *stringp=NULL; 06810 ast_copy_string(exten2, exten, sizeof(exten2)); 06811 /* Parse out extension and callerid */ 06812 stringp=exten2 +1; 06813 s1 = strsep(&stringp, "#"); 06814 s2 = strsep(&stringp, "#"); 06815 if (s2) { 06816 if (!ast_strlen_zero(p->cid_num)) 06817 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 06818 else 06819 if (*(s1 + 2)) 06820 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2); 06821 ast_copy_string(exten, s2 + 1, sizeof(exten)); 06822 } else 06823 ast_copy_string(exten, s1 + 2, sizeof(exten)); 06824 } else 06825 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 06826 } 06827 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) { 06828 if (exten[0] == '*') { 06829 char *stringp=NULL; 06830 ast_copy_string(exten2, exten, sizeof(exten2)); 06831 /* Parse out extension and callerid */ 06832 stringp=exten2 +1; 06833 s1 = strsep(&stringp, "#"); 06834 s2 = strsep(&stringp, "#"); 06835 if (s2 && (*(s2 + 1) == '0')) { 06836 if (*(s2 + 2)) 06837 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2); 06838 } 06839 if (s1) ast_copy_string(exten, s1, sizeof(exten)); 06840 else ast_copy_string(exten, "911", sizeof(exten)); 06841 } else 06842 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel); 06843 } 06844 if (p->sig == SIG_FEATB) { 06845 if (exten[0] == '*') { 06846 char *stringp=NULL; 06847 ast_copy_string(exten2, exten, sizeof(exten2)); 06848 /* Parse out extension and callerid */ 06849 stringp=exten2 +1; 06850 s1 = strsep(&stringp, "#"); 06851 ast_copy_string(exten, exten2 + 1, sizeof(exten)); 06852 } else 06853 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel); 06854 } 06855 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 06856 dahdi_wink(p, idx); 06857 /* some switches require a minimum guard time between 06858 the last FGD wink and something that answers 06859 immediately. This ensures it */ 06860 if (ast_safe_sleep(chan,100)) goto quit; 06861 } 06862 dahdi_enable_ec(p); 06863 if (NEED_MFDETECT(p)) { 06864 if (p->dsp) { 06865 if (!p->hardwaredtmf) 06866 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 06867 else { 06868 ast_dsp_free(p->dsp); 06869 p->dsp = NULL; 06870 } 06871 } 06872 } 06873 06874 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) { 06875 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06876 if (p->dsp) ast_dsp_digitreset(p->dsp); 06877 res = ast_pbx_run(chan); 06878 if (res) { 06879 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 06880 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06881 } 06882 goto quit; 06883 } else { 06884 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context); 06885 sleep(2); 06886 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO); 06887 if (res < 0) 06888 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel); 06889 else 06890 sleep(1); 06891 res = ast_streamfile(chan, "ss-noservice", chan->language); 06892 if (res >= 0) 06893 ast_waitstream(chan, ""); 06894 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06895 ast_hangup(chan); 06896 goto quit; 06897 } 06898 break; 06899 case SIG_FXOLS: 06900 case SIG_FXOGS: 06901 case SIG_FXOKS: 06902 /* Read the first digit */ 06903 timeout = firstdigittimeout; 06904 /* If starting a threeway call, never timeout on the first digit so someone 06905 can use flash-hook as a "hold" feature */ 06906 if (p->subs[SUB_THREEWAY].owner) 06907 timeout = 999999; 06908 while (len < AST_MAX_EXTENSION-1) { 06909 /* Read digit unless it's supposed to be immediate, in which case the 06910 only answer is 's' */ 06911 if (p->immediate) 06912 res = 's'; 06913 else 06914 res = ast_waitfordigit(chan, timeout); 06915 timeout = 0; 06916 if (res < 0) { 06917 ast_debug(1, "waitfordigit returned < 0...\n"); 06918 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 06919 ast_hangup(chan); 06920 goto quit; 06921 } else if (res) { 06922 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout); 06923 exten[len++]=res; 06924 exten[len] = '\0'; 06925 } 06926 if (!ast_ignore_pattern(chan->context, exten)) 06927 tone_zone_play_tone(p->subs[idx].dfd, -1); 06928 else 06929 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 06930 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) { 06931 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 06932 if (getforward) { 06933 /* Record this as the forwarding extension */ 06934 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 06935 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel); 06936 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 06937 if (res) 06938 break; 06939 usleep(500000); 06940 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 06941 sleep(1); 06942 memset(exten, 0, sizeof(exten)); 06943 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 06944 len = 0; 06945 getforward = 0; 06946 } else { 06947 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 06948 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06949 if (!ast_strlen_zero(p->cid_num)) { 06950 if (!p->hidecallerid) 06951 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 06952 else 06953 ast_set_callerid(chan, NULL, NULL, p->cid_num); 06954 } 06955 if (!ast_strlen_zero(p->cid_name)) { 06956 if (!p->hidecallerid) 06957 ast_set_callerid(chan, NULL, p->cid_name, NULL); 06958 } 06959 ast_setstate(chan, AST_STATE_RING); 06960 dahdi_enable_ec(p); 06961 res = ast_pbx_run(chan); 06962 if (res) { 06963 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 06964 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06965 } 06966 goto quit; 06967 } 06968 } else { 06969 /* It's a match, but they just typed a digit, and there is an ambiguous match, 06970 so just set the timeout to matchdigittimeout and wait some more */ 06971 timeout = matchdigittimeout; 06972 } 06973 } else if (res == 0) { 06974 ast_debug(1, "not enough digits (and no ambiguous match)...\n"); 06975 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06976 dahdi_wait_event(p->subs[idx].dfd); 06977 ast_hangup(chan); 06978 goto quit; 06979 } else if (p->callwaiting && !strcmp(exten, "*70")) { 06980 ast_verb(3, "Disabling call waiting on %s\n", chan->name); 06981 /* Disable call waiting if enabled */ 06982 p->callwaiting = 0; 06983 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 06984 if (res) { 06985 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 06986 chan->name, strerror(errno)); 06987 } 06988 len = 0; 06989 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len); 06990 memset(exten, 0, sizeof(exten)); 06991 timeout = firstdigittimeout; 06992 06993 } else if (!strcmp(exten,ast_pickup_ext())) { 06994 /* Scan all channels and see if there are any 06995 * ringing channels that have call groups 06996 * that equal this channels pickup group 06997 */ 06998 if (idx == SUB_REAL) { 06999 /* Switch us from Third call to Call Wait */ 07000 if (p->subs[SUB_THREEWAY].owner) { 07001 /* If you make a threeway call and the *8# a call, it should actually 07002 look like a callwait */ 07003 alloc_sub(p, SUB_CALLWAIT); 07004 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 07005 unalloc_sub(p, SUB_THREEWAY); 07006 } 07007 dahdi_enable_ec(p); 07008 if (ast_pickup_call(chan)) { 07009 ast_debug(1, "No call pickup possible...\n"); 07010 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07011 dahdi_wait_event(p->subs[idx].dfd); 07012 } 07013 ast_hangup(chan); 07014 goto quit; 07015 } else { 07016 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n"); 07017 ast_hangup(chan); 07018 goto quit; 07019 } 07020 07021 } else if (!p->hidecallerid && !strcmp(exten, "*67")) { 07022 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name); 07023 /* Disable Caller*ID if enabled */ 07024 p->hidecallerid = 1; 07025 if (chan->cid.cid_num) 07026 ast_free(chan->cid.cid_num); 07027 chan->cid.cid_num = NULL; 07028 if (chan->cid.cid_name) 07029 ast_free(chan->cid.cid_name); 07030 chan->cid.cid_name = NULL; 07031 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07032 if (res) { 07033 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07034 chan->name, strerror(errno)); 07035 } 07036 len = 0; 07037 memset(exten, 0, sizeof(exten)); 07038 timeout = firstdigittimeout; 07039 } else if (p->callreturn && !strcmp(exten, "*69")) { 07040 res = 0; 07041 if (!ast_strlen_zero(p->lastcid_num)) { 07042 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language); 07043 } 07044 if (!res) 07045 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07046 break; 07047 } else if (!strcmp(exten, "*78")) { 07048 dahdi_dnd(p, 1); 07049 /* Do not disturb */ 07050 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07051 getforward = 0; 07052 memset(exten, 0, sizeof(exten)); 07053 len = 0; 07054 } else if (!strcmp(exten, "*79")) { 07055 dahdi_dnd(p, 0); 07056 /* Do not disturb */ 07057 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07058 getforward = 0; 07059 memset(exten, 0, sizeof(exten)); 07060 len = 0; 07061 } else if (p->cancallforward && !strcmp(exten, "*72")) { 07062 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07063 getforward = 1; 07064 memset(exten, 0, sizeof(exten)); 07065 len = 0; 07066 } else if (p->cancallforward && !strcmp(exten, "*73")) { 07067 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel); 07068 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07069 memset(p->call_forward, 0, sizeof(p->call_forward)); 07070 getforward = 0; 07071 memset(exten, 0, sizeof(exten)); 07072 len = 0; 07073 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 07074 p->subs[SUB_THREEWAY].owner && 07075 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 07076 /* This is a three way call, the main call being a real channel, 07077 and we're parking the first call. */ 07078 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL); 07079 ast_verb(3, "Parking call to '%s'\n", chan->name); 07080 break; 07081 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) { 07082 ast_verb(3, "Blacklisting number %s\n", p->lastcid_num); 07083 res = ast_db_put("blacklist", p->lastcid_num, "1"); 07084 if (!res) { 07085 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07086 memset(exten, 0, sizeof(exten)); 07087 len = 0; 07088 } 07089 } else if (p->hidecallerid && !strcmp(exten, "*82")) { 07090 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name); 07091 /* Enable Caller*ID if enabled */ 07092 p->hidecallerid = 0; 07093 if (chan->cid.cid_num) 07094 ast_free(chan->cid.cid_num); 07095 chan->cid.cid_num = NULL; 07096 if (chan->cid.cid_name) 07097 ast_free(chan->cid.cid_name); 07098 chan->cid.cid_name = NULL; 07099 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 07100 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07101 if (res) { 07102 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07103 chan->name, strerror(errno)); 07104 } 07105 len = 0; 07106 memset(exten, 0, sizeof(exten)); 07107 timeout = firstdigittimeout; 07108 } else if (!strcmp(exten, "*0")) { 07109 struct ast_channel *nbridge = 07110 p->subs[SUB_THREEWAY].owner; 07111 struct dahdi_pvt *pbridge = NULL; 07112 /* set up the private struct of the bridged one, if any */ 07113 if (nbridge && ast_bridged_channel(nbridge)) 07114 pbridge = ast_bridged_channel(nbridge)->tech_pvt; 07115 if (nbridge && pbridge && 07116 (nbridge->tech == &dahdi_tech) && 07117 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) && 07118 ISTRUNK(pbridge)) { 07119 int func = DAHDI_FLASH; 07120 /* Clear out the dial buffer */ 07121 p->dop.dialstr[0] = '\0'; 07122 /* flash hookswitch */ 07123 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 07124 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 07125 nbridge->name, strerror(errno)); 07126 } 07127 swap_subs(p, SUB_REAL, SUB_THREEWAY); 07128 unalloc_sub(p, SUB_THREEWAY); 07129 p->owner = p->subs[SUB_REAL].owner; 07130 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 07131 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 07132 ast_hangup(chan); 07133 goto quit; 07134 } else { 07135 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07136 dahdi_wait_event(p->subs[idx].dfd); 07137 tone_zone_play_tone(p->subs[idx].dfd, -1); 07138 swap_subs(p, SUB_REAL, SUB_THREEWAY); 07139 unalloc_sub(p, SUB_THREEWAY); 07140 p->owner = p->subs[SUB_REAL].owner; 07141 ast_hangup(chan); 07142 goto quit; 07143 } 07144 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) && 07145 ((exten[0] != '*') || (strlen(exten) > 2))) { 07146 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); 07147 break; 07148 } 07149 if (!timeout) 07150 timeout = gendigittimeout; 07151 if (len && !ast_ignore_pattern(chan->context, exten)) 07152 tone_zone_play_tone(p->subs[idx].dfd, -1); 07153 } 07154 break; 07155 case SIG_FXSLS: 07156 case SIG_FXSGS: 07157 case SIG_FXSKS: 07158 #ifdef HAVE_PRI 07159 if (p->pri) { 07160 /* This is a GR-303 trunk actually. Wait for the first ring... */ 07161 struct ast_frame *f; 07162 int res; 07163 time_t start; 07164 07165 time(&start); 07166 ast_setstate(chan, AST_STATE_RING); 07167 while (time(NULL) < start + 3) { 07168 res = ast_waitfor(chan, 1000); 07169 if (res) { 07170 f = ast_read(chan); 07171 if (!f) { 07172 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n"); 07173 ast_hangup(chan); 07174 goto quit; 07175 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) { 07176 res = 1; 07177 } else 07178 res = 0; 07179 ast_frfree(f); 07180 if (res) { 07181 ast_debug(1, "Got ring!\n"); 07182 res = 0; 07183 break; 07184 } 07185 } 07186 } 07187 } 07188 #endif 07189 /* check for SMDI messages */ 07190 if (p->use_smdi && p->smdi_iface) { 07191 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); 07192 07193 if (smdi_msg != NULL) { 07194 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten)); 07195 07196 if (smdi_msg->type == 'B') 07197 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b"); 07198 else if (smdi_msg->type == 'N') 07199 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u"); 07200 07201 ast_debug(1, "Recieved SMDI message on %s\n", chan->name); 07202 } else { 07203 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n"); 07204 } 07205 } 07206 07207 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) { 07208 number = smdi_msg->calling_st; 07209 07210 /* If we want caller id, we're in a prering state due to a polarity reversal 07211 * and we're set to use a polarity reversal to trigger the start of caller id, 07212 * grab the caller id and wait for ringing to start... */ 07213 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) { 07214 /* If set to use DTMF CID signalling, listen for DTMF */ 07215 if (p->cid_signalling == CID_SIG_DTMF) { 07216 int k = 0; 07217 cs = NULL; 07218 ast_debug(1, "Receiving DTMF cid on " 07219 "channel %s\n", chan->name); 07220 dahdi_setlinear(p->subs[idx].dfd, 0); 07221 res = 2000; 07222 for (;;) { 07223 struct ast_frame *f; 07224 res = ast_waitfor(chan, res); 07225 if (res <= 0) { 07226 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 07227 "Exiting simple switch\n"); 07228 ast_hangup(chan); 07229 goto quit; 07230 } 07231 f = ast_read(chan); 07232 if (!f) 07233 break; 07234 if (f->frametype == AST_FRAME_DTMF) { 07235 dtmfbuf[k++] = f->subclass; 07236 ast_debug(1, "CID got digit '%c'\n", f->subclass); 07237 res = 2000; 07238 } 07239 ast_frfree(f); 07240 if (chan->_state == AST_STATE_RING || 07241 chan->_state == AST_STATE_RINGING) 07242 break; /* Got ring */ 07243 } 07244 dtmfbuf[k] = '\0'; 07245 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 07246 /* Got cid and ring. */ 07247 ast_debug(1, "CID got string '%s'\n", dtmfbuf); 07248 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 07249 ast_debug(1, "CID is '%s', flags %d\n", 07250 dtmfcid, flags); 07251 /* If first byte is NULL, we have no cid */ 07252 if (!ast_strlen_zero(dtmfcid)) 07253 number = dtmfcid; 07254 else 07255 number = NULL; 07256 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 07257 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { 07258 cs = callerid_new(p->cid_signalling); 07259 if (cs) { 07260 samples = 0; 07261 #if 1 07262 bump_gains(p); 07263 #endif 07264 /* Take out of linear mode for Caller*ID processing */ 07265 dahdi_setlinear(p->subs[idx].dfd, 0); 07266 07267 /* First we wait and listen for the Caller*ID */ 07268 for (;;) { 07269 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07270 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 07271 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07272 callerid_free(cs); 07273 ast_hangup(chan); 07274 goto quit; 07275 } 07276 if (i & DAHDI_IOMUX_SIGEVENT) { 07277 res = dahdi_get_event(p->subs[idx].dfd); 07278 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07279 07280 if (p->cid_signalling == CID_SIG_V23_JP) { 07281 if (res == DAHDI_EVENT_RINGBEGIN) { 07282 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07283 usleep(1); 07284 } 07285 } else { 07286 res = 0; 07287 break; 07288 } 07289 } else if (i & DAHDI_IOMUX_READ) { 07290 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 07291 if (res < 0) { 07292 if (errno != ELAST) { 07293 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07294 callerid_free(cs); 07295 ast_hangup(chan); 07296 goto quit; 07297 } 07298 break; 07299 } 07300 samples += res; 07301 07302 if (p->cid_signalling == CID_SIG_V23_JP) { 07303 res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); 07304 } else { 07305 res = callerid_feed(cs, buf, res, AST_LAW(p)); 07306 } 07307 07308 if (res < 0) { 07309 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name); 07310 break; 07311 } else if (res) 07312 break; 07313 else if (samples > (8000 * 10)) 07314 break; 07315 } 07316 } 07317 if (res == 1) { 07318 callerid_get(cs, &name, &number, &flags); 07319 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 07320 } 07321 07322 if (p->cid_signalling == CID_SIG_V23_JP) { 07323 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 07324 usleep(1); 07325 res = 4000; 07326 } else { 07327 07328 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 07329 res = 2000; 07330 } 07331 07332 for (;;) { 07333 struct ast_frame *f; 07334 res = ast_waitfor(chan, res); 07335 if (res <= 0) { 07336 ast_log(LOG_WARNING, "CID timed out waiting for ring. " 07337 "Exiting simple switch\n"); 07338 ast_hangup(chan); 07339 goto quit; 07340 } 07341 if (!(f = ast_read(chan))) { 07342 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); 07343 ast_hangup(chan); 07344 goto quit; 07345 } 07346 ast_frfree(f); 07347 if (chan->_state == AST_STATE_RING || 07348 chan->_state == AST_STATE_RINGING) 07349 break; /* Got ring */ 07350 } 07351 07352 /* We must have a ring by now, so, if configured, lets try to listen for 07353 * distinctive ringing */ 07354 if (p->usedistinctiveringdetection) { 07355 len = 0; 07356 distMatches = 0; 07357 /* Clear the current ring data array so we dont have old data in it. */ 07358 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 07359 curRingData[receivedRingT] = 0; 07360 receivedRingT = 0; 07361 counter = 0; 07362 counter1 = 0; 07363 /* Check to see if context is what it should be, if not set to be. */ 07364 if (strcmp(p->context,p->defcontext) != 0) { 07365 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 07366 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 07367 } 07368 07369 for (;;) { 07370 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07371 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 07372 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07373 callerid_free(cs); 07374 ast_hangup(chan); 07375 goto quit; 07376 } 07377 if (i & DAHDI_IOMUX_SIGEVENT) { 07378 res = dahdi_get_event(p->subs[idx].dfd); 07379 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07380 res = 0; 07381 /* Let us detect distinctive ring */ 07382 07383 curRingData[receivedRingT] = p->ringt; 07384 07385 if (p->ringt < p->ringt_base/2) 07386 break; 07387 /* Increment the ringT counter so we can match it against 07388 values in chan_dahdi.conf for distinctive ring */ 07389 if (++receivedRingT == ARRAY_LEN(curRingData)) 07390 break; 07391 } else if (i & DAHDI_IOMUX_READ) { 07392 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 07393 if (res < 0) { 07394 if (errno != ELAST) { 07395 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07396 callerid_free(cs); 07397 ast_hangup(chan); 07398 goto quit; 07399 } 07400 break; 07401 } 07402 if (p->ringt) 07403 p->ringt--; 07404 if (p->ringt == 1) { 07405 res = -1; 07406 break; 07407 } 07408 } 07409 } 07410 /* this only shows up if you have n of the dring patterns filled in */ 07411 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 07412 for (counter = 0; counter < 3; counter++) { 07413 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 07414 channel */ 07415 distMatches = 0; 07416 for (counter1 = 0; counter1 < 3; counter1++) { 07417 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 07418 if (p->drings.ringnum[counter].ring[counter1] == -1) { 07419 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 07420 curRingData[counter1]); 07421 distMatches++; 07422 } 07423 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 07424 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 07425 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 07426 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 07427 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 07428 distMatches++; 07429 } 07430 } 07431 07432 if (distMatches == 3) { 07433 /* The ring matches, set the context to whatever is for distinctive ring.. */ 07434 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 07435 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 07436 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 07437 break; 07438 } 07439 } 07440 } 07441 /* Restore linear mode (if appropriate) for Caller*ID processing */ 07442 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 07443 #if 1 07444 restore_gains(p); 07445 #endif 07446 } else 07447 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 07448 } else { 07449 ast_log(LOG_WARNING, "Channel %s in prering " 07450 "state, but I have nothing to do. " 07451 "Terminating simple switch, should be " 07452 "restarted by the actual ring.\n", 07453 chan->name); 07454 ast_hangup(chan); 07455 goto quit; 07456 } 07457 } else if (p->use_callerid && p->cid_start == CID_START_RING) { 07458 if (p->cid_signalling == CID_SIG_DTMF) { 07459 int k = 0; 07460 cs = NULL; 07461 dahdi_setlinear(p->subs[idx].dfd, 0); 07462 res = 2000; 07463 for (;;) { 07464 struct ast_frame *f; 07465 res = ast_waitfor(chan, res); 07466 if (res <= 0) { 07467 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 07468 "Exiting simple switch\n"); 07469 ast_hangup(chan); 07470 return NULL; 07471 } 07472 f = ast_read(chan); 07473 if (f->frametype == AST_FRAME_DTMF) { 07474 dtmfbuf[k++] = f->subclass; 07475 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass); 07476 res = 2000; 07477 } 07478 ast_frfree(f); 07479 07480 if (p->ringt_base == p->ringt) 07481 break; 07482 07483 } 07484 dtmfbuf[k] = '\0'; 07485 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 07486 /* Got cid and ring. */ 07487 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 07488 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 07489 dtmfcid, flags); 07490 /* If first byte is NULL, we have no cid */ 07491 if (!ast_strlen_zero(dtmfcid)) 07492 number = dtmfcid; 07493 else 07494 number = NULL; 07495 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 07496 } else { 07497 /* FSK Bell202 callerID */ 07498 cs = callerid_new(p->cid_signalling); 07499 if (cs) { 07500 #if 1 07501 bump_gains(p); 07502 #endif 07503 samples = 0; 07504 len = 0; 07505 distMatches = 0; 07506 /* Clear the current ring data array so we dont have old data in it. */ 07507 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 07508 curRingData[receivedRingT] = 0; 07509 receivedRingT = 0; 07510 counter = 0; 07511 counter1 = 0; 07512 /* Check to see if context is what it should be, if not set to be. */ 07513 if (strcmp(p->context,p->defcontext) != 0) { 07514 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 07515 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 07516 } 07517 07518 /* Take out of linear mode for Caller*ID processing */ 07519 dahdi_setlinear(p->subs[idx].dfd, 0); 07520 for (;;) { 07521 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07522 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 07523 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07524 callerid_free(cs); 07525 ast_hangup(chan); 07526 goto quit; 07527 } 07528 if (i & DAHDI_IOMUX_SIGEVENT) { 07529 res = dahdi_get_event(p->subs[idx].dfd); 07530 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07531 /* If we get a PR event, they hung up while processing calerid */ 07532 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { 07533 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); 07534 p->polarity = POLARITY_IDLE; 07535 callerid_free(cs); 07536 ast_hangup(chan); 07537 goto quit; 07538 } 07539 res = 0; 07540 /* Let us detect callerid when the telco uses distinctive ring */ 07541 07542 curRingData[receivedRingT] = p->ringt; 07543 07544 if (p->ringt < p->ringt_base/2) 07545 break; 07546 /* Increment the ringT counter so we can match it against 07547 values in chan_dahdi.conf for distinctive ring */ 07548 if (++receivedRingT == ARRAY_LEN(curRingData)) 07549 break; 07550 } else if (i & DAHDI_IOMUX_READ) { 07551 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 07552 if (res < 0) { 07553 if (errno != ELAST) { 07554 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07555 callerid_free(cs); 07556 ast_hangup(chan); 07557 goto quit; 07558 } 07559 break; 07560 } 07561 if (p->ringt) 07562 p->ringt--; 07563 if (p->ringt == 1) { 07564 res = -1; 07565 break; 07566 } 07567 samples += res; 07568 res = callerid_feed(cs, buf, res, AST_LAW(p)); 07569 if (res < 0) { 07570 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno)); 07571 break; 07572 } else if (res) 07573 break; 07574 else if (samples > (8000 * 10)) 07575 break; 07576 } 07577 } 07578 if (res == 1) { 07579 callerid_get(cs, &name, &number, &flags); 07580 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 07581 } 07582 if (distinctiveringaftercid == 1) { 07583 /* Clear the current ring data array so we dont have old data in it. */ 07584 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) { 07585 curRingData[receivedRingT] = 0; 07586 } 07587 receivedRingT = 0; 07588 ast_verb(3, "Detecting post-CID distinctive ring\n"); 07589 for (;;) { 07590 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07591 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 07592 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07593 callerid_free(cs); 07594 ast_hangup(chan); 07595 goto quit; 07596 } 07597 if (i & DAHDI_IOMUX_SIGEVENT) { 07598 res = dahdi_get_event(p->subs[idx].dfd); 07599 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07600 res = 0; 07601 /* Let us detect callerid when the telco uses distinctive ring */ 07602 07603 curRingData[receivedRingT] = p->ringt; 07604 07605 if (p->ringt < p->ringt_base/2) 07606 break; 07607 /* Increment the ringT counter so we can match it against 07608 values in chan_dahdi.conf for distinctive ring */ 07609 if (++receivedRingT == ARRAY_LEN(curRingData)) 07610 break; 07611 } else if (i & DAHDI_IOMUX_READ) { 07612 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 07613 if (res < 0) { 07614 if (errno != ELAST) { 07615 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07616 callerid_free(cs); 07617 ast_hangup(chan); 07618 goto quit; 07619 } 07620 break; 07621 } 07622 if (p->ringt) 07623 p->ringt--; 07624 if (p->ringt == 1) { 07625 res = -1; 07626 break; 07627 } 07628 } 07629 } 07630 } 07631 if (p->usedistinctiveringdetection) { 07632 /* this only shows up if you have n of the dring patterns filled in */ 07633 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 07634 07635 for (counter = 0; counter < 3; counter++) { 07636 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 07637 channel */ 07638 /* this only shows up if you have n of the dring patterns filled in */ 07639 ast_verb(3, "Checking %d,%d,%d\n", 07640 p->drings.ringnum[counter].ring[0], 07641 p->drings.ringnum[counter].ring[1], 07642 p->drings.ringnum[counter].ring[2]); 07643 distMatches = 0; 07644 for (counter1 = 0; counter1 < 3; counter1++) { 07645 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 07646 if (p->drings.ringnum[counter].ring[counter1] == -1) { 07647 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 07648 curRingData[counter1]); 07649 distMatches++; 07650 } 07651 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 07652 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 07653 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 07654 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 07655 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 07656 distMatches++; 07657 } 07658 } 07659 if (distMatches == 3) { 07660 /* The ring matches, set the context to whatever is for distinctive ring.. */ 07661 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 07662 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 07663 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 07664 break; 07665 } 07666 } 07667 } 07668 /* Restore linear mode (if appropriate) for Caller*ID processing */ 07669 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 07670 #if 1 07671 restore_gains(p); 07672 #endif 07673 if (res < 0) { 07674 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); 07675 } 07676 } else 07677 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 07678 } 07679 } 07680 else 07681 cs = NULL; 07682 07683 if (number) 07684 ast_shrink_phone_number(number); 07685 ast_set_callerid(chan, number, name, number); 07686 07687 if (smdi_msg) 07688 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy); 07689 07690 if (cs) 07691 callerid_free(cs); 07692 /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */ 07693 if (flags & CID_MSGWAITING) { 07694 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel); 07695 notify_message(p->mailbox, 1); 07696 /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */ 07697 if (p->mwimonitor_rpas) { 07698 ast_hangup(chan); 07699 return NULL; 07700 } 07701 } else if (flags & CID_NOMSGWAITING) { 07702 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel); 07703 notify_message(p->mailbox, 0); 07704 /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */ 07705 if (p->mwimonitor_rpas) { 07706 ast_hangup(chan); 07707 return NULL; 07708 } 07709 } 07710 07711 ast_setstate(chan, AST_STATE_RING); 07712 chan->rings = 1; 07713 p->ringt = p->ringt_base; 07714 res = ast_pbx_run(chan); 07715 if (res) { 07716 ast_hangup(chan); 07717 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07718 } 07719 goto quit; 07720 default: 07721 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel); 07722 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07723 if (res < 0) 07724 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 07725 } 07726 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07727 if (res < 0) 07728 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 07729 ast_hangup(chan); 07730 quit: 07731 ast_mutex_lock(&ss_thread_lock); 07732 ss_thread_count--; 07733 ast_cond_signal(&ss_thread_complete); 07734 ast_mutex_unlock(&ss_thread_lock); 07735 return NULL; 07736 }
static int start_pri | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 11960 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().
11961 { 11962 int res, x; 11963 struct dahdi_params p; 11964 struct dahdi_bufferinfo bi; 11965 struct dahdi_spaninfo si; 11966 int i; 11967 11968 for (i = 0; i < NUM_DCHANS; i++) { 11969 if (!pri->dchannels[i]) 11970 break; 11971 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR); 11972 x = pri->dchannels[i]; 11973 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) { 11974 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno)); 11975 return -1; 11976 } 11977 memset(&p, 0, sizeof(p)); 11978 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p); 11979 if (res) { 11980 dahdi_close_pri_fd(pri, i); 11981 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno)); 11982 return -1; 11983 } 11984 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) { 11985 dahdi_close_pri_fd(pri, i); 11986 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x); 11987 return -1; 11988 } 11989 memset(&si, 0, sizeof(si)); 11990 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si); 11991 if (res) { 11992 dahdi_close_pri_fd(pri, i); 11993 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno)); 11994 } 11995 if (!si.alarms) 11996 pri->dchanavail[i] |= DCHAN_NOTINALARM; 11997 else 11998 pri->dchanavail[i] &= ~DCHAN_NOTINALARM; 11999 memset(&bi, 0, sizeof(bi)); 12000 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 12001 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 12002 bi.numbufs = 32; 12003 bi.bufsize = 1024; 12004 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) { 12005 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno)); 12006 dahdi_close_pri_fd(pri, i); 12007 return -1; 12008 } 12009 switch (pri->sig) { 12010 case SIG_BRI: 12011 pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype); 12012 break; 12013 case SIG_BRI_PTMP: 12014 pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype); 12015 break; 12016 default: 12017 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype); 12018 } 12019 /* Force overlap dial if we're doing GR-303! */ 12020 if (pri->switchtype == PRI_SWITCH_GR303_TMC) 12021 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH; 12022 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0); 12023 #ifdef HAVE_PRI_INBANDDISCONNECT 12024 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect); 12025 #endif 12026 /* Enslave to master if appropriate */ 12027 if (i) 12028 pri_enslave(pri->dchans[0], pri->dchans[i]); 12029 if (!pri->dchans[i]) { 12030 dahdi_close_pri_fd(pri, i); 12031 ast_log(LOG_ERROR, "Unable to create PRI structure\n"); 12032 return -1; 12033 } 12034 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG); 12035 pri_set_nsf(pri->dchans[i], pri->nsf); 12036 #ifdef PRI_GETSET_TIMERS 12037 for (x = 0; x < PRI_MAX_TIMERS; x++) { 12038 if (pritimers[x] != 0) 12039 pri_set_timer(pri->dchans[i], x, pritimers[x]); 12040 } 12041 #endif 12042 } 12043 /* Assume primary is the one we use */ 12044 pri->pri = pri->dchans[0]; 12045 pri->resetpos = -1; 12046 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) { 12047 for (i = 0; i < NUM_DCHANS; i++) { 12048 if (!pri->dchannels[i]) 12049 break; 12050 dahdi_close_pri_fd(pri, i); 12051 } 12052 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno)); 12053 return -1; 12054 } 12055 return 0; 12056 }
static void swap_subs | ( | struct dahdi_pvt * | p, | |
int | a, | |||
int | b | |||
) | [static] |
Definition at line 1428 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().
01429 { 01430 int tchan; 01431 int tinthreeway; 01432 struct ast_channel *towner; 01433 01434 ast_debug(1, "Swapping %d and %d\n", a, b); 01435 01436 tchan = p->subs[a].chan; 01437 towner = p->subs[a].owner; 01438 tinthreeway = p->subs[a].inthreeway; 01439 01440 p->subs[a].chan = p->subs[b].chan; 01441 p->subs[a].owner = p->subs[b].owner; 01442 p->subs[a].inthreeway = p->subs[b].inthreeway; 01443 01444 p->subs[b].chan = tchan; 01445 p->subs[b].owner = towner; 01446 p->subs[b].inthreeway = tinthreeway; 01447 01448 if (p->subs[a].owner) 01449 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd); 01450 if (p->subs[b].owner) 01451 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd); 01452 wakeup_sub(p, a, NULL); 01453 wakeup_sub(p, b, NULL); 01454 }
static int unalloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 1578 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().
01579 { 01580 if (!x) { 01581 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel); 01582 return -1; 01583 } 01584 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel); 01585 dahdi_close_sub(p, x); 01586 p->subs[x].linear = 0; 01587 p->subs[x].chan = 0; 01588 p->subs[x].owner = NULL; 01589 p->subs[x].inthreeway = 0; 01590 p->polarity = POLARITY_IDLE; 01591 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf)); 01592 return 0; 01593 }
static int unload_module | ( | void | ) | [static] |
Definition at line 14070 of file chan_dahdi.c.
References __unload_module(), ast_mutex_destroy(), lock, NUM_SPANS, and pris.
14071 { 14072 #if defined(HAVE_PRI) || defined(HAVE_SS7) 14073 int y; 14074 #endif 14075 #ifdef HAVE_PRI 14076 for (y = 0; y < NUM_SPANS; y++) 14077 ast_mutex_destroy(&pris[y].lock); 14078 #endif 14079 #ifdef HAVE_SS7 14080 for (y = 0; y < NUM_SPANS; y++) 14081 ast_mutex_destroy(&linksets[y].lock); 14082 #endif /* HAVE_SS7 */ 14083 return __unload_module(); 14084 }
static int update_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1968 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().
01969 { 01970 int needconf = 0; 01971 int x; 01972 int useslavenative; 01973 struct dahdi_pvt *slave = NULL; 01974 01975 useslavenative = isslavenative(p, &slave); 01976 /* Start with the obvious, general stuff */ 01977 for (x = 0; x < 3; x++) { 01978 /* Look for three way calls */ 01979 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) { 01980 conf_add(p, &p->subs[x], x, 0); 01981 needconf++; 01982 } else { 01983 conf_del(p, &p->subs[x], x); 01984 } 01985 } 01986 /* If we have a slave, add him to our conference now. or DAX 01987 if this is slave native */ 01988 for (x = 0; x < MAX_SLAVES; x++) { 01989 if (p->slaves[x]) { 01990 if (useslavenative) 01991 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 01992 else { 01993 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 01994 needconf++; 01995 } 01996 } 01997 } 01998 /* If we're supposed to be in there, do so now */ 01999 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 02000 if (useslavenative) 02001 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 02002 else { 02003 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 02004 needconf++; 02005 } 02006 } 02007 /* If we have a master, add ourselves to his conference */ 02008 if (p->master) { 02009 if (isslavenative(p->master, NULL)) { 02010 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 02011 } else { 02012 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 02013 } 02014 } 02015 if (!needconf) { 02016 /* Nobody is left (or should be left) in our conference. 02017 Kill it. */ 02018 p->confno = -1; 02019 } 02020 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf); 02021 return 0; 02022 }
Definition at line 1335 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().
01339 { 01340 #ifdef HAVE_PRI 01341 if (pri) 01342 ast_mutex_unlock(&pri->lock); 01343 #endif 01344 for (;;) { 01345 if (p->subs[a].owner) { 01346 if (ast_channel_trylock(p->subs[a].owner)) { 01347 DEADLOCK_AVOIDANCE(&p->lock); 01348 } else { 01349 ast_queue_frame(p->subs[a].owner, &ast_null_frame); 01350 ast_channel_unlock(p->subs[a].owner); 01351 break; 01352 } 01353 } else 01354 break; 01355 } 01356 #ifdef HAVE_PRI 01357 if (pri) 01358 ast_mutex_lock(&pri->lock); 01359 #endif 01360 }
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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 15481 of file chan_dahdi.c.
int alarm |
struct { ... } alarms[] [static] |
Referenced by alarm2str().
struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}} [static] |
Definition at line 1309 of file chan_dahdi.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 15481 of file chan_dahdi.c.
struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static] |
Definition at line 1290 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 1301 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 3264 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 3268 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static] |
Definition at line 3266 of file chan_dahdi.c.
struct ast_channel_tech dahdi_tech [static] |
Definition at line 1217 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 238 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 254 of file chan_dahdi.c.
Referenced by disa_exec(), and mgcp_ss().
int gendigittimeout = 8000 [static] |
How long to wait for following digits (FXO logic).
Definition at line 257 of file chan_dahdi.c.
Referenced by mgcp_ss().
struct ast_jb_conf global_jbconf [static] |
Definition at line 125 of file chan_dahdi.c.
int ifcount = 0 [static] |
Definition at line 266 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 263 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 245 of file chan_dahdi.c.
Referenced by 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 260 of file chan_dahdi.c.
Referenced by mgcp_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 278 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 274 of file chan_dahdi.c.
Referenced by __unload_module(), dahdi_restart(), do_monitor(), restart_monitor(), and unload_module().
ast_cond_t mwi_thread_complete [static] |
Definition at line 279 of file chan_dahdi.c.
int mwi_thread_count = 0 [static] |
Definition at line 284 of file chan_dahdi.c.
ast_mutex_t mwi_thread_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
int mwilevel = 512 [static] |
Definition at line 242 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 232 of file chan_dahdi.c.
int mwisend_rpas = 0 [static] |
Definition at line 233 of file chan_dahdi.c.
char* name |
Definition at line 1734 of file chan_dahdi.c.
int num_cadence = 4 [static] |
Definition at line 1287 of file chan_dahdi.c.
int num_restart_pending = 0 [static] |
Definition at line 286 of file chan_dahdi.c.
int numbufs = 4 [static] |
Definition at line 240 of file chan_dahdi.c.
char parkinglot[AST_MAX_EXTENSION] = "" [static] |
Default parking lot for this channel
Definition at line 229 of file chan_dahdi.c.
Referenced by __find_callno(), ast_iax2_new(), build_gateway(), build_parkinglot(), build_user(), check_access(), check_peer_ok(), create_addr_from_peer(), find_parkinglot(), findparkinglotname(), func_channel_write(), gtalk_load_config(), gtalk_new(), park_exec_full(), park_space_reserve(), parkinglot_addref(), parkinglot_cmp_cb(), parkinglot_hash_cb(), parkinglot_unref(), set_pvt_defaults(), sip_alloc(), and store_config_core().
int pridebugfd = -1 [static] |
Definition at line 249 of file chan_dahdi.c.
ast_mutex_t pridebugfdlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 269 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 250 of file chan_dahdi.c.
Definition at line 447 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 235 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 341 of file chan_dahdi.c.
struct dahdi_pvt* round_robin[32] |
ast_cond_t ss_thread_complete [static] |
Definition at line 280 of file chan_dahdi.c.
int ss_thread_count = 0 [static] |
Definition at line 285 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 237 of file chan_dahdi.c.
int user_has_defined_cadences = 0 [static] |
Definition at line 1288 of file chan_dahdi.c.