#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 struct dahdi_pvt * | 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 154 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 330 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 207 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 152 of file chan_dahdi.c.
#define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) |
#define CONF_USER_REAL (1 << 0) |
Definition at line 512 of file chan_dahdi.c.
#define CONF_USER_THIRDCALL (1 << 1) |
Definition at line 513 of file chan_dahdi.c.
#define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING) |
#define DAHDI_OVERLAPDIAL_INCOMING 2 |
Definition at line 218 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_read(), handle_pri_show_span(), and ss_thread().
#define DAHDI_OVERLAPDIAL_NONE 0 |
Definition at line 216 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 209 of file chan_dahdi.c.
Referenced by build_status(), pri_create_trunkgroup(), and pri_resolve_span().
#define DCHAN_UP (1 << 2) |
Definition at line 211 of file chan_dahdi.c.
#define DEFAULT_CIDRINGS 1 |
Typically, how many rings before we should send Caller*ID.
Definition at line 150 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 334 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 1240 of file chan_dahdi.c.
#define HANGUP 1 |
Definition at line 13459 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 1312 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 327 of file chan_dahdi.c.
#define MASK_INUSE (1 << 1) |
Channel currently in use
Definition at line 328 of file chan_dahdi.c.
#define MAX_CHANLIST_LEN 80 |
The length of the parameters list of 'dahdichan'.
Definition at line 14318 of file chan_dahdi.c.
Referenced by process_dahdi().
#define MAX_CHANNELS 672 |
No more than a DS3 per trunk group
Definition at line 205 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 158 of file chan_dahdi.c.
Referenced by dahdi_new(), and ss_thread().
#define NUM_CADENCE_MAX 25 |
Definition at line 1287 of file chan_dahdi.c.
#define NUM_DCHANS 4 |
No more than 4 d-channels
Definition at line 204 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 202 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 471 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_hangup(), and unalloc_sub().
#define POLARITY_REV 1 |
Definition at line 472 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 14372 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 14374 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 391 of file chan_dahdi.c.
Referenced by dahdi_call(), dahdi_indicate(), dahdi_write(), pri_check_restart(), and ss_thread().
#define READ_SIZE 160 |
Chunk size to read -- we use 20ms chunks to make things happy.
Definition at line 325 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 1837 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 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_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR) |
Definition at line 188 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 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_EM 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_EM_E1 DAHDI_SIG_EM_E1 |
Definition at line 195 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 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_FEATB (0x0800000 | 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_FEATD (0x0200000 | 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 (0x0400000 | 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_FEATDMF_TA (0x2000000 | 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_CAMA (0x4000000 | 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_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM) |
Definition at line 179 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 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(), and ss_thread().
#define SIG_FXOKS DAHDI_SIG_FXOKS |
Definition at line 185 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 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_FXSGS DAHDI_SIG_FXSGS |
Definition at line 181 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 182 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 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_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS) |
Definition at line 196 of file chan_dahdi.c.
Referenced by dahdi_sig2str(), handle_init_event(), and mkintf().
#define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS) |
Definition at line 197 of file chan_dahdi.c.
Referenced by dahdi_sig2str(), handle_init_event(), and mkintf().
#define SIG_PRI 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(), dahdi_write(), handle_init_event(), mkintf(), and ss_thread().
#define SIG_SF 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_SF_FEATB (0x0800000 | DAHDI_SIG_SF) |
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_SF_FEATD (0x0200000 | 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_SF_FEATDMF (0x0400000 | 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_SFWINK (0x0100000 | 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_SS7 (0x1000000 | DAHDI_SIG_CLEAR) |
Definition at line 189 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 467 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 466 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 468 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 15621 of file chan_dahdi.c.
#define TRAILER_MS 5 |
Referenced by dahdi_sendtext().
#define TRANSFER 0 |
Definition at line 13458 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 7989 of file chan_dahdi.c.
07989 { 07990 MWI_SEND_SA, 07991 MWI_SEND_SA_WAIT, 07992 MWI_SEND_PAUSE, 07993 MWI_SEND_SPILL, 07994 MWI_SEND_CLEANUP, 07995 MWI_SEND_DONE 07996 };
static struct ast_frame* __dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5571 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().
05572 { 05573 struct dahdi_pvt *p = ast->tech_pvt; 05574 int res; 05575 int usedindex=-1; 05576 int idx; 05577 struct ast_frame *f; 05578 05579 05580 idx = dahdi_get_index(ast, p, 1); 05581 05582 p->subs[idx].f.frametype = AST_FRAME_NULL; 05583 p->subs[idx].f.datalen = 0; 05584 p->subs[idx].f.samples = 0; 05585 p->subs[idx].f.mallocd = 0; 05586 p->subs[idx].f.offset = 0; 05587 p->subs[idx].f.subclass = 0; 05588 p->subs[idx].f.delivery = ast_tv(0,0); 05589 p->subs[idx].f.src = "dahdi_exception"; 05590 p->subs[idx].f.data.ptr = NULL; 05591 05592 05593 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) { 05594 /* If nobody owns us, absorb the event appropriately, otherwise 05595 we loop indefinitely. This occurs when, during call waiting, the 05596 other end hangs up our channel so that it no longer exists, but we 05597 have neither FLASH'd nor ONHOOK'd to signify our desire to 05598 change to the other channel. */ 05599 if (p->fake_event) { 05600 res = p->fake_event; 05601 p->fake_event = 0; 05602 } else 05603 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 05604 /* Switch to real if there is one and this isn't something really silly... */ 05605 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) && 05606 (res != DAHDI_EVENT_HOOKCOMPLETE)) { 05607 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res); 05608 p->owner = p->subs[SUB_REAL].owner; 05609 if (p->owner && ast_bridged_channel(p->owner)) 05610 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05611 p->subs[SUB_REAL].needunhold = 1; 05612 } 05613 switch (res) { 05614 case DAHDI_EVENT_ONHOOK: 05615 dahdi_disable_ec(p); 05616 if (p->owner) { 05617 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name); 05618 dahdi_ring_phone(p); 05619 p->callwaitingrepeat = 0; 05620 p->cidcwexpire = 0; 05621 } else 05622 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 05623 update_conf(p); 05624 break; 05625 case DAHDI_EVENT_RINGOFFHOOK: 05626 dahdi_enable_ec(p); 05627 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 05628 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) { 05629 p->subs[SUB_REAL].needanswer = 1; 05630 p->dialing = 0; 05631 } 05632 break; 05633 case DAHDI_EVENT_HOOKCOMPLETE: 05634 case DAHDI_EVENT_RINGERON: 05635 case DAHDI_EVENT_RINGEROFF: 05636 /* Do nothing */ 05637 break; 05638 case DAHDI_EVENT_WINKFLASH: 05639 p->flashtime = ast_tvnow(); 05640 if (p->owner) { 05641 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name); 05642 if (p->owner->_state != AST_STATE_UP) { 05643 /* Answer if necessary */ 05644 usedindex = dahdi_get_index(p->owner, p, 0); 05645 if (usedindex > -1) { 05646 p->subs[usedindex].needanswer = 1; 05647 } 05648 ast_setstate(p->owner, AST_STATE_UP); 05649 } 05650 p->callwaitingrepeat = 0; 05651 p->cidcwexpire = 0; 05652 if (ast_bridged_channel(p->owner)) 05653 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05654 p->subs[SUB_REAL].needunhold = 1; 05655 } else 05656 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 05657 update_conf(p); 05658 break; 05659 default: 05660 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res)); 05661 } 05662 f = &p->subs[idx].f; 05663 return f; 05664 } 05665 if (!(p->radio || (p->oprmode < 0))) 05666 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel); 05667 /* If it's not us, return NULL immediately */ 05668 if (ast != p->owner) { 05669 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name); 05670 f = &p->subs[idx].f; 05671 return f; 05672 } 05673 f = dahdi_handle_event(ast); 05674 return f; 05675 }
static void __reg_module | ( | void | ) | [static] |
Definition at line 15635 of file chan_dahdi.c.
static int __unload_module | ( | void | ) | [static] |
Definition at line 14135 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().
14136 { 14137 struct dahdi_pvt *p; 14138 #if defined(HAVE_PRI) || defined(HAVE_SS7) 14139 int i, j; 14140 #endif 14141 14142 #ifdef HAVE_PRI 14143 for (i = 0; i < NUM_SPANS; i++) { 14144 if (pris[i].master != AST_PTHREADT_NULL) 14145 pthread_cancel(pris[i].master); 14146 } 14147 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 14148 ast_unregister_application(dahdi_send_keypad_facility_app); 14149 #endif 14150 #if defined(HAVE_SS7) 14151 for (i = 0; i < NUM_SPANS; i++) { 14152 if (linksets[i].master != AST_PTHREADT_NULL) 14153 pthread_cancel(linksets[i].master); 14154 } 14155 ast_cli_unregister_multiple(dahdi_ss7_cli, sizeof(dahdi_ss7_cli) / sizeof(struct ast_cli_entry)); 14156 #endif 14157 14158 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 14159 ast_manager_unregister( "DAHDIDialOffhook" ); 14160 ast_manager_unregister( "DAHDIHangup" ); 14161 ast_manager_unregister( "DAHDITransfer" ); 14162 ast_manager_unregister( "DAHDIDNDoff" ); 14163 ast_manager_unregister( "DAHDIDNDon" ); 14164 ast_manager_unregister("DAHDIShowChannels"); 14165 ast_manager_unregister("DAHDIRestart"); 14166 ast_channel_unregister(&dahdi_tech); 14167 ast_mutex_lock(&iflock); 14168 /* Hangup all interfaces if they have an owner */ 14169 p = iflist; 14170 while (p) { 14171 if (p->owner) 14172 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 14173 p = p->next; 14174 } 14175 ast_mutex_unlock(&iflock); 14176 ast_mutex_lock(&monlock); 14177 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 14178 pthread_cancel(monitor_thread); 14179 pthread_kill(monitor_thread, SIGURG); 14180 pthread_join(monitor_thread, NULL); 14181 } 14182 monitor_thread = AST_PTHREADT_STOP; 14183 ast_mutex_unlock(&monlock); 14184 14185 destroy_all_channels(); 14186 14187 #if defined(HAVE_PRI) 14188 for (i = 0; i < NUM_SPANS; i++) { 14189 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) 14190 pthread_join(pris[i].master, NULL); 14191 for (j = 0; j < NUM_DCHANS; j++) { 14192 dahdi_close_pri_fd(&(pris[i]), j); 14193 } 14194 } 14195 #endif 14196 14197 #if defined(HAVE_SS7) 14198 for (i = 0; i < NUM_SPANS; i++) { 14199 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) 14200 pthread_join(linksets[i].master, NULL); 14201 for (j = 0; j < NUM_DCHANS; j++) { 14202 dahdi_close_ss7_fd(&(linksets[i]), j); 14203 } 14204 } 14205 #endif 14206 14207 ast_cond_destroy(&mwi_thread_complete); 14208 ast_cond_destroy(&ss_thread_complete); 14209 return 0; 14210 }
static void __unreg_module | ( | void | ) | [static] |
Definition at line 15635 of file chan_dahdi.c.
static int action_dahdidialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13565 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().
13566 { 13567 struct dahdi_pvt *p = NULL; 13568 const char *channel = astman_get_header(m, "DAHDIChannel"); 13569 const char *number = astman_get_header(m, "Number"); 13570 int i; 13571 13572 if (ast_strlen_zero(channel)) { 13573 astman_send_error(s, m, "No channel specified"); 13574 return 0; 13575 } 13576 if (ast_strlen_zero(number)) { 13577 astman_send_error(s, m, "No number specified"); 13578 return 0; 13579 } 13580 p = find_channel(atoi(channel)); 13581 if (!p) { 13582 astman_send_error(s, m, "No such channel"); 13583 return 0; 13584 } 13585 if (!p->owner) { 13586 astman_send_error(s, m, "Channel does not have it's owner"); 13587 return 0; 13588 } 13589 for (i = 0; i < strlen(number); i++) { 13590 struct ast_frame f = { AST_FRAME_DTMF, number[i] }; 13591 dahdi_queue_frame(p, &f, NULL); 13592 } 13593 astman_send_ack(s, m, "DAHDIDialOffhook"); 13594 return 0; 13595 }
static int action_dahdidndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13508 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().
13509 { 13510 struct dahdi_pvt *p = NULL; 13511 const char *channel = astman_get_header(m, "DAHDIChannel"); 13512 13513 if (ast_strlen_zero(channel)) { 13514 astman_send_error(s, m, "No channel specified"); 13515 return 0; 13516 } 13517 p = find_channel(atoi(channel)); 13518 if (!p) { 13519 astman_send_error(s, m, "No such channel"); 13520 return 0; 13521 } 13522 p->dnd = 0; 13523 astman_send_ack(s, m, "DND Disabled"); 13524 return 0; 13525 }
static int action_dahdidndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13489 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().
13490 { 13491 struct dahdi_pvt *p = NULL; 13492 const char *channel = astman_get_header(m, "DAHDIChannel"); 13493 13494 if (ast_strlen_zero(channel)) { 13495 astman_send_error(s, m, "No channel specified"); 13496 return 0; 13497 } 13498 p = find_channel(atoi(channel)); 13499 if (!p) { 13500 astman_send_error(s, m, "No such channel"); 13501 return 0; 13502 } 13503 p->dnd = 1; 13504 astman_send_ack(s, m, "DND Enabled"); 13505 return 0; 13506 }
static int action_dahdirestart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12763 of file chan_dahdi.c.
References astman_send_ack(), astman_send_error(), dahdi_restart(), and s.
Referenced by load_module().
12764 { 12765 if (dahdi_restart() != 0) { 12766 astman_send_error(s, m, "Failed rereading DAHDI configuration"); 12767 return 1; 12768 } 12769 astman_send_ack(s, m, "DAHDIRestart: Success"); 12770 return 0; 12771 }
static int action_dahdishowchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13597 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().
13598 { 13599 struct dahdi_pvt *tmp = NULL; 13600 const char *id = astman_get_header(m, "ActionID"); 13601 const char *dahdichannel = astman_get_header(m, "DAHDIChannel"); 13602 char idText[256] = ""; 13603 int channels = 0; 13604 int dahdichanquery = -1; 13605 if (!ast_strlen_zero(dahdichannel)) { 13606 dahdichanquery = atoi(dahdichannel); 13607 } 13608 13609 astman_send_ack(s, m, "DAHDI channel status will follow"); 13610 if (!ast_strlen_zero(id)) 13611 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 13612 13613 ast_mutex_lock(&iflock); 13614 13615 tmp = iflist; 13616 while (tmp) { 13617 if (tmp->channel > 0) { 13618 int alm = get_alarms(tmp); 13619 13620 /* If a specific channel is queried for, only deliver status for that channel */ 13621 if (dahdichanquery > 0 && tmp->channel != dahdichanquery) 13622 continue; 13623 13624 channels++; 13625 if (tmp->owner) { 13626 /* Add data if we have a current call */ 13627 astman_append(s, 13628 "Event: DAHDIShowChannels\r\n" 13629 "DAHDIChannel: %d\r\n" 13630 "Channel: %s\r\n" 13631 "Uniqueid: %s\r\n" 13632 "AccountCode: %s\r\n" 13633 "Signalling: %s\r\n" 13634 "SignallingCode: %d\r\n" 13635 "Context: %s\r\n" 13636 "DND: %s\r\n" 13637 "Alarm: %s\r\n" 13638 "%s" 13639 "\r\n", 13640 tmp->channel, 13641 tmp->owner->name, 13642 tmp->owner->uniqueid, 13643 tmp->owner->accountcode, 13644 sig2str(tmp->sig), 13645 tmp->sig, 13646 tmp->context, 13647 tmp->dnd ? "Enabled" : "Disabled", 13648 alarm2str(alm), idText); 13649 } else { 13650 astman_append(s, 13651 "Event: DAHDIShowChannels\r\n" 13652 "DAHDIChannel: %d\r\n" 13653 "Signalling: %s\r\n" 13654 "SignallingCode: %d\r\n" 13655 "Context: %s\r\n" 13656 "DND: %s\r\n" 13657 "Alarm: %s\r\n" 13658 "%s" 13659 "\r\n", 13660 tmp->channel, sig2str(tmp->sig), tmp->sig, 13661 tmp->context, 13662 tmp->dnd ? "Enabled" : "Disabled", 13663 alarm2str(alm), idText); 13664 } 13665 } 13666 13667 tmp = tmp->next; 13668 } 13669 13670 ast_mutex_unlock(&iflock); 13671 13672 astman_append(s, 13673 "Event: DAHDIShowChannelsComplete\r\n" 13674 "%s" 13675 "Items: %d\r\n" 13676 "\r\n", 13677 idText, 13678 channels); 13679 return 0; 13680 }
static int action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13527 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().
13528 { 13529 struct dahdi_pvt *p = NULL; 13530 const char *channel = astman_get_header(m, "DAHDIChannel"); 13531 13532 if (ast_strlen_zero(channel)) { 13533 astman_send_error(s, m, "No channel specified"); 13534 return 0; 13535 } 13536 p = find_channel(atoi(channel)); 13537 if (!p) { 13538 astman_send_error(s, m, "No such channel"); 13539 return 0; 13540 } 13541 dahdi_fake_event(p,TRANSFER); 13542 astman_send_ack(s, m, "DAHDITransfer"); 13543 return 0; 13544 }
static int action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13546 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().
13547 { 13548 struct dahdi_pvt *p = NULL; 13549 const char *channel = astman_get_header(m, "DAHDIChannel"); 13550 13551 if (ast_strlen_zero(channel)) { 13552 astman_send_error(s, m, "No channel specified"); 13553 return 0; 13554 } 13555 p = find_channel(atoi(channel)); 13556 if (!p) { 13557 astman_send_error(s, m, "No such channel"); 13558 return 0; 13559 } 13560 dahdi_fake_event(p,HANGUP); 13561 astman_send_ack(s, m, "DAHDIHangup"); 13562 return 0; 13563 }
static char* alarm2str | ( | int | alm | ) | [static] |
Definition at line 1742 of file chan_dahdi.c.
References alarm, alarms, and ARRAY_LEN.
Referenced by action_dahdishowchannels(), and handle_alarms().
01743 { 01744 int x; 01745 for (x = 0; x < ARRAY_LEN(alarms); x++) { 01746 if (alarms[x].alarm & alm) 01747 return alarms[x].name; 01748 } 01749 return alm ? "Unknown Alarm" : "No Alarm"; 01750 }
static int alloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 1538 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().
01539 { 01540 struct dahdi_bufferinfo bi; 01541 int res; 01542 if (p->subs[x].dfd >= 0) { 01543 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel); 01544 return -1; 01545 } 01546 01547 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo"); 01548 if (p->subs[x].dfd <= -1) { 01549 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 01550 return -1; 01551 } 01552 01553 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi); 01554 if (!res) { 01555 bi.txbufpolicy = p->buf_policy; 01556 bi.rxbufpolicy = p->buf_policy; 01557 bi.numbufs = p->buf_no; 01558 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi); 01559 if (res < 0) { 01560 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno)); 01561 } 01562 } else 01563 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno)); 01564 01565 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) { 01566 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno)); 01567 dahdi_close_sub(p, x); 01568 p->subs[x].dfd = -1; 01569 return -1; 01570 } 01571 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan); 01572 return 0; 01573 }
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 10943 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.
10944 { 10945 if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */ 10946 snprintf(buf, size, "%s", number); 10947 return; 10948 } 10949 if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */ 10950 if (size) { 10951 *buf = '\0'; 10952 } 10953 return; 10954 } 10955 switch (plan) { 10956 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */ 10957 snprintf(buf, size, "%s%s", pri->internationalprefix, number); 10958 break; 10959 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */ 10960 snprintf(buf, size, "%s%s", pri->nationalprefix, number); 10961 break; 10962 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */ 10963 snprintf(buf, size, "%s%s", pri->localprefix, number); 10964 break; 10965 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */ 10966 snprintf(buf, size, "%s%s", pri->privateprefix, number); 10967 break; 10968 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */ 10969 snprintf(buf, size, "%s%s", pri->unknownprefix, number); 10970 break; 10971 default: /* other Q.931 dialplan => don't twiddle with callingnum */ 10972 snprintf(buf, size, "%s", number); 10973 break; 10974 } 10975 }
static int attempt_transfer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4517 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().
04518 { 04519 /* In order to transfer, we need at least one of the channels to 04520 actually be in a call bridge. We can't conference two applications 04521 together (but then, why would we want to?) */ 04522 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 04523 /* The three-way person we're about to transfer to could still be in MOH, so 04524 stop if now if appropriate */ 04525 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) 04526 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD); 04527 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) { 04528 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING); 04529 } 04530 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) { 04531 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 04532 } 04533 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { 04534 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 04535 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name); 04536 return -1; 04537 } 04538 /* Orphan the channel after releasing the lock */ 04539 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04540 unalloc_sub(p, SUB_THREEWAY); 04541 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 04542 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 04543 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) { 04544 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING); 04545 } 04546 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) { 04547 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04548 } 04549 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { 04550 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 04551 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); 04552 return -1; 04553 } 04554 /* Three-way is now the REAL */ 04555 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04556 ast_channel_unlock(p->subs[SUB_REAL].owner); 04557 unalloc_sub(p, SUB_THREEWAY); 04558 /* Tell the caller not to hangup */ 04559 return 1; 04560 } else { 04561 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n", 04562 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name); 04563 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04564 return -1; 04565 } 04566 return 0; 04567 }
static int available | ( | struct dahdi_pvt * | p, | |
int | channelmatch, | |||
ast_group_t | groupmatch, | |||
int * | busy, | |||
int * | channelmatched, | |||
int * | groupmatched | |||
) | [inline, static] |
Definition at line 9374 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().
09375 { 09376 int res; 09377 struct dahdi_params par; 09378 09379 /* First, check group matching */ 09380 if (groupmatch) { 09381 if ((p->group & groupmatch) != groupmatch) 09382 return 0; 09383 *groupmatched = 1; 09384 } 09385 /* Check to see if we have a channel match */ 09386 if (channelmatch != -1) { 09387 if (p->channel != channelmatch) 09388 return 0; 09389 *channelmatched = 1; 09390 } 09391 /* We're at least busy at this point */ 09392 if (busy) { 09393 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS)) 09394 *busy = 1; 09395 } 09396 /* If do not disturb, definitely not */ 09397 if (p->dnd) 09398 return 0; 09399 /* If guard time, definitely not */ 09400 if (p->guardtime && (time(NULL) < p->guardtime)) 09401 return 0; 09402 09403 if (p->locallyblocked || p->remotelyblocked) 09404 return 0; 09405 09406 /* If no owner definitely available */ 09407 if (!p->owner) { 09408 #ifdef HAVE_PRI 09409 /* Trust PRI */ 09410 if (p->pri) { 09411 if (p->resetting || p->call) 09412 return 0; 09413 else 09414 return 1; 09415 } 09416 #endif 09417 #ifdef HAVE_SS7 09418 /* Trust SS7 */ 09419 if (p->ss7) { 09420 if (p->ss7call) 09421 return 0; 09422 else 09423 return 1; 09424 } 09425 #endif 09426 if (!(p->radio || (p->oprmode < 0))) 09427 { 09428 if (!p->sig || (p->sig == SIG_FXSLS)) 09429 return 1; 09430 /* Check hook state */ 09431 if (p->subs[SUB_REAL].dfd > -1) { 09432 memset(&par, 0, sizeof(par)); 09433 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 09434 } else { 09435 /* Assume not off hook on CVRS */ 09436 res = 0; 09437 par.rxisoffhook = 0; 09438 } 09439 if (res) { 09440 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno)); 09441 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) { 09442 /* When "onhook" that means no battery on the line, and thus 09443 it is out of service..., if it's on a TDM card... If it's a channel 09444 bank, there is no telling... */ 09445 if (par.rxbits > -1) 09446 return 1; 09447 if (par.rxisoffhook) 09448 return 1; 09449 else 09450 return 0; 09451 } else if (par.rxisoffhook) { 09452 ast_debug(1, "Channel %d off hook, can't use\n", p->channel); 09453 /* Not available when the other end is off hook */ 09454 #ifdef DAHDI_CHECK_HOOKSTATE 09455 return 0; 09456 #else 09457 return 1; 09458 #endif 09459 } 09460 } 09461 return 1; 09462 } 09463 09464 /* If it's not an FXO, forget about call wait */ 09465 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 09466 return 0; 09467 09468 if (!p->callwaiting) { 09469 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */ 09470 return 0; 09471 } 09472 09473 if (p->subs[SUB_CALLWAIT].dfd > -1) { 09474 /* If there is already a call waiting call, then we can't take a second one */ 09475 return 0; 09476 } 09477 09478 if ((p->owner->_state != AST_STATE_UP) && 09479 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) { 09480 /* If the current call is not up, then don't allow the call */ 09481 return 0; 09482 } 09483 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) { 09484 /* Can't take a call wait when the three way calling hasn't been merged yet. */ 09485 return 0; 09486 } 09487 /* We're cool */ 09488 return 1; 09489 }
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 14228 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().
14229 { 14230 char *c, *chan; 14231 int x, start, finish; 14232 struct dahdi_pvt *tmp; 14233 #ifdef HAVE_PRI 14234 struct dahdi_pri *pri; 14235 int trunkgroup, y; 14236 #endif 14237 14238 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) { 14239 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); 14240 return -1; 14241 } 14242 14243 c = ast_strdupa(value); 14244 14245 #ifdef HAVE_PRI 14246 pri = NULL; 14247 if (iscrv) { 14248 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) { 14249 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno); 14250 return -1; 14251 } 14252 if (trunkgroup < 1) { 14253 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno); 14254 return -1; 14255 } 14256 c += y; 14257 for (y = 0; y < NUM_SPANS; y++) { 14258 if (pris[y].trunkgroup == trunkgroup) { 14259 pri = pris + y; 14260 break; 14261 } 14262 } 14263 if (!pri) { 14264 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno); 14265 return -1; 14266 } 14267 } 14268 #endif 14269 14270 while ((chan = strsep(&c, ","))) { 14271 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) { 14272 /* Range */ 14273 } else if (sscanf(chan, "%30d", &start)) { 14274 /* Just one */ 14275 finish = start; 14276 } else if (!strcasecmp(chan, "pseudo")) { 14277 finish = start = CHAN_PSEUDO; 14278 if (found_pseudo) 14279 *found_pseudo = 1; 14280 } else { 14281 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan); 14282 return -1; 14283 } 14284 if (finish < start) { 14285 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); 14286 x = finish; 14287 finish = start; 14288 start = x; 14289 } 14290 14291 for (x = start; x <= finish; x++) { 14292 #ifdef HAVE_PRI 14293 tmp = mkintf(x, conf, pri, reload); 14294 #else 14295 tmp = mkintf(x, conf, NULL, reload); 14296 #endif 14297 14298 if (tmp) { 14299 #ifdef HAVE_PRI 14300 if (pri) 14301 ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig)); 14302 else 14303 #endif 14304 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig)); 14305 } else { 14306 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n", 14307 (reload == 1) ? "reconfigure" : "register", value); 14308 return -1; 14309 } 14310 } 14311 } 14312 14313 return 0; 14314 }
static void build_status | ( | char * | s, | |
size_t | len, | |||
int | status, | |||
int | active | |||
) | [static] |
Definition at line 12394 of file chan_dahdi.c.
References DCHAN_NOTINALARM, and DCHAN_PROVISIONED.
Referenced by handle_pri_show_span(), and handle_pri_show_spans().
12395 { 12396 if (!s || len < 1) { 12397 return; 12398 } 12399 s[0] = '\0'; 12400 if (status & DCHAN_PROVISIONED) 12401 strncat(s, "Provisioned, ", len - strlen(s) - 1); 12402 if (!(status & DCHAN_NOTINALARM)) 12403 strncat(s, "In Alarm, ", len - strlen(s) - 1); 12404 if (status & DCHAN_UP) 12405 strncat(s, "Up", len - strlen(s) - 1); 12406 else 12407 strncat(s, "Down", len - strlen(s) - 1); 12408 if (active) 12409 strncat(s, ", Active", len - strlen(s) - 1); 12410 else 12411 strncat(s, ", Standby", len - strlen(s) - 1); 12412 s[len - 1] = '\0'; 12413 }
static int bump_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2197 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().
02198 { 02199 int res; 02200 02201 /* Bump receive gain by value stored in cid_rxgain */ 02202 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law); 02203 if (res) { 02204 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno)); 02205 return -1; 02206 } 02207 02208 return 0; 02209 }
static int calc_energy | ( | const unsigned char * | buf, | |
int | len, | |||
int | law | |||
) | [static] |
Definition at line 7837 of file chan_dahdi.c.
References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.
Referenced by mwi_thread().
07838 { 07839 int x; 07840 int sum = 0; 07841 07842 if (!len) 07843 return 0; 07844 07845 for (x = 0; x < len; x++) 07846 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x])); 07847 07848 return sum / len; 07849 }
Definition at line 9491 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().
09492 { 09493 struct dahdi_pvt *p; 09494 struct dahdi_bufferinfo bi; 09495 int res; 09496 09497 if ((p = ast_malloc(sizeof(*p)))) { 09498 memcpy(p, src, sizeof(struct dahdi_pvt)); 09499 ast_mutex_init(&p->lock); 09500 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo"); 09501 /* Allocate a dahdi structure */ 09502 if (p->subs[SUB_REAL].dfd < 0) { 09503 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno)); 09504 destroy_dahdi_pvt(&p); 09505 return NULL; 09506 } 09507 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 09508 if (!res) { 09509 bi.txbufpolicy = src->buf_policy; 09510 bi.rxbufpolicy = src->buf_policy; 09511 bi.numbufs = src->buf_no; 09512 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 09513 if (res < 0) { 09514 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno)); 09515 } 09516 } else 09517 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno)); 09518 } 09519 p->destroy = 1; 09520 p->next = iflist; 09521 p->prev = NULL; 09522 iflist = p; 09523 if (iflist->next) 09524 iflist->next->prev = p; 09525 return p; 09526 }
static int check_for_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4569 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().
04570 { 04571 struct dahdi_confinfo ci; 04572 /* Fine if we already have a master, etc */ 04573 if (p->master || (p->confno > -1)) 04574 return 0; 04575 memset(&ci, 0, sizeof(ci)); 04576 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 04577 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno)); 04578 return 0; 04579 } 04580 /* If we have no master and don't have a confno, then 04581 if we're in a conference, it's probably a MeetMe room or 04582 some such, so don't let us 3-way out! */ 04583 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) { 04584 ast_verb(3, "Avoiding 3-way call when in an external conference\n"); 04585 return 1; 04586 } 04587 return 0; 04588 }
static char* complete_span_4 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 12219 of file chan_dahdi.c.
References complete_span_helper().
Referenced by handle_pri_debug(), and handle_pri_show_span().
12220 { 12221 return complete_span_helper(line,word,pos,state,3); 12222 }
static char* complete_span_5 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 12224 of file chan_dahdi.c.
References complete_span_helper().
Referenced by handle_pri_no_debug(), and handle_pri_really_debug().
12225 { 12226 return complete_span_helper(line,word,pos,state,4); 12227 }
static char* complete_span_helper | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state, | |||
int | rpos | |||
) | [static] |
Definition at line 12200 of file chan_dahdi.c.
References asprintf, ast_log(), errno, NUM_SPANS, and pris.
Referenced by complete_span_4(), and complete_span_5().
12201 { 12202 int which, span; 12203 char *ret = NULL; 12204 12205 if (pos != rpos) 12206 return ret; 12207 12208 for (which = span = 0; span < NUM_SPANS; span++) { 12209 if (pris[span].pri && ++which > state) { 12210 if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */ 12211 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 12212 } 12213 break; 12214 } 12215 } 12216 return ret; 12217 }
static int conf_add | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | idx, | |||
int | slavechannel | |||
) | [static] |
Definition at line 1839 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().
01840 { 01841 /* If the conference already exists, and we're already in it 01842 don't bother doing anything */ 01843 struct dahdi_confinfo zi; 01844 01845 memset(&zi, 0, sizeof(zi)); 01846 zi.chan = 0; 01847 01848 if (slavechannel > 0) { 01849 /* If we have only one slave, do a digital mon */ 01850 zi.confmode = DAHDI_CONF_DIGITALMON; 01851 zi.confno = slavechannel; 01852 } else { 01853 if (!idx) { 01854 /* Real-side and pseudo-side both participate in conference */ 01855 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER | 01856 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 01857 } else 01858 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 01859 zi.confno = p->confno; 01860 } 01861 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode)) 01862 return 0; 01863 if (c->dfd < 0) 01864 return 0; 01865 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 01866 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno)); 01867 return -1; 01868 } 01869 if (slavechannel < 1) { 01870 p->confno = zi.confno; 01871 } 01872 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 01873 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 01874 return 0; 01875 }
static int conf_del | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | idx | |||
) | [static] |
Definition at line 1888 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().
01889 { 01890 struct dahdi_confinfo zi; 01891 if (/* Can't delete if there's no dfd */ 01892 (c->dfd < 0) || 01893 /* Don't delete from the conference if it's not our conference */ 01894 !isourconf(p, c) 01895 /* Don't delete if we don't think it's conferenced at all (implied) */ 01896 ) return 0; 01897 memset(&zi, 0, sizeof(zi)); 01898 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 01899 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno)); 01900 return -1; 01901 } 01902 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 01903 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 01904 return 0; 01905 }
static int dahdi_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3756 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.
03757 { 03758 struct dahdi_pvt *p = ast->tech_pvt; 03759 int res = 0; 03760 int idx; 03761 int oldstate = ast->_state; 03762 ast_setstate(ast, AST_STATE_UP); 03763 ast_mutex_lock(&p->lock); 03764 idx = dahdi_get_index(ast, p, 0); 03765 if (idx < 0) 03766 idx = SUB_REAL; 03767 /* nothing to do if a radio channel */ 03768 if ((p->radio || (p->oprmode < 0))) { 03769 ast_mutex_unlock(&p->lock); 03770 return 0; 03771 } 03772 switch (p->sig) { 03773 case SIG_FXSLS: 03774 case SIG_FXSGS: 03775 case SIG_FXSKS: 03776 p->ringt = 0; 03777 /* Fall through */ 03778 case SIG_EM: 03779 case SIG_EM_E1: 03780 case SIG_EMWINK: 03781 case SIG_FEATD: 03782 case SIG_FEATDMF: 03783 case SIG_FEATDMF_TA: 03784 case SIG_E911: 03785 case SIG_FGC_CAMA: 03786 case SIG_FGC_CAMAMF: 03787 case SIG_FEATB: 03788 case SIG_SF: 03789 case SIG_SFWINK: 03790 case SIG_SF_FEATD: 03791 case SIG_SF_FEATDMF: 03792 case SIG_SF_FEATB: 03793 case SIG_FXOLS: 03794 case SIG_FXOGS: 03795 case SIG_FXOKS: 03796 /* Pick up the line */ 03797 ast_debug(1, "Took %s off hook\n", ast->name); 03798 if (p->hanguponpolarityswitch) { 03799 p->polaritydelaytv = ast_tvnow(); 03800 } 03801 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 03802 tone_zone_play_tone(p->subs[idx].dfd, -1); 03803 p->dialing = 0; 03804 if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) { 03805 if (oldstate == AST_STATE_RINGING) { 03806 ast_debug(1, "Finally swapping real and threeway\n"); 03807 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1); 03808 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03809 p->owner = p->subs[SUB_REAL].owner; 03810 } 03811 } 03812 if (p->sig & __DAHDI_SIG_FXS) { 03813 dahdi_enable_ec(p); 03814 dahdi_train_ec(p); 03815 } 03816 break; 03817 #ifdef HAVE_PRI 03818 case SIG_BRI: 03819 case SIG_BRI_PTMP: 03820 case SIG_PRI: 03821 /* Send a pri acknowledge */ 03822 if (!pri_grab(p, p->pri)) { 03823 p->proceeding = 1; 03824 p->dialing = 0; 03825 res = pri_answer(p->pri->pri, p->call, 0, !p->digital); 03826 pri_rel(p->pri); 03827 } else { 03828 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 03829 res = -1; 03830 } 03831 break; 03832 #endif 03833 #ifdef HAVE_SS7 03834 case SIG_SS7: 03835 if (!ss7_grab(p, p->ss7)) { 03836 p->proceeding = 1; 03837 res = isup_anm(p->ss7->ss7, p->ss7call); 03838 ss7_rel(p->ss7); 03839 } else { 03840 ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span); 03841 res = -1; 03842 } 03843 break; 03844 #endif 03845 case 0: 03846 ast_mutex_unlock(&p->lock); 03847 return 0; 03848 default: 03849 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel); 03850 res = -1; 03851 } 03852 ast_mutex_unlock(&p->lock); 03853 return res; 03854 }
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 4168 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_lock(), 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_pri::lock, dahdi_pvt::lock, LOG_NOTICE, master, ast_channel::name, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pri, 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().
04169 { 04170 struct ast_channel *who; 04171 struct dahdi_pvt *p0, *p1, *op0, *op1; 04172 struct dahdi_pvt *master = NULL, *slave = NULL; 04173 struct ast_frame *f; 04174 int inconf = 0; 04175 int nothingok = 1; 04176 int ofd0, ofd1; 04177 int oi0, oi1, i0 = -1, i1 = -1, t0, t1; 04178 int os0 = -1, os1 = -1; 04179 int priority = 0; 04180 struct ast_channel *oc0, *oc1; 04181 enum ast_bridge_result res; 04182 04183 #ifdef PRI_2BCT 04184 int triedtopribridge = 0; 04185 #endif 04186 04187 /* For now, don't attempt to native bridge if either channel needs DTMF detection. 04188 There is code below to handle it properly until DTMF is actually seen, 04189 but due to currently unresolved issues it's ignored... 04190 */ 04191 04192 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 04193 return AST_BRIDGE_FAILED_NOWARN; 04194 04195 ast_channel_lock(c0); 04196 while (ast_channel_trylock(c1)) { 04197 CHANNEL_DEADLOCK_AVOIDANCE(c0); 04198 } 04199 04200 p0 = c0->tech_pvt; 04201 p1 = c1->tech_pvt; 04202 /* cant do pseudo-channels here */ 04203 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) { 04204 ast_channel_unlock(c0); 04205 ast_channel_unlock(c1); 04206 return AST_BRIDGE_FAILED_NOWARN; 04207 } 04208 04209 oi0 = dahdi_get_index(c0, p0, 0); 04210 oi1 = dahdi_get_index(c1, p1, 0); 04211 if ((oi0 < 0) || (oi1 < 0)) { 04212 ast_channel_unlock(c0); 04213 ast_channel_unlock(c1); 04214 return AST_BRIDGE_FAILED; 04215 } 04216 04217 op0 = p0 = c0->tech_pvt; 04218 op1 = p1 = c1->tech_pvt; 04219 ofd0 = c0->fds[0]; 04220 ofd1 = c1->fds[0]; 04221 oc0 = p0->owner; 04222 oc1 = p1->owner; 04223 04224 if (ast_mutex_trylock(&p0->lock)) { 04225 /* Don't block, due to potential for deadlock */ 04226 ast_channel_unlock(c0); 04227 ast_channel_unlock(c1); 04228 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 04229 return AST_BRIDGE_RETRY; 04230 } 04231 if (ast_mutex_trylock(&p1->lock)) { 04232 /* Don't block, due to potential for deadlock */ 04233 ast_mutex_unlock(&p0->lock); 04234 ast_channel_unlock(c0); 04235 ast_channel_unlock(c1); 04236 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 04237 return AST_BRIDGE_RETRY; 04238 } 04239 04240 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 04241 if (p0->owner && p1->owner) { 04242 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */ 04243 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) { 04244 master = p0; 04245 slave = p1; 04246 inconf = 1; 04247 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) { 04248 master = p1; 04249 slave = p0; 04250 inconf = 1; 04251 } else { 04252 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n"); 04253 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n", 04254 p0->channel, 04255 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 04256 p0->subs[SUB_REAL].inthreeway, p0->channel, 04257 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 04258 p1->subs[SUB_REAL].inthreeway); 04259 } 04260 nothingok = 0; 04261 } 04262 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) { 04263 if (p1->subs[SUB_THREEWAY].inthreeway) { 04264 master = p1; 04265 slave = p0; 04266 nothingok = 0; 04267 } 04268 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) { 04269 if (p0->subs[SUB_THREEWAY].inthreeway) { 04270 master = p0; 04271 slave = p1; 04272 nothingok = 0; 04273 } 04274 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) { 04275 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise, 04276 don't put us in anything */ 04277 if (p1->subs[SUB_CALLWAIT].inthreeway) { 04278 master = p1; 04279 slave = p0; 04280 nothingok = 0; 04281 } 04282 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) { 04283 /* Same as previous */ 04284 if (p0->subs[SUB_CALLWAIT].inthreeway) { 04285 master = p0; 04286 slave = p1; 04287 nothingok = 0; 04288 } 04289 } 04290 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n", 04291 master ? master->channel : 0, slave ? slave->channel : 0, nothingok); 04292 if (master && slave) { 04293 /* Stop any tones, or play ringtone as appropriate. If they're bridged 04294 in an active threeway call with a channel that is ringing, we should 04295 indicate ringing. */ 04296 if ((oi1 == SUB_THREEWAY) && 04297 p1->subs[SUB_THREEWAY].inthreeway && 04298 p1->subs[SUB_REAL].owner && 04299 p1->subs[SUB_REAL].inthreeway && 04300 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 04301 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name); 04302 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE); 04303 os1 = p1->subs[SUB_REAL].owner->_state; 04304 } else { 04305 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1); 04306 tone_zone_play_tone(p0->subs[oi0].dfd, -1); 04307 } 04308 if ((oi0 == SUB_THREEWAY) && 04309 p0->subs[SUB_THREEWAY].inthreeway && 04310 p0->subs[SUB_REAL].owner && 04311 p0->subs[SUB_REAL].inthreeway && 04312 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 04313 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name); 04314 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE); 04315 os0 = p0->subs[SUB_REAL].owner->_state; 04316 } else { 04317 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0); 04318 tone_zone_play_tone(p1->subs[oi0].dfd, -1); 04319 } 04320 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 04321 if (!p0->echocanbridged || !p1->echocanbridged) { 04322 /* Disable echo cancellation if appropriate */ 04323 dahdi_disable_ec(p0); 04324 dahdi_disable_ec(p1); 04325 } 04326 } 04327 dahdi_link(slave, master); 04328 master->inconference = inconf; 04329 } else if (!nothingok) 04330 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]); 04331 04332 update_conf(p0); 04333 update_conf(p1); 04334 t0 = p0->subs[SUB_REAL].inthreeway; 04335 t1 = p1->subs[SUB_REAL].inthreeway; 04336 04337 ast_mutex_unlock(&p0->lock); 04338 ast_mutex_unlock(&p1->lock); 04339 04340 ast_channel_unlock(c0); 04341 ast_channel_unlock(c1); 04342 04343 /* Native bridge failed */ 04344 if ((!master || !slave) && !nothingok) { 04345 dahdi_enable_ec(p0); 04346 dahdi_enable_ec(p1); 04347 return AST_BRIDGE_FAILED; 04348 } 04349 04350 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name); 04351 04352 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 04353 disable_dtmf_detect(op0); 04354 04355 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 04356 disable_dtmf_detect(op1); 04357 04358 for (;;) { 04359 struct ast_channel *c0_priority[2] = {c0, c1}; 04360 struct ast_channel *c1_priority[2] = {c1, c0}; 04361 04362 /* Here's our main loop... Start by locking things, looking for private parts, 04363 and then balking if anything is wrong */ 04364 04365 ast_channel_lock(c0); 04366 while (ast_channel_trylock(c1)) { 04367 CHANNEL_DEADLOCK_AVOIDANCE(c0); 04368 } 04369 04370 p0 = c0->tech_pvt; 04371 p1 = c1->tech_pvt; 04372 04373 if (op0 == p0) 04374 i0 = dahdi_get_index(c0, p0, 1); 04375 if (op1 == p1) 04376 i1 = dahdi_get_index(c1, p1, 1); 04377 04378 ast_channel_unlock(c0); 04379 ast_channel_unlock(c1); 04380 04381 if (!timeoutms || 04382 (op0 != p0) || 04383 (op1 != p1) || 04384 (ofd0 != c0->fds[0]) || 04385 (ofd1 != c1->fds[0]) || 04386 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 04387 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 04388 (oc0 != p0->owner) || 04389 (oc1 != p1->owner) || 04390 (t0 != p0->subs[SUB_REAL].inthreeway) || 04391 (t1 != p1->subs[SUB_REAL].inthreeway) || 04392 (oi0 != i0) || 04393 (oi1 != i1)) { 04394 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n", 04395 op0->channel, oi0, op1->channel, oi1); 04396 res = AST_BRIDGE_RETRY; 04397 goto return_from_bridge; 04398 } 04399 04400 #ifdef PRI_2BCT 04401 if (!triedtopribridge) { 04402 triedtopribridge = 1; 04403 if (p0->pri && p0->pri == p1->pri && p0->transfer && p1->transfer) { 04404 ast_mutex_lock(&p0->pri->lock); 04405 if (p0->call && p1->call) { 04406 pri_channel_bridge(p0->call, p1->call); 04407 } 04408 ast_mutex_unlock(&p0->pri->lock); 04409 } 04410 } 04411 #endif 04412 04413 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms); 04414 if (!who) { 04415 ast_debug(1, "Ooh, empty read...\n"); 04416 continue; 04417 } 04418 f = ast_read(who); 04419 if (!f || (f->frametype == AST_FRAME_CONTROL)) { 04420 *fo = f; 04421 *rc = who; 04422 res = AST_BRIDGE_COMPLETE; 04423 goto return_from_bridge; 04424 } 04425 if (f->frametype == AST_FRAME_DTMF) { 04426 if ((who == c0) && p0->pulsedial) { 04427 ast_write(c1, f); 04428 } else if ((who == c1) && p1->pulsedial) { 04429 ast_write(c0, f); 04430 } else { 04431 *fo = f; 04432 *rc = who; 04433 res = AST_BRIDGE_COMPLETE; 04434 goto return_from_bridge; 04435 } 04436 } 04437 ast_frfree(f); 04438 04439 /* Swap who gets priority */ 04440 priority = !priority; 04441 } 04442 04443 return_from_bridge: 04444 if (op0 == p0) 04445 dahdi_enable_ec(p0); 04446 04447 if (op1 == p1) 04448 dahdi_enable_ec(p1); 04449 04450 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 04451 enable_dtmf_detect(op0); 04452 04453 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 04454 enable_dtmf_detect(op1); 04455 04456 dahdi_unlink(slave, master, 1); 04457 04458 return res; 04459 }
static int dahdi_call | ( | struct ast_channel * | ast, | |
char * | rdest, | |||
int | timeout | |||
) | [static] |
Definition at line 2460 of file chan_dahdi.c.
References ast_channel::_state, dahdi_pvt::answeronpolarityswitch, 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_tvnow(), ast_verb, dahdi_pvt::bearer, cadences, 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, cidrings, 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::hanguponpolarityswitch, 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, num_cadence, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pvt::owner, pbx_builtin_getvar_helper(), dahdi_pvt::polaritydelaytv, 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.
02461 { 02462 struct dahdi_pvt *p = ast->tech_pvt; 02463 int x, res, idx,mysig; 02464 char *c, *n, *l; 02465 #ifdef HAVE_PRI 02466 char *s = NULL; 02467 #endif 02468 char dest[256]; /* must be same length as p->dialdest */ 02469 ast_mutex_lock(&p->lock); 02470 ast_copy_string(dest, rdest, sizeof(dest)); 02471 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest)); 02472 if ((ast->_state == AST_STATE_BUSY)) { 02473 p->subs[SUB_REAL].needbusy = 1; 02474 ast_mutex_unlock(&p->lock); 02475 return 0; 02476 } 02477 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 02478 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name); 02479 ast_mutex_unlock(&p->lock); 02480 return -1; 02481 } 02482 p->dialednone = 0; 02483 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ 02484 { 02485 /* Special pseudo -- automatically up */ 02486 ast_setstate(ast, AST_STATE_UP); 02487 ast_mutex_unlock(&p->lock); 02488 return 0; 02489 } 02490 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE; 02491 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 02492 if (res) 02493 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno)); 02494 p->outgoing = 1; 02495 02496 if (IS_DIGITAL(ast->transfercapability)){ 02497 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law); 02498 } else { 02499 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02500 } 02501 02502 mysig = p->sig; 02503 if (p->outsigmod > -1) 02504 mysig = p->outsigmod; 02505 02506 switch (mysig) { 02507 case SIG_FXOLS: 02508 case SIG_FXOGS: 02509 case SIG_FXOKS: 02510 if (p->owner == ast) { 02511 /* Normal ring, on hook */ 02512 02513 /* Don't send audio while on hook, until the call is answered */ 02514 p->dialing = 1; 02515 if (p->use_callerid) { 02516 /* Generate the Caller-ID spill if desired */ 02517 if (p->cidspill) { 02518 ast_log(LOG_WARNING, "cidspill already exists??\n"); 02519 ast_free(p->cidspill); 02520 } 02521 p->callwaitcas = 0; 02522 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) { 02523 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p)); 02524 p->cidpos = 0; 02525 send_callerid(p); 02526 } 02527 } 02528 /* Choose proper cadence */ 02529 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { 02530 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) 02531 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); 02532 p->cidrings = cidrings[p->distinctivering - 1]; 02533 } else { 02534 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) 02535 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); 02536 p->cidrings = p->sendcalleridafter; 02537 } 02538 02539 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */ 02540 c = strchr(dest, '/'); 02541 if (c) 02542 c++; 02543 if (c && (strlen(c) < p->stripmsd)) { 02544 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02545 c = NULL; 02546 } 02547 if (c) { 02548 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02549 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c); 02550 ast_debug(1, "FXO: setup deferred dialstring: %s\n", c); 02551 } else { 02552 p->dop.dialstr[0] = '\0'; 02553 } 02554 x = DAHDI_RING; 02555 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) { 02556 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno)); 02557 ast_mutex_unlock(&p->lock); 02558 return -1; 02559 } 02560 p->dialing = 1; 02561 } else { 02562 /* Call waiting call */ 02563 p->callwaitrings = 0; 02564 if (ast->cid.cid_num) 02565 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num)); 02566 else 02567 p->callwait_num[0] = '\0'; 02568 if (ast->cid.cid_name) 02569 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name)); 02570 else 02571 p->callwait_name[0] = '\0'; 02572 /* Call waiting tone instead */ 02573 if (dahdi_callwait(ast)) { 02574 ast_mutex_unlock(&p->lock); 02575 return -1; 02576 } 02577 /* Make ring-back */ 02578 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE)) 02579 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name); 02580 02581 } 02582 n = ast->cid.cid_name; 02583 l = ast->cid.cid_num; 02584 if (l) 02585 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num)); 02586 else 02587 p->lastcid_num[0] = '\0'; 02588 if (n) 02589 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name)); 02590 else 02591 p->lastcid_name[0] = '\0'; 02592 ast_setstate(ast, AST_STATE_RINGING); 02593 idx = dahdi_get_index(ast, p, 0); 02594 if (idx > -1) { 02595 p->subs[idx].needringing = 1; 02596 } 02597 break; 02598 case SIG_FXSLS: 02599 case SIG_FXSGS: 02600 case SIG_FXSKS: 02601 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) { 02602 ast_debug(1, "Ignore possible polarity reversal on line seizure\n"); 02603 p->polaritydelaytv = ast_tvnow(); 02604 } 02605 /* fall through */ 02606 case SIG_EMWINK: 02607 case SIG_EM: 02608 case SIG_EM_E1: 02609 case SIG_FEATD: 02610 case SIG_FEATDMF: 02611 case SIG_E911: 02612 case SIG_FGC_CAMA: 02613 case SIG_FGC_CAMAMF: 02614 case SIG_FEATB: 02615 case SIG_SFWINK: 02616 case SIG_SF: 02617 case SIG_SF_FEATD: 02618 case SIG_SF_FEATDMF: 02619 case SIG_FEATDMF_TA: 02620 case SIG_SF_FEATB: 02621 c = strchr(dest, '/'); 02622 if (c) 02623 c++; 02624 else 02625 c = ""; 02626 if (strlen(c) < p->stripmsd) { 02627 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02628 ast_mutex_unlock(&p->lock); 02629 return -1; 02630 } 02631 #ifdef HAVE_PRI 02632 /* Start the trunk, if not GR-303 */ 02633 if (!p->pri) { 02634 #endif 02635 x = DAHDI_START; 02636 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02637 if (res < 0) { 02638 if (errno != EINPROGRESS) { 02639 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 02640 ast_mutex_unlock(&p->lock); 02641 return -1; 02642 } 02643 } 02644 #ifdef HAVE_PRI 02645 } 02646 #endif 02647 ast_debug(1, "Dialing '%s'\n", c); 02648 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02649 02650 c += p->stripmsd; 02651 02652 switch (mysig) { 02653 case SIG_FEATD: 02654 l = ast->cid.cid_num; 02655 if (l) 02656 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c); 02657 else 02658 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c); 02659 break; 02660 case SIG_FEATDMF: 02661 l = ast->cid.cid_num; 02662 if (l) 02663 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c); 02664 else 02665 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c); 02666 break; 02667 case SIG_FEATDMF_TA: 02668 { 02669 const char *cic, *ozz; 02670 02671 /* If you have to go through a Tandem Access point you need to use this */ 02672 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ"); 02673 if (!ozz) 02674 ozz = defaultozz; 02675 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC"); 02676 if (!cic) 02677 cic = defaultcic; 02678 if (!ozz || !cic) { 02679 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n"); 02680 ast_mutex_unlock(&p->lock); 02681 return -1; 02682 } 02683 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic); 02684 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c); 02685 p->whichwink = 0; 02686 } 02687 break; 02688 case SIG_E911: 02689 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr)); 02690 break; 02691 case SIG_FGC_CAMA: 02692 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c); 02693 break; 02694 case SIG_FGC_CAMAMF: 02695 case SIG_FEATB: 02696 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c); 02697 break; 02698 default: 02699 if (p->pulse) 02700 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c); 02701 else 02702 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c); 02703 break; 02704 } 02705 02706 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) { 02707 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 02708 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 02709 p->echorest[sizeof(p->echorest) - 1] = '\0'; 02710 p->echobreak = 1; 02711 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 02712 } else 02713 p->echobreak = 0; 02714 if (!res) { 02715 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 02716 int saveerr = errno; 02717 02718 x = DAHDI_ONHOOK; 02719 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02720 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 02721 ast_mutex_unlock(&p->lock); 02722 return -1; 02723 } 02724 } else 02725 ast_debug(1, "Deferring dialing...\n"); 02726 02727 p->dialing = 1; 02728 if (ast_strlen_zero(c)) 02729 p->dialednone = 1; 02730 ast_setstate(ast, AST_STATE_DIALING); 02731 break; 02732 case 0: 02733 /* Special pseudo -- automatically up*/ 02734 ast_setstate(ast, AST_STATE_UP); 02735 break; 02736 case SIG_PRI: 02737 case SIG_BRI: 02738 case SIG_BRI_PTMP: 02739 case SIG_SS7: 02740 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */ 02741 p->dialdest[0] = '\0'; 02742 p->dialing = 1; 02743 break; 02744 default: 02745 ast_debug(1, "not yet implemented\n"); 02746 ast_mutex_unlock(&p->lock); 02747 return -1; 02748 } 02749 #ifdef HAVE_SS7 02750 if (p->ss7) { 02751 char ss7_called_nai; 02752 int called_nai_strip; 02753 char ss7_calling_nai; 02754 int calling_nai_strip; 02755 const char *charge_str = NULL; 02756 const char *gen_address = NULL; 02757 const char *gen_digits = NULL; 02758 const char *gen_dig_type = NULL; 02759 const char *gen_dig_scheme = NULL; 02760 const char *gen_name = NULL; 02761 const char *jip_digits = NULL; 02762 const char *lspi_ident = NULL; 02763 const char *rlt_flag = NULL; 02764 const char *call_ref_id = NULL; 02765 const char *call_ref_pc = NULL; 02766 const char *send_far = NULL; 02767 02768 c = strchr(dest, '/'); 02769 if (c) { 02770 c++; 02771 } else { 02772 c = ""; 02773 } 02774 if (strlen(c) < p->stripmsd) { 02775 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02776 ast_mutex_unlock(&p->lock); 02777 return -1; 02778 } 02779 02780 if (!p->hidecallerid) { 02781 l = ast->cid.cid_num; 02782 } else { 02783 l = NULL; 02784 } 02785 02786 if (ss7_grab(p, p->ss7)) { 02787 ast_log(LOG_WARNING, "Failed to grab SS7!\n"); 02788 ast_mutex_unlock(&p->lock); 02789 return -1; 02790 } 02791 p->digital = IS_DIGITAL(ast->transfercapability); 02792 p->ss7call = isup_new_call(p->ss7->ss7); 02793 02794 if (!p->ss7call) { 02795 ss7_rel(p->ss7); 02796 ast_mutex_unlock(&p->lock); 02797 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n"); 02798 return -1; 02799 } 02800 02801 called_nai_strip = 0; 02802 ss7_called_nai = p->ss7->called_nai; 02803 if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */ 02804 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) { 02805 called_nai_strip = strlen(p->ss7->internationalprefix); 02806 ss7_called_nai = SS7_NAI_INTERNATIONAL; 02807 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) { 02808 called_nai_strip = strlen(p->ss7->nationalprefix); 02809 ss7_called_nai = SS7_NAI_NATIONAL; 02810 } else { 02811 ss7_called_nai = SS7_NAI_SUBSCRIBER; 02812 } 02813 } 02814 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7); 02815 02816 calling_nai_strip = 0; 02817 ss7_calling_nai = p->ss7->calling_nai; 02818 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */ 02819 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) { 02820 calling_nai_strip = strlen(p->ss7->internationalprefix); 02821 ss7_calling_nai = SS7_NAI_INTERNATIONAL; 02822 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) { 02823 calling_nai_strip = strlen(p->ss7->nationalprefix); 02824 ss7_calling_nai = SS7_NAI_NATIONAL; 02825 } else { 02826 ss7_calling_nai = SS7_NAI_SUBSCRIBER; 02827 } 02828 } 02829 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai, 02830 p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED), 02831 p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED ); 02832 02833 isup_set_oli(p->ss7call, ast->cid.cid_ani2); 02834 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc); 02835 02836 ast_channel_lock(ast); 02837 /* Set the charge number if it is set */ 02838 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER"); 02839 if (charge_str) 02840 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10); 02841 02842 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS"); 02843 if (gen_address) 02844 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 */ 02845 02846 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS"); 02847 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE"); 02848 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME"); 02849 if (gen_digits) 02850 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme)); 02851 02852 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME"); 02853 if (gen_name) 02854 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED); 02855 02856 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP"); 02857 if (jip_digits) 02858 isup_set_jip_digits(p->ss7call, jip_digits); 02859 02860 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT"); 02861 if (lspi_ident) 02862 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00); 02863 02864 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON"); 02865 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) { 02866 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */ 02867 } 02868 02869 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT"); 02870 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC"); 02871 if (call_ref_id && call_ref_pc) { 02872 isup_set_callref(p->ss7call, atoi(call_ref_id), 02873 call_ref_pc ? atoi(call_ref_pc) : 0); 02874 } 02875 02876 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR"); 02877 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 )) 02878 (isup_far(p->ss7->ss7, p->ss7call)); 02879 02880 ast_channel_unlock(ast); 02881 02882 isup_iam(p->ss7->ss7, p->ss7call); 02883 ast_setstate(ast, AST_STATE_DIALING); 02884 ss7_rel(p->ss7); 02885 } 02886 #endif /* HAVE_SS7 */ 02887 #ifdef HAVE_PRI 02888 if (p->pri) { 02889 struct pri_sr *sr; 02890 #ifdef SUPPORT_USERUSER 02891 const char *useruser; 02892 #endif 02893 int pridialplan; 02894 int dp_strip; 02895 int prilocaldialplan; 02896 int ldp_strip; 02897 int exclusive; 02898 const char *rr_str; 02899 int redirect_reason; 02900 02901 c = strchr(dest, '/'); 02902 if (c) { 02903 c++; 02904 } else { 02905 c = ""; 02906 } 02907 02908 l = NULL; 02909 n = NULL; 02910 if (!p->hidecallerid) { 02911 l = ast->cid.cid_num; 02912 if (!p->hidecalleridname) { 02913 n = ast->cid.cid_name; 02914 } 02915 } 02916 02917 if (strlen(c) < p->stripmsd) { 02918 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02919 ast_mutex_unlock(&p->lock); 02920 return -1; 02921 } 02922 if (mysig != SIG_FXSKS) { 02923 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02924 s = strchr(c + p->stripmsd, 'w'); 02925 if (s) { 02926 if (strlen(s) > 1) 02927 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s); 02928 else 02929 p->dop.dialstr[0] = '\0'; 02930 *s = '\0'; 02931 } else { 02932 p->dop.dialstr[0] = '\0'; 02933 } 02934 } 02935 if (pri_grab(p, p->pri)) { 02936 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 02937 ast_mutex_unlock(&p->lock); 02938 return -1; 02939 } 02940 if (!(p->call = pri_new_call(p->pri->pri))) { 02941 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel); 02942 pri_rel(p->pri); 02943 ast_mutex_unlock(&p->lock); 02944 return -1; 02945 } 02946 if (!(sr = pri_sr_new())) { 02947 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel); 02948 pri_rel(p->pri); 02949 ast_mutex_unlock(&p->lock); 02950 } 02951 if (p->bearer || (mysig == SIG_FXSKS)) { 02952 if (p->bearer) { 02953 ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel); 02954 p->bearer->call = p->call; 02955 } else 02956 ast_debug(1, "I'm being setup with no bearer right now...\n"); 02957 02958 pri_set_crv(p->pri->pri, p->call, p->channel, 0); 02959 } 02960 p->digital = IS_DIGITAL(ast->transfercapability); 02961 02962 /* Should the picked channel be used exclusively? */ 02963 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) { 02964 exclusive = 1; 02965 } else { 02966 exclusive = 0; 02967 } 02968 02969 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1); 02970 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 02971 (p->digital ? -1 : 02972 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW))); 02973 if (p->pri->facilityenable) 02974 pri_facility_enable(p->pri->pri); 02975 02976 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability)); 02977 dp_strip = 0; 02978 pridialplan = p->pri->dialplan - 1; 02979 if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */ 02980 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 02981 if (pridialplan == -2) { 02982 dp_strip = strlen(p->pri->internationalprefix); 02983 } 02984 pridialplan = PRI_INTERNATIONAL_ISDN; 02985 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 02986 if (pridialplan == -2) { 02987 dp_strip = strlen(p->pri->nationalprefix); 02988 } 02989 pridialplan = PRI_NATIONAL_ISDN; 02990 } else { 02991 pridialplan = PRI_LOCAL_ISDN; 02992 } 02993 } 02994 while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') { 02995 switch (c[p->stripmsd]) { 02996 case 'U': 02997 pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf); 02998 break; 02999 case 'I': 03000 pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf); 03001 break; 03002 case 'N': 03003 pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf); 03004 break; 03005 case 'L': 03006 pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf); 03007 break; 03008 case 'S': 03009 pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf); 03010 break; 03011 case 'V': 03012 pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf); 03013 break; 03014 case 'R': 03015 pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf); 03016 break; 03017 case 'u': 03018 pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0); 03019 break; 03020 case 'e': 03021 pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0); 03022 break; 03023 case 'x': 03024 pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0); 03025 break; 03026 case 'f': 03027 pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0); 03028 break; 03029 case 'n': 03030 pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0); 03031 break; 03032 case 'p': 03033 pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0); 03034 break; 03035 case 'r': 03036 pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0); 03037 break; 03038 default: 03039 if (isalpha(c[p->stripmsd])) { 03040 ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n", 03041 c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]); 03042 } 03043 break; 03044 } 03045 c++; 03046 } 03047 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0); 03048 03049 ldp_strip = 0; 03050 prilocaldialplan = p->pri->localdialplan - 1; 03051 if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */ 03052 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 03053 if (prilocaldialplan == -2) { 03054 ldp_strip = strlen(p->pri->internationalprefix); 03055 } 03056 prilocaldialplan = PRI_INTERNATIONAL_ISDN; 03057 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 03058 if (prilocaldialplan == -2) { 03059 ldp_strip = strlen(p->pri->nationalprefix); 03060 } 03061 prilocaldialplan = PRI_NATIONAL_ISDN; 03062 } else { 03063 prilocaldialplan = PRI_LOCAL_ISDN; 03064 } 03065 } 03066 if (l != NULL) { 03067 while (*l > '9' && *l != '*' && *l != '#') { 03068 switch (*l) { 03069 case 'U': 03070 prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf); 03071 break; 03072 case 'I': 03073 prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf); 03074 break; 03075 case 'N': 03076 prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf); 03077 break; 03078 case 'L': 03079 prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf); 03080 break; 03081 case 'S': 03082 prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf); 03083 break; 03084 case 'V': 03085 prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf); 03086 break; 03087 case 'R': 03088 prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf); 03089 break; 03090 case 'u': 03091 prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0); 03092 break; 03093 case 'e': 03094 prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0); 03095 break; 03096 case 'x': 03097 prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0); 03098 break; 03099 case 'f': 03100 prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0); 03101 break; 03102 case 'n': 03103 prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0); 03104 break; 03105 case 'p': 03106 prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0); 03107 break; 03108 case 'r': 03109 prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0); 03110 break; 03111 default: 03112 if (isalpha(*l)) { 03113 ast_log(LOG_WARNING, 03114 "Unrecognized prilocaldialplan %s modifier: %c\n", 03115 *l > 'Z' ? "NPI" : "TON", *l); 03116 } 03117 break; 03118 } 03119 l++; 03120 } 03121 } 03122 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan, 03123 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE)); 03124 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) { 03125 if (!strcasecmp(rr_str, "UNKNOWN")) 03126 redirect_reason = 0; 03127 else if (!strcasecmp(rr_str, "BUSY")) 03128 redirect_reason = 1; 03129 else if (!strcasecmp(rr_str, "NO_REPLY") || !strcasecmp(rr_str, "NOANSWER")) 03130 /* the NOANSWER is to match diversion-reason from chan_sip, (which never reads PRIREDIRECTREASON) */ 03131 redirect_reason = 2; 03132 else if (!strcasecmp(rr_str, "UNCONDITIONAL")) 03133 redirect_reason = 15; 03134 else 03135 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03136 } else 03137 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03138 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason); 03139 03140 #ifdef SUPPORT_USERUSER 03141 /* User-user info */ 03142 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO"); 03143 03144 if (useruser) 03145 pri_sr_set_useruser(sr, useruser); 03146 #endif 03147 03148 if (pri_setup(p->pri->pri, p->call, sr)) { 03149 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 03150 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan)); 03151 pri_rel(p->pri); 03152 ast_mutex_unlock(&p->lock); 03153 pri_sr_free(sr); 03154 return -1; 03155 } 03156 pri_sr_free(sr); 03157 ast_setstate(ast, AST_STATE_DIALING); 03158 pri_rel(p->pri); 03159 } 03160 #endif 03161 ast_mutex_unlock(&p->lock); 03162 return 0; 03163 }
static int dahdi_callwait | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 2420 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().
02421 { 02422 struct dahdi_pvt *p = ast->tech_pvt; 02423 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 02424 if (p->cidspill) { 02425 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 02426 ast_free(p->cidspill); 02427 } 02428 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 02429 return -1; 02430 save_conference(p); 02431 /* Silence */ 02432 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 02433 if (!p->callwaitrings && p->callwaitingcallerid) { 02434 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 02435 p->callwaitcas = 1; 02436 p->cidlen = 2400 + 680 + READ_SIZE * 4; 02437 } else { 02438 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 02439 p->callwaitcas = 0; 02440 p->cidlen = 2400 + READ_SIZE * 4; 02441 } 02442 p->cidpos = 0; 02443 send_callerid(p); 02444 02445 return 0; 02446 }
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 1109 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().
01109 { 01110 /* recall that if a field is not included here it is initialized 01111 * to 0 or equivalent 01112 */ 01113 struct dahdi_chan_conf conf = { 01114 #ifdef HAVE_PRI 01115 .pri = { 01116 .nsf = PRI_NSF_NONE, 01117 .switchtype = PRI_SWITCH_NI2, 01118 .dialplan = PRI_UNKNOWN + 1, 01119 .localdialplan = PRI_NATIONAL_ISDN + 1, 01120 .nodetype = PRI_CPE, 01121 01122 .minunused = 2, 01123 .idleext = "", 01124 .idledial = "", 01125 .internationalprefix = "", 01126 .nationalprefix = "", 01127 .localprefix = "", 01128 .privateprefix = "", 01129 .unknownprefix = "", 01130 .resetinterval = -1, 01131 }, 01132 #endif 01133 #ifdef HAVE_SS7 01134 .ss7 = { 01135 .called_nai = SS7_NAI_NATIONAL, 01136 .calling_nai = SS7_NAI_NATIONAL, 01137 .internationalprefix = "", 01138 .nationalprefix = "", 01139 .subscriberprefix = "", 01140 .unknownprefix = "" 01141 }, 01142 #endif 01143 .chan = { 01144 .context = "default", 01145 .cid_num = "", 01146 .cid_name = "", 01147 .mohinterpret = "default", 01148 .mohsuggest = "", 01149 .parkinglot = "", 01150 .transfertobusy = 1, 01151 01152 .cid_signalling = CID_SIG_BELL, 01153 .cid_start = CID_START_RING, 01154 .dahditrcallerid = 0, 01155 .use_callerid = 1, 01156 .sig = -1, 01157 .outsigmod = -1, 01158 01159 .cid_rxgain = +5.0, 01160 01161 .tonezone = -1, 01162 01163 .echocancel.head.tap_length = 1, 01164 01165 .busycount = 3, 01166 .busycompare = 0, 01167 .busytonelength = 0, 01168 .busyquietlength = 0, 01169 .busyfuzziness = 0, 01170 .silencethreshold = 0, 01171 01172 .accountcode = "", 01173 01174 .mailbox = "", 01175 01176 01177 .polarityonanswerdelay = 600, 01178 01179 .sendcalleridafter = DEFAULT_CIDRINGS, 01180 01181 .buf_policy = DAHDI_POLICY_IMMEDIATE, 01182 .buf_no = numbufs 01183 }, 01184 .timing = { 01185 .prewinktime = -1, 01186 .preflashtime = -1, 01187 .winktime = -1, 01188 .flashtime = -1, 01189 .starttime = -1, 01190 .rxwinktime = -1, 01191 .rxflashtime = -1, 01192 .debouncetime = -1 01193 }, 01194 .is_sig_auto = 1, 01195 .smdi_port = "/dev/ttyS0", 01196 }; 01197 01198 return conf; 01199 }
static void dahdi_close | ( | int | fd | ) | [static] |
Definition at line 1500 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 1513 of file chan_dahdi.c.
References dahdi_close(), and dahdi_pri::fds.
Referenced by __unload_module(), dahdi_restart(), and start_pri().
01514 { 01515 dahdi_close(pri->fds[fd_num]); 01516 pri->fds[fd_num] = -1; 01517 }
static void dahdi_close_sub | ( | struct dahdi_pvt * | chan_pvt, | |
int | sub_num | |||
) | [static] |
Definition at line 1506 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().
01507 { 01508 dahdi_close(chan_pvt->subs[sub_num].dfd); 01509 chan_pvt->subs[sub_num].dfd = -1; 01510 }
static int dahdi_confmute | ( | struct dahdi_pvt * | p, | |
int | muted | |||
) | [inline, static] |
Definition at line 2241 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().
02242 { 02243 int x, y, res; 02244 x = muted; 02245 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 02246 y = 1; 02247 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y); 02248 if (res) 02249 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno)); 02250 } 02251 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x); 02252 if (res < 0) 02253 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno)); 02254 return res; 02255 }
static char* dahdi_destroy_channel | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12571 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.
12572 { 12573 int channel; 12574 int ret; 12575 switch (cmd) { 12576 case CLI_INIT: 12577 e->command = "dahdi destroy channel"; 12578 e->usage = 12579 "Usage: dahdi destroy channel <chan num>\n" 12580 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n"; 12581 return NULL; 12582 case CLI_GENERATE: 12583 return NULL; 12584 } 12585 if (a->argc != 4) 12586 return CLI_SHOWUSAGE; 12587 12588 channel = atoi(a->argv[3]); 12589 ret = dahdi_destroy_channel_bynum(channel); 12590 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE; 12591 }
static int dahdi_destroy_channel_bynum | ( | int | channel | ) | [static] |
Definition at line 8151 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().
08152 { 08153 struct dahdi_pvt *tmp = NULL; 08154 struct dahdi_pvt *prev = NULL; 08155 08156 tmp = iflist; 08157 while (tmp) { 08158 if (tmp->channel == channel) { 08159 int x = DAHDI_FLASH; 08160 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 */ 08161 destroy_channel(prev, tmp, 1); 08162 ast_module_unref(ast_module_info->self); 08163 return RESULT_SUCCESS; 08164 } 08165 prev = tmp; 08166 tmp = tmp->next; 08167 } 08168 return RESULT_FAILURE; 08169 }
static int dahdi_digit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 1608 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.
01609 { 01610 struct dahdi_pvt *pvt; 01611 int idx; 01612 int dtmf = -1; 01613 01614 pvt = chan->tech_pvt; 01615 01616 ast_mutex_lock(&pvt->lock); 01617 01618 idx = dahdi_get_index(chan, pvt, 0); 01619 01620 if ((idx != SUB_REAL) || !pvt->owner) 01621 goto out; 01622 01623 #ifdef HAVE_PRI 01624 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP)) 01625 && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) { 01626 if (pvt->setup_ack) { 01627 if (!pri_grab(pvt, pvt->pri)) { 01628 pri_information(pvt->pri->pri, pvt->call, digit); 01629 pri_rel(pvt->pri); 01630 } else 01631 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span); 01632 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) { 01633 int res; 01634 ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit); 01635 res = strlen(pvt->dialdest); 01636 pvt->dialdest[res++] = digit; 01637 pvt->dialdest[res] = '\0'; 01638 } 01639 goto out; 01640 } 01641 #endif 01642 if ((dtmf = digit_to_dtmfindex(digit)) == -1) 01643 goto out; 01644 01645 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) { 01646 int res; 01647 struct dahdi_dialoperation zo = { 01648 .op = DAHDI_DIAL_OP_APPEND, 01649 }; 01650 01651 zo.dialstr[0] = 'T'; 01652 zo.dialstr[1] = digit; 01653 zo.dialstr[2] = '\0'; 01654 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo))) 01655 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno)); 01656 else 01657 pvt->dialing = 1; 01658 } else { 01659 ast_debug(1, "Started VLDTMF digit '%c'\n", digit); 01660 pvt->dialing = 1; 01661 pvt->begindigit = digit; 01662 } 01663 01664 out: 01665 ast_mutex_unlock(&pvt->lock); 01666 01667 return 0; 01668 }
static int dahdi_digit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 1670 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.
01671 { 01672 struct dahdi_pvt *pvt; 01673 int res = 0; 01674 int idx; 01675 int x; 01676 01677 pvt = chan->tech_pvt; 01678 01679 ast_mutex_lock(&pvt->lock); 01680 01681 idx = dahdi_get_index(chan, pvt, 0); 01682 01683 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse) 01684 goto out; 01685 01686 #ifdef HAVE_PRI 01687 /* This means that the digit was already sent via PRI signalling */ 01688 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP)) 01689 && !pvt->begindigit) 01690 goto out; 01691 #endif 01692 01693 if (pvt->begindigit) { 01694 x = -1; 01695 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit); 01696 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x); 01697 pvt->dialing = 0; 01698 pvt->begindigit = 0; 01699 } 01700 01701 out: 01702 ast_mutex_unlock(&pvt->lock); 01703 01704 return res; 01705 }
static void dahdi_disable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2070 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().
02071 { 02072 int res; 02073 02074 if (p->echocanon) { 02075 struct dahdi_echocanparams ecp = { .tap_length = 0 }; 02076 02077 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp); 02078 02079 if (res) 02080 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno)); 02081 else 02082 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel); 02083 } 02084 02085 p->echocanon = 0; 02086 }
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 6564 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().
06565 { 06566 /* Do not disturb */ 06567 dahdichan->dnd = on; 06568 ast_verb(3, "%s DND on channel %d\n", 06569 on? "Enabled" : "Disabled", 06570 dahdichan->channel); 06571 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 06572 "Channel: DAHDI/%d\r\n" 06573 "Status: %s\r\n", dahdichan->channel, 06574 on? "enabled" : "disabled"); 06575 }
static void dahdi_enable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2021 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().
02022 { 02023 int x; 02024 int res; 02025 if (!p) 02026 return; 02027 if (p->echocanon) { 02028 ast_debug(1, "Echo cancellation already on\n"); 02029 return; 02030 } 02031 if (p->digital) { 02032 ast_debug(1, "Echo cancellation isn't required on digital connection\n"); 02033 return; 02034 } 02035 if (p->echocancel.head.tap_length) { 02036 if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) { 02037 x = 1; 02038 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x); 02039 if (res) 02040 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno)); 02041 } 02042 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel); 02043 if (res) { 02044 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno)); 02045 } else { 02046 p->echocanon = 1; 02047 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel); 02048 } 02049 } else 02050 ast_debug(1, "No echo cancellation requested\n"); 02051 }
static struct ast_frame * dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5677 of file chan_dahdi.c.
References __dahdi_exception(), ast_mutex_lock(), ast_mutex_unlock(), f, dahdi_pvt::lock, and ast_channel::tech_pvt.
05678 { 05679 struct dahdi_pvt *p = ast->tech_pvt; 05680 struct ast_frame *f; 05681 ast_mutex_lock(&p->lock); 05682 f = __dahdi_exception(ast); 05683 ast_mutex_unlock(&p->lock); 05684 return f; 05685 }
static int dahdi_fake_event | ( | struct dahdi_pvt * | p, | |
int | mode | |||
) | [static] |
Definition at line 13461 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().
13462 { 13463 if (p) { 13464 switch (mode) { 13465 case TRANSFER: 13466 p->fake_event = DAHDI_EVENT_WINKFLASH; 13467 break; 13468 case HANGUP: 13469 p->fake_event = DAHDI_EVENT_ONHOOK; 13470 break; 13471 default: 13472 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name); 13473 } 13474 } 13475 return 0; 13476 }
static int dahdi_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 4461 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.
04462 { 04463 struct dahdi_pvt *p = newchan->tech_pvt; 04464 int x; 04465 ast_mutex_lock(&p->lock); 04466 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name); 04467 if (p->owner == oldchan) { 04468 p->owner = newchan; 04469 } 04470 for (x = 0; x < 3; x++) 04471 if (p->subs[x].owner == oldchan) { 04472 if (!x) 04473 dahdi_unlink(NULL, p, 0); 04474 p->subs[x].owner = newchan; 04475 } 04476 if (newchan->_state == AST_STATE_RINGING) 04477 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0); 04478 update_conf(p); 04479 ast_mutex_unlock(&p->lock); 04480 return 0; 04481 }
static int dahdi_func_read | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 4037 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.
04038 { 04039 struct dahdi_pvt *p = chan->tech_pvt; 04040 04041 if (!strcasecmp(data, "rxgain")) { 04042 ast_mutex_lock(&p->lock); 04043 snprintf(buf, len, "%f", p->rxgain); 04044 ast_mutex_unlock(&p->lock); 04045 } else if (!strcasecmp(data, "txgain")) { 04046 ast_mutex_lock(&p->lock); 04047 snprintf(buf, len, "%f", p->txgain); 04048 ast_mutex_unlock(&p->lock); 04049 } else { 04050 ast_copy_string(buf, "", len); 04051 } 04052 return 0; 04053 }
static int dahdi_get_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition at line 304 of file chan_dahdi.c.
Referenced by __dahdi_exception(), dahdi_handle_event(), mwi_send_thread(), mwi_thread(), and ss_thread().
00305 { 00306 int j; 00307 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) 00308 return -1; 00309 return j; 00310 }
static int dahdi_get_index | ( | struct ast_channel * | ast, | |
struct dahdi_pvt * | p, | |||
int | nullok | |||
) | [static] |
Definition at line 1318 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().
01319 { 01320 int res; 01321 if (p->subs[SUB_REAL].owner == ast) 01322 res = 0; 01323 else if (p->subs[SUB_CALLWAIT].owner == ast) 01324 res = 1; 01325 else if (p->subs[SUB_THREEWAY].owner == ast) 01326 res = 2; 01327 else { 01328 res = -1; 01329 if (!nullok) 01330 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n"); 01331 } 01332 return res; 01333 }
static void dahdi_handle_dtmfup | ( | struct ast_channel * | ast, | |
int | idx, | |||
struct ast_frame ** | dest | |||
) | [static] |
Definition at line 4622 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().
04623 { 04624 struct dahdi_pvt *p = ast->tech_pvt; 04625 struct ast_frame *f = *dest; 04626 04627 ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name); 04628 04629 if (p->confirmanswer) { 04630 ast_debug(1, "Confirm answer on %s!\n", ast->name); 04631 /* Upon receiving a DTMF digit, consider this an answer confirmation instead 04632 of a DTMF digit */ 04633 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04634 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 04635 *dest = &p->subs[idx].f; 04636 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */ 04637 p->confirmanswer = 0; 04638 } else if (p->callwaitcas) { 04639 if ((f->subclass == 'A') || (f->subclass == 'D')) { 04640 ast_debug(1, "Got some DTMF, but it's for the CAS\n"); 04641 if (p->cidspill) 04642 ast_free(p->cidspill); 04643 send_cwcidspill(p); 04644 } 04645 p->callwaitcas = 0; 04646 p->subs[idx].f.frametype = AST_FRAME_NULL; 04647 p->subs[idx].f.subclass = 0; 04648 *dest = &p->subs[idx].f; 04649 } else if (f->subclass == 'f') { 04650 /* Fax tone -- Handle and return NULL */ 04651 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) { 04652 p->faxhandled = 1; 04653 if (strcmp(ast->exten, "fax")) { 04654 const char *target_context = S_OR(ast->macrocontext, ast->context); 04655 04656 /* We need to unlock 'ast' here because ast_exists_extension has the 04657 * potential to start autoservice on the channel. Such action is prone 04658 * to deadlock. 04659 */ 04660 ast_mutex_unlock(&p->lock); 04661 ast_channel_unlock(ast); 04662 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) { 04663 ast_channel_lock(ast); 04664 ast_mutex_lock(&p->lock); 04665 ast_verb(3, "Redirecting %s to fax extension\n", ast->name); 04666 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 04667 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 04668 if (ast_async_goto(ast, target_context, "fax", 1)) 04669 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 04670 } else { 04671 ast_channel_lock(ast); 04672 ast_mutex_lock(&p->lock); 04673 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 04674 } 04675 } else { 04676 ast_debug(1, "Already in a fax extension, not redirecting\n"); 04677 } 04678 } else { 04679 ast_debug(1, "Fax already handled\n"); 04680 } 04681 dahdi_confmute(p, 0); 04682 p->subs[idx].f.frametype = AST_FRAME_NULL; 04683 p->subs[idx].f.subclass = 0; 04684 *dest = &p->subs[idx].f; 04685 } 04686 }
static struct ast_frame* dahdi_handle_event | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 4699 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_OFFHOOK, 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::needringing, 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().
04700 { 04701 int res, x; 04702 int idx, mysig; 04703 char *c; 04704 struct dahdi_pvt *p = ast->tech_pvt; 04705 pthread_t threadid; 04706 struct ast_channel *chan; 04707 struct ast_frame *f; 04708 04709 idx = dahdi_get_index(ast, p, 0); 04710 mysig = p->sig; 04711 if (p->outsigmod > -1) 04712 mysig = p->outsigmod; 04713 p->subs[idx].f.frametype = AST_FRAME_NULL; 04714 p->subs[idx].f.subclass = 0; 04715 p->subs[idx].f.datalen = 0; 04716 p->subs[idx].f.samples = 0; 04717 p->subs[idx].f.mallocd = 0; 04718 p->subs[idx].f.offset = 0; 04719 p->subs[idx].f.src = "dahdi_handle_event"; 04720 p->subs[idx].f.data.ptr = NULL; 04721 f = &p->subs[idx].f; 04722 04723 if (idx < 0) 04724 return &p->subs[idx].f; 04725 if (p->fake_event) { 04726 res = p->fake_event; 04727 p->fake_event = 0; 04728 } else 04729 res = dahdi_get_event(p->subs[idx].dfd); 04730 04731 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx); 04732 04733 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) { 04734 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0; 04735 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff); 04736 #ifdef HAVE_PRI 04737 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 04738 /* absorb event */ 04739 } else { 04740 #endif 04741 dahdi_confmute(p, 0); 04742 p->subs[idx].f.frametype = AST_FRAME_DTMF_END; 04743 p->subs[idx].f.subclass = res & 0xff; 04744 #ifdef HAVE_PRI 04745 } 04746 #endif 04747 dahdi_handle_dtmfup(ast, idx, &f); 04748 return f; 04749 } 04750 04751 if (res & DAHDI_EVENT_DTMFDOWN) { 04752 ast_debug(1, "DTMF Down '%c'\n", res & 0xff); 04753 /* Mute conference */ 04754 dahdi_confmute(p, 1); 04755 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN; 04756 p->subs[idx].f.subclass = res & 0xff; 04757 return &p->subs[idx].f; 04758 } 04759 04760 switch (res) { 04761 case DAHDI_EVENT_EC_DISABLED: 04762 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel); 04763 p->echocanon = 0; 04764 break; 04765 case DAHDI_EVENT_BITSCHANGED: 04766 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig)); 04767 case DAHDI_EVENT_PULSE_START: 04768 /* Stop tone if there's a pulse start and the PBX isn't started */ 04769 if (!ast->pbx) 04770 tone_zone_play_tone(p->subs[idx].dfd, -1); 04771 break; 04772 case DAHDI_EVENT_DIALCOMPLETE: 04773 if (p->inalarm) break; 04774 if ((p->radio || (p->oprmode < 0))) break; 04775 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) { 04776 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno)); 04777 return NULL; 04778 } 04779 if (!x) { /* if not still dialing in driver */ 04780 dahdi_enable_ec(p); 04781 if (p->echobreak) { 04782 dahdi_train_ec(p); 04783 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); 04784 p->dop.op = DAHDI_DIAL_OP_REPLACE; 04785 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 04786 p->echobreak = 0; 04787 } else { 04788 p->dialing = 0; 04789 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) { 04790 /* if thru with dialing after offhook */ 04791 if (ast->_state == AST_STATE_DIALING_OFFHOOK) { 04792 ast_setstate(ast, AST_STATE_UP); 04793 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04794 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 04795 break; 04796 } else { /* if to state wait for offhook to dial rest */ 04797 /* we now wait for off hook */ 04798 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK); 04799 } 04800 } 04801 if (ast->_state == AST_STATE_DIALING) { 04802 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 04803 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n"); 04804 } 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)))) { 04805 ast_setstate(ast, AST_STATE_RINGING); 04806 } else if (!p->answeronpolarityswitch) { 04807 ast_setstate(ast, AST_STATE_UP); 04808 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04809 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 04810 /* If aops=0 and hops=1, this is necessary */ 04811 p->polarity = POLARITY_REV; 04812 } else { 04813 /* Start clean, so we can catch the change to REV polarity when party answers */ 04814 p->polarity = POLARITY_IDLE; 04815 } 04816 } 04817 } 04818 } 04819 break; 04820 case DAHDI_EVENT_ALARM: 04821 #ifdef HAVE_PRI 04822 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 04823 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) { 04824 /* T309 is not enabled : hangup calls when alarm occurs */ 04825 if (p->call) { 04826 if (p->pri && p->pri->pri) { 04827 if (!pri_grab(p, p->pri)) { 04828 pri_hangup(p->pri->pri, p->call, -1); 04829 pri_destroycall(p->pri->pri, p->call); 04830 p->call = NULL; 04831 pri_rel(p->pri); 04832 } else 04833 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 04834 } else 04835 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n"); 04836 } 04837 if (p->owner) 04838 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 04839 } 04840 } 04841 if (p->bearer) 04842 p->bearer->inalarm = 1; 04843 else 04844 #endif 04845 p->inalarm = 1; 04846 res = get_alarms(p); 04847 handle_alarms(p, res); 04848 #ifdef HAVE_PRI 04849 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 04850 /* fall through intentionally */ 04851 } else { 04852 break; 04853 } 04854 #endif 04855 #ifdef HAVE_SS7 04856 if (p->sig == SIG_SS7) 04857 break; 04858 #endif 04859 case DAHDI_EVENT_ONHOOK: 04860 if (p->radio) { 04861 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04862 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY; 04863 break; 04864 } 04865 if (p->oprmode < 0) 04866 { 04867 if (p->oprmode != -1) break; 04868 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 04869 { 04870 /* Make sure it starts ringing */ 04871 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 04872 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING); 04873 save_conference(p->oprpeer); 04874 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04875 } 04876 break; 04877 } 04878 switch (p->sig) { 04879 case SIG_FXOLS: 04880 case SIG_FXOGS: 04881 case SIG_FXOKS: 04882 p->onhooktime = time(NULL); 04883 p->msgstate = -1; 04884 /* Check for some special conditions regarding call waiting */ 04885 if (idx == SUB_REAL) { 04886 /* The normal line was hung up */ 04887 if (p->subs[SUB_CALLWAIT].owner) { 04888 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */ 04889 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 04890 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel); 04891 unalloc_sub(p, SUB_CALLWAIT); 04892 #if 0 04893 p->subs[idx].needanswer = 0; 04894 p->subs[idx].needringing = 0; 04895 #endif 04896 p->callwaitingrepeat = 0; 04897 p->cidcwexpire = 0; 04898 p->owner = NULL; 04899 /* Don't start streaming audio yet if the incoming call isn't up yet */ 04900 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP) 04901 p->dialing = 1; 04902 dahdi_ring_phone(p); 04903 } else if (p->subs[SUB_THREEWAY].owner) { 04904 unsigned int mssinceflash; 04905 /* Here we have to retain the lock on both the main channel, the 3-way channel, and 04906 the private structure -- not especially easy or clean */ 04907 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) { 04908 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */ 04909 DLA_UNLOCK(&p->lock); 04910 CHANNEL_DEADLOCK_AVOIDANCE(ast); 04911 /* We can grab ast and p in that order, without worry. We should make sure 04912 nothing seriously bad has happened though like some sort of bizarre double 04913 masquerade! */ 04914 DLA_LOCK(&p->lock); 04915 if (p->owner != ast) { 04916 ast_log(LOG_WARNING, "This isn't good...\n"); 04917 return NULL; 04918 } 04919 } 04920 if (!p->subs[SUB_THREEWAY].owner) { 04921 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n"); 04922 return NULL; 04923 } 04924 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime); 04925 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash); 04926 if (mssinceflash < MIN_MS_SINCE_FLASH) { 04927 /* It hasn't been long enough since the last flashook. This is probably a bounce on 04928 hanging up. Hangup both channels now */ 04929 if (p->subs[SUB_THREEWAY].owner) 04930 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER); 04931 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04932 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel); 04933 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04934 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) { 04935 if (p->transfer) { 04936 /* In any case this isn't a threeway call anymore */ 04937 p->subs[SUB_REAL].inthreeway = 0; 04938 p->subs[SUB_THREEWAY].inthreeway = 0; 04939 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */ 04940 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) { 04941 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04942 /* Swap subs and dis-own channel */ 04943 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04944 p->owner = NULL; 04945 /* Ring the phone */ 04946 dahdi_ring_phone(p); 04947 } else { 04948 if ((res = attempt_transfer(p)) < 0) { 04949 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04950 if (p->subs[SUB_THREEWAY].owner) 04951 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04952 } else if (res) { 04953 /* Don't actually hang up at this point */ 04954 if (p->subs[SUB_THREEWAY].owner) 04955 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04956 break; 04957 } 04958 } 04959 } else { 04960 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04961 if (p->subs[SUB_THREEWAY].owner) 04962 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04963 } 04964 } else { 04965 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04966 /* Swap subs and dis-own channel */ 04967 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04968 p->owner = NULL; 04969 /* Ring the phone */ 04970 dahdi_ring_phone(p); 04971 } 04972 } 04973 } else { 04974 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx); 04975 } 04976 /* Fall through */ 04977 default: 04978 dahdi_disable_ec(p); 04979 return NULL; 04980 } 04981 break; 04982 case DAHDI_EVENT_RINGOFFHOOK: 04983 if (p->inalarm) break; 04984 if (p->oprmode < 0) 04985 { 04986 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 04987 { 04988 /* Make sure it stops ringing */ 04989 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 04990 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1); 04991 restore_conference(p->oprpeer); 04992 } 04993 break; 04994 } 04995 if (p->radio) 04996 { 04997 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04998 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY; 04999 break; 05000 } 05001 /* for E911, its supposed to wait for offhook then dial 05002 the second half of the dial string */ 05003 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) { 05004 c = strchr(p->dialdest, '/'); 05005 if (c) 05006 c++; 05007 else 05008 c = p->dialdest; 05009 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c); 05010 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr)); 05011 if (strlen(p->dop.dialstr) > 4) { 05012 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 05013 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 05014 p->echorest[sizeof(p->echorest) - 1] = '\0'; 05015 p->echobreak = 1; 05016 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 05017 } else 05018 p->echobreak = 0; 05019 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 05020 int saveerr = errno; 05021 05022 x = DAHDI_ONHOOK; 05023 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 05024 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 05025 return NULL; 05026 } 05027 p->dialing = 1; 05028 return &p->subs[idx].f; 05029 } 05030 switch (p->sig) { 05031 case SIG_FXOLS: 05032 case SIG_FXOGS: 05033 case SIG_FXOKS: 05034 switch (ast->_state) { 05035 case AST_STATE_RINGING: 05036 dahdi_enable_ec(p); 05037 dahdi_train_ec(p); 05038 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05039 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 05040 /* Make sure it stops ringing */ 05041 p->subs[SUB_REAL].needringing = 0; 05042 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 05043 ast_debug(1, "channel %d answered\n", p->channel); 05044 if (p->cidspill) { 05045 /* Cancel any running CallerID spill */ 05046 ast_free(p->cidspill); 05047 p->cidspill = NULL; 05048 } 05049 p->dialing = 0; 05050 p->callwaitcas = 0; 05051 if (p->confirmanswer) { 05052 /* Ignore answer if "confirm answer" is enabled */ 05053 p->subs[idx].f.frametype = AST_FRAME_NULL; 05054 p->subs[idx].f.subclass = 0; 05055 } else if (!ast_strlen_zero(p->dop.dialstr)) { 05056 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ 05057 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05058 if (res < 0) { 05059 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05060 p->dop.dialstr[0] = '\0'; 05061 return NULL; 05062 } else { 05063 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr); 05064 p->subs[idx].f.frametype = AST_FRAME_NULL; 05065 p->subs[idx].f.subclass = 0; 05066 p->dialing = 1; 05067 } 05068 p->dop.dialstr[0] = '\0'; 05069 ast_setstate(ast, AST_STATE_DIALING); 05070 } else 05071 ast_setstate(ast, AST_STATE_UP); 05072 return &p->subs[idx].f; 05073 case AST_STATE_DOWN: 05074 ast_setstate(ast, AST_STATE_RING); 05075 ast->rings = 1; 05076 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05077 p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK; 05078 ast_debug(1, "channel %d picked up\n", p->channel); 05079 return &p->subs[idx].f; 05080 case AST_STATE_UP: 05081 /* Make sure it stops ringing */ 05082 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 05083 /* Okay -- probably call waiting*/ 05084 if (ast_bridged_channel(p->owner)) 05085 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05086 p->subs[idx].needunhold = 1; 05087 break; 05088 case AST_STATE_RESERVED: 05089 /* Start up dialtone */ 05090 if (has_voicemail(p)) 05091 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 05092 else 05093 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 05094 break; 05095 default: 05096 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state); 05097 } 05098 break; 05099 case SIG_FXSLS: 05100 case SIG_FXSGS: 05101 case SIG_FXSKS: 05102 if (ast->_state == AST_STATE_RING) { 05103 p->ringt = p->ringt_base; 05104 } 05105 05106 /* If we get a ring then we cannot be in 05107 * reversed polarity. So we reset to idle */ 05108 ast_debug(1, "Setting IDLE polarity due " 05109 "to ring. Old polarity was %d\n", 05110 p->polarity); 05111 p->polarity = POLARITY_IDLE; 05112 05113 /* Fall through */ 05114 case SIG_EM: 05115 case SIG_EM_E1: 05116 case SIG_EMWINK: 05117 case SIG_FEATD: 05118 case SIG_FEATDMF: 05119 case SIG_FEATDMF_TA: 05120 case SIG_E911: 05121 case SIG_FGC_CAMA: 05122 case SIG_FGC_CAMAMF: 05123 case SIG_FEATB: 05124 case SIG_SF: 05125 case SIG_SFWINK: 05126 case SIG_SF_FEATD: 05127 case SIG_SF_FEATDMF: 05128 case SIG_SF_FEATB: 05129 if (ast->_state == AST_STATE_PRERING) 05130 ast_setstate(ast, AST_STATE_RING); 05131 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) { 05132 ast_debug(1, "Ring detected\n"); 05133 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05134 p->subs[idx].f.subclass = AST_CONTROL_RING; 05135 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) { 05136 ast_debug(1, "Line answered\n"); 05137 if (p->confirmanswer) { 05138 p->subs[idx].f.frametype = AST_FRAME_NULL; 05139 p->subs[idx].f.subclass = 0; 05140 } else { 05141 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05142 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 05143 ast_setstate(ast, AST_STATE_UP); 05144 } 05145 } else if (ast->_state != AST_STATE_RING) 05146 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel); 05147 break; 05148 default: 05149 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 05150 } 05151 break; 05152 case DAHDI_EVENT_RINGBEGIN: 05153 switch (p->sig) { 05154 case SIG_FXSLS: 05155 case SIG_FXSGS: 05156 case SIG_FXSKS: 05157 if (ast->_state == AST_STATE_RING) { 05158 p->ringt = p->ringt_base; 05159 } 05160 break; 05161 } 05162 break; 05163 case DAHDI_EVENT_RINGEROFF: 05164 if (p->inalarm) break; 05165 if ((p->radio || (p->oprmode < 0))) break; 05166 ast->rings++; 05167 if ((ast->rings > p->cidrings) && (p->cidspill)) { 05168 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n"); 05169 ast_free(p->cidspill); 05170 p->cidspill = NULL; 05171 p->callwaitcas = 0; 05172 } 05173 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05174 p->subs[idx].f.subclass = AST_CONTROL_RINGING; 05175 break; 05176 case DAHDI_EVENT_RINGERON: 05177 break; 05178 case DAHDI_EVENT_NOALARM: 05179 p->inalarm = 0; 05180 #ifdef HAVE_PRI 05181 /* Extremely unlikely but just in case */ 05182 if (p->bearer) 05183 p->bearer->inalarm = 0; 05184 #endif 05185 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 05186 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 05187 "Channel: %d\r\n", p->channel); 05188 break; 05189 case DAHDI_EVENT_WINKFLASH: 05190 if (p->inalarm) break; 05191 if (p->radio) break; 05192 if (p->oprmode < 0) break; 05193 if (p->oprmode > 1) 05194 { 05195 struct dahdi_params par; 05196 05197 memset(&par, 0, sizeof(par)); 05198 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1) 05199 { 05200 if (!par.rxisoffhook) 05201 { 05202 /* Make sure it stops ringing */ 05203 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 05204 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING); 05205 save_conference(p); 05206 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05207 } 05208 } 05209 break; 05210 } 05211 /* Remember last time we got a flash-hook */ 05212 p->flashtime = ast_tvnow(); 05213 switch (mysig) { 05214 case SIG_FXOLS: 05215 case SIG_FXOGS: 05216 case SIG_FXOKS: 05217 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n", 05218 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 05219 p->callwaitcas = 0; 05220 05221 if (idx != SUB_REAL) { 05222 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel); 05223 goto winkflashdone; 05224 } 05225 05226 if (p->subs[SUB_CALLWAIT].owner) { 05227 /* Swap to call-wait */ 05228 swap_subs(p, SUB_REAL, SUB_CALLWAIT); 05229 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 05230 p->owner = p->subs[SUB_REAL].owner; 05231 ast_debug(1, "Making %s the new owner\n", p->owner->name); 05232 if (p->owner->_state == AST_STATE_RINGING) { 05233 ast_setstate(p->owner, AST_STATE_UP); 05234 p->subs[SUB_REAL].needanswer = 1; 05235 } 05236 p->callwaitingrepeat = 0; 05237 p->cidcwexpire = 0; 05238 /* Start music on hold if appropriate */ 05239 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 05240 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 05241 S_OR(p->mohsuggest, NULL), 05242 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05243 } 05244 p->subs[SUB_CALLWAIT].needhold = 1; 05245 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 05246 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD, 05247 S_OR(p->mohsuggest, NULL), 05248 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05249 } 05250 p->subs[SUB_REAL].needunhold = 1; 05251 } else if (!p->subs[SUB_THREEWAY].owner) { 05252 if (!p->threewaycalling) { 05253 /* Just send a flash if no 3-way calling */ 05254 p->subs[SUB_REAL].needflash = 1; 05255 goto winkflashdone; 05256 } else if (!check_for_conference(p)) { 05257 char cid_num[256]; 05258 char cid_name[256]; 05259 05260 cid_num[0] = 0; 05261 cid_name[0] = 0; 05262 if (p->dahditrcallerid && p->owner) { 05263 if (p->owner->cid.cid_num) 05264 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num)); 05265 if (p->owner->cid.cid_name) 05266 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name)); 05267 } 05268 /* XXX This section needs much more error checking!!! XXX */ 05269 /* Start a 3-way call if feasible */ 05270 if (!((ast->pbx) || 05271 (ast->_state == AST_STATE_UP) || 05272 (ast->_state == AST_STATE_RING))) { 05273 ast_debug(1, "Flash when call not up or ringing\n"); 05274 goto winkflashdone; 05275 } 05276 if (alloc_sub(p, SUB_THREEWAY)) { 05277 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n"); 05278 goto winkflashdone; 05279 } 05280 /* Make new channel */ 05281 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0); 05282 if (p->dahditrcallerid) { 05283 if (!p->origcid_num) 05284 p->origcid_num = ast_strdup(p->cid_num); 05285 if (!p->origcid_name) 05286 p->origcid_name = ast_strdup(p->cid_name); 05287 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num)); 05288 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name)); 05289 } 05290 /* Swap things around between the three-way and real call */ 05291 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05292 /* Disable echo canceller for better dialing */ 05293 dahdi_disable_ec(p); 05294 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL); 05295 if (res) 05296 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel); 05297 p->owner = chan; 05298 if (!chan) { 05299 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel); 05300 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 05301 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel); 05302 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 05303 dahdi_enable_ec(p); 05304 ast_hangup(chan); 05305 } else { 05306 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 05307 int way3bridge = 0, cdr3way = 0; 05308 05309 if (!other) { 05310 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 05311 } else 05312 way3bridge = 1; 05313 05314 if (p->subs[SUB_THREEWAY].owner->cdr) 05315 cdr3way = 1; 05316 05317 ast_verb(3, "Started three way call on channel %d\n", p->channel); 05318 05319 /* Start music on hold if appropriate */ 05320 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 05321 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 05322 S_OR(p->mohsuggest, NULL), 05323 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05324 } 05325 p->subs[SUB_THREEWAY].needhold = 1; 05326 } 05327 } 05328 } else { 05329 /* Already have a 3 way call */ 05330 if (p->subs[SUB_THREEWAY].inthreeway) { 05331 /* Call is already up, drop the last person */ 05332 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel); 05333 /* If the primary call isn't answered yet, use it */ 05334 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) { 05335 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/ 05336 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05337 p->owner = p->subs[SUB_REAL].owner; 05338 } 05339 /* Drop the last call and stop the conference */ 05340 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name); 05341 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05342 p->subs[SUB_REAL].inthreeway = 0; 05343 p->subs[SUB_THREEWAY].inthreeway = 0; 05344 } else { 05345 /* Lets see what we're up to */ 05346 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 05347 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) { 05348 int otherindex = SUB_THREEWAY; 05349 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 05350 int way3bridge = 0, cdr3way = 0; 05351 05352 if (!other) { 05353 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 05354 } else 05355 way3bridge = 1; 05356 05357 if (p->subs[SUB_THREEWAY].owner->cdr) 05358 cdr3way = 1; 05359 05360 ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name); 05361 /* Put them in the threeway, and flip */ 05362 p->subs[SUB_THREEWAY].inthreeway = 1; 05363 p->subs[SUB_REAL].inthreeway = 1; 05364 if (ast->_state == AST_STATE_UP) { 05365 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05366 otherindex = SUB_REAL; 05367 } 05368 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner)) 05369 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD); 05370 p->subs[otherindex].needunhold = 1; 05371 p->owner = p->subs[SUB_REAL].owner; 05372 if (ast->_state == AST_STATE_RINGING) { 05373 ast_debug(1, "Enabling ringtone on real and threeway\n"); 05374 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05375 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 05376 } 05377 } else { 05378 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name); 05379 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05380 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05381 p->owner = p->subs[SUB_REAL].owner; 05382 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner)) 05383 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 05384 p->subs[SUB_REAL].needunhold = 1; 05385 dahdi_enable_ec(p); 05386 } 05387 05388 } 05389 } 05390 winkflashdone: 05391 update_conf(p); 05392 break; 05393 case SIG_EM: 05394 case SIG_EM_E1: 05395 case SIG_FEATD: 05396 case SIG_SF: 05397 case SIG_SFWINK: 05398 case SIG_SF_FEATD: 05399 case SIG_FXSLS: 05400 case SIG_FXSGS: 05401 if (option_debug) { 05402 if (p->dialing) 05403 ast_debug(1, "Ignoring wink on channel %d\n", p->channel); 05404 else 05405 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel); 05406 } 05407 break; 05408 case SIG_FEATDMF_TA: 05409 switch (p->whichwink) { 05410 case 0: 05411 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 05412 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 05413 break; 05414 case 1: 05415 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr)); 05416 break; 05417 case 2: 05418 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n"); 05419 return NULL; 05420 } 05421 p->whichwink++; 05422 /* Fall through */ 05423 case SIG_FEATDMF: 05424 case SIG_E911: 05425 case SIG_FGC_CAMAMF: 05426 case SIG_FGC_CAMA: 05427 case SIG_FEATB: 05428 case SIG_SF_FEATDMF: 05429 case SIG_SF_FEATB: 05430 case SIG_EMWINK: 05431 /* FGD MF and EMWINK *Must* wait for wink */ 05432 if (!ast_strlen_zero(p->dop.dialstr)) { 05433 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05434 if (res < 0) { 05435 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05436 p->dop.dialstr[0] = '\0'; 05437 return NULL; 05438 } else 05439 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 05440 } 05441 p->dop.dialstr[0] = '\0'; 05442 break; 05443 default: 05444 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 05445 } 05446 break; 05447 case DAHDI_EVENT_HOOKCOMPLETE: 05448 if (p->inalarm) break; 05449 if ((p->radio || (p->oprmode < 0))) break; 05450 switch (mysig) { 05451 case SIG_FXSLS: /* only interesting for FXS */ 05452 case SIG_FXSGS: 05453 case SIG_FXSKS: 05454 case SIG_EM: 05455 case SIG_EM_E1: 05456 case SIG_EMWINK: 05457 case SIG_FEATD: 05458 case SIG_SF: 05459 case SIG_SFWINK: 05460 case SIG_SF_FEATD: 05461 if (!ast_strlen_zero(p->dop.dialstr)) { 05462 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05463 if (res < 0) { 05464 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05465 p->dop.dialstr[0] = '\0'; 05466 return NULL; 05467 } else 05468 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 05469 } 05470 p->dop.dialstr[0] = '\0'; 05471 p->dop.op = DAHDI_DIAL_OP_REPLACE; 05472 break; 05473 case SIG_FEATDMF: 05474 case SIG_FEATDMF_TA: 05475 case SIG_E911: 05476 case SIG_FGC_CAMA: 05477 case SIG_FGC_CAMAMF: 05478 case SIG_FEATB: 05479 case SIG_SF_FEATDMF: 05480 case SIG_SF_FEATB: 05481 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel); 05482 break; 05483 default: 05484 break; 05485 } 05486 break; 05487 case DAHDI_EVENT_POLARITY: 05488 /* 05489 * If we get a Polarity Switch event, this could be 05490 * due to line seizure, remote end connect or remote end disconnect. 05491 * 05492 * Check to see if we should change the polarity state and 05493 * mark the channel as UP or if this is an indication 05494 * of remote end disconnect. 05495 */ 05496 05497 if (p->polarityonanswerdelay > 0) { 05498 /* check if event is not too soon after OffHook or Answer */ 05499 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) { 05500 switch (ast->_state) { 05501 case AST_STATE_DIALING: /*!< Digits (or equivalent) have been dialed */ 05502 case AST_STATE_RINGING: /*!< Remote end is ringing */ 05503 if (p->answeronpolarityswitch) { 05504 ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel); 05505 ast_setstate(p->owner, AST_STATE_UP); 05506 p->polarity = POLARITY_REV; 05507 if (p->hanguponpolarityswitch) { 05508 p->polaritydelaytv = ast_tvnow(); 05509 } 05510 } else { 05511 ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel); 05512 } 05513 break; 05514 case AST_STATE_UP: /*!< Line is up */ 05515 case AST_STATE_RING: /*!< Line is ringing */ 05516 if (p->hanguponpolarityswitch) { 05517 ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel); 05518 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 05519 p->polarity = POLARITY_IDLE; 05520 } else { 05521 ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel); 05522 } 05523 break; 05524 05525 case AST_STATE_DOWN: /*!< Channel is down and available */ 05526 case AST_STATE_RESERVED: /*!< Channel is down, but reserved */ 05527 case AST_STATE_OFFHOOK: /*!< Channel is off hook */ 05528 case AST_STATE_BUSY: /*!< Line is busy */ 05529 case AST_STATE_DIALING_OFFHOOK: /*!< Digits (or equivalent) have been dialed while offhook */ 05530 case AST_STATE_PRERING: /*!< Channel has detected an incoming call and is waiting for ring */ 05531 default: 05532 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) { 05533 ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state); 05534 } 05535 05536 } 05537 05538 } else { 05539 /* event is too soon after OffHook or Answer */ 05540 switch (ast->_state) { 05541 case AST_STATE_DIALING: /*!< Digits (or equivalent) have been dialed */ 05542 case AST_STATE_RINGING: /*!< Remote end is ringing */ 05543 if (p->answeronpolarityswitch) { 05544 ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state); 05545 } 05546 break; 05547 05548 case AST_STATE_UP: /*!< Line is up */ 05549 case AST_STATE_RING: /*!< Line is ringing */ 05550 if (p->hanguponpolarityswitch) { 05551 ast_debug(1, "Polarity switch detected but NOT hanging up (too close to Answer event) on channel %d, state %d\n", p->channel, ast->_state); 05552 } 05553 break; 05554 05555 default: 05556 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) { 05557 ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state); 05558 } 05559 } 05560 } 05561 } 05562 /* Added more log_debug information below to provide a better indication of what is going on */ 05563 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) ); 05564 break; 05565 default: 05566 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel); 05567 } 05568 return &p->subs[idx].f; 05569 }
static int dahdi_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3396 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().
03397 { 03398 int res; 03399 int idx,x, law; 03400 /*static int restore_gains(struct dahdi_pvt *p);*/ 03401 struct dahdi_pvt *p = ast->tech_pvt; 03402 struct dahdi_pvt *tmp = NULL; 03403 struct dahdi_pvt *prev = NULL; 03404 struct dahdi_params par; 03405 03406 ast_debug(1, "dahdi_hangup(%s)\n", ast->name); 03407 if (!ast->tech_pvt) { 03408 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 03409 return 0; 03410 } 03411 03412 ast_mutex_lock(&p->lock); 03413 03414 idx = dahdi_get_index(ast, p, 1); 03415 03416 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 03417 x = 1; 03418 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 03419 p->cid_num[0] = '\0'; 03420 p->cid_name[0] = '\0'; 03421 } 03422 03423 x = 0; 03424 dahdi_confmute(p, 0); 03425 p->muting = 0; 03426 restore_gains(p); 03427 if (p->origcid_num) { 03428 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num)); 03429 ast_free(p->origcid_num); 03430 p->origcid_num = NULL; 03431 } 03432 if (p->origcid_name) { 03433 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name)); 03434 ast_free(p->origcid_name); 03435 p->origcid_name = NULL; 03436 } 03437 if (p->dsp) 03438 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 03439 p->exten[0] = '\0'; 03440 03441 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n", 03442 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 03443 p->ignoredtmf = 0; 03444 03445 if (idx > -1) { 03446 /* Real channel, do some fixup */ 03447 p->subs[idx].owner = NULL; 03448 p->subs[idx].needanswer = 0; 03449 p->subs[idx].needflash = 0; 03450 p->subs[idx].needringing = 0; 03451 p->subs[idx].needbusy = 0; 03452 p->subs[idx].needcongestion = 0; 03453 p->subs[idx].linear = 0; 03454 p->subs[idx].needcallerid = 0; 03455 p->polarity = POLARITY_IDLE; 03456 dahdi_setlinear(p->subs[idx].dfd, 0); 03457 if (idx == SUB_REAL) { 03458 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) { 03459 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n"); 03460 if (p->subs[SUB_CALLWAIT].inthreeway) { 03461 /* We had flipped over to answer a callwait and now it's gone */ 03462 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n"); 03463 /* Move to the call-wait, but un-own us until they flip back. */ 03464 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03465 unalloc_sub(p, SUB_CALLWAIT); 03466 p->owner = NULL; 03467 } else { 03468 /* The three way hung up, but we still have a call wait */ 03469 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n"); 03470 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03471 unalloc_sub(p, SUB_THREEWAY); 03472 if (p->subs[SUB_REAL].inthreeway) { 03473 /* This was part of a three way call. Immediately make way for 03474 another call */ 03475 ast_debug(1, "Call was complete, setting owner to former third call\n"); 03476 p->owner = p->subs[SUB_REAL].owner; 03477 } else { 03478 /* This call hasn't been completed yet... Set owner to NULL */ 03479 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 03480 p->owner = NULL; 03481 } 03482 p->subs[SUB_REAL].inthreeway = 0; 03483 } 03484 } else if (p->subs[SUB_CALLWAIT].dfd > -1) { 03485 /* Move to the call-wait and switch back to them. */ 03486 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03487 unalloc_sub(p, SUB_CALLWAIT); 03488 p->owner = p->subs[SUB_REAL].owner; 03489 if (p->owner->_state != AST_STATE_UP) 03490 p->subs[SUB_REAL].needanswer = 1; 03491 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 03492 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 03493 } else if (p->subs[SUB_THREEWAY].dfd > -1) { 03494 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03495 unalloc_sub(p, SUB_THREEWAY); 03496 if (p->subs[SUB_REAL].inthreeway) { 03497 /* This was part of a three way call. Immediately make way for 03498 another call */ 03499 ast_debug(1, "Call was complete, setting owner to former third call\n"); 03500 p->owner = p->subs[SUB_REAL].owner; 03501 } else { 03502 /* This call hasn't been completed yet... Set owner to NULL */ 03503 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 03504 p->owner = NULL; 03505 } 03506 p->subs[SUB_REAL].inthreeway = 0; 03507 } 03508 } else if (idx == SUB_CALLWAIT) { 03509 /* Ditch the holding callwait call, and immediately make it availabe */ 03510 if (p->subs[SUB_CALLWAIT].inthreeway) { 03511 /* This is actually part of a three way, placed on hold. Place the third part 03512 on music on hold now */ 03513 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 03514 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 03515 S_OR(p->mohsuggest, NULL), 03516 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 03517 } 03518 p->subs[SUB_THREEWAY].inthreeway = 0; 03519 /* Make it the call wait now */ 03520 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 03521 unalloc_sub(p, SUB_THREEWAY); 03522 } else 03523 unalloc_sub(p, SUB_CALLWAIT); 03524 } else if (idx == SUB_THREEWAY) { 03525 if (p->subs[SUB_CALLWAIT].inthreeway) { 03526 /* The other party of the three way call is currently in a call-wait state. 03527 Start music on hold for them, and take the main guy out of the third call */ 03528 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 03529 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 03530 S_OR(p->mohsuggest, NULL), 03531 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 03532 } 03533 p->subs[SUB_CALLWAIT].inthreeway = 0; 03534 } 03535 p->subs[SUB_REAL].inthreeway = 0; 03536 /* If this was part of a three way call index, let us make 03537 another three way call */ 03538 unalloc_sub(p, SUB_THREEWAY); 03539 } else { 03540 /* This wasn't any sort of call, but how are we an index? */ 03541 ast_log(LOG_WARNING, "Index found but not any type of call?\n"); 03542 } 03543 } 03544 03545 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 03546 p->owner = NULL; 03547 p->ringt = 0; 03548 p->distinctivering = 0; 03549 p->confirmanswer = 0; 03550 p->cidrings = 1; 03551 p->outgoing = 0; 03552 p->digital = 0; 03553 p->faxhandled = 0; 03554 p->pulsedial = 0; 03555 p->onhooktime = time(NULL); 03556 #if defined(HAVE_PRI) || defined(HAVE_SS7) 03557 p->proceeding = 0; 03558 p->dialing = 0; 03559 p->progress = 0; 03560 p->alerting = 0; 03561 p->setup_ack = 0; 03562 p->rlt = 0; 03563 #endif 03564 if (p->dsp) { 03565 ast_dsp_free(p->dsp); 03566 p->dsp = NULL; 03567 } 03568 03569 law = DAHDI_LAW_DEFAULT; 03570 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 03571 if (res < 0) 03572 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 03573 /* Perform low level hangup if no owner left */ 03574 #ifdef HAVE_SS7 03575 if (p->ss7) { 03576 if (p->ss7call) { 03577 if (!ss7_grab(p, p->ss7)) { 03578 if (!p->alreadyhungup) { 03579 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE"); 03580 int icause = ast->hangupcause ? ast->hangupcause : -1; 03581 03582 if (cause) { 03583 if (atoi(cause)) 03584 icause = atoi(cause); 03585 } 03586 isup_rel(p->ss7->ss7, p->ss7call, icause); 03587 ss7_rel(p->ss7); 03588 p->alreadyhungup = 1; 03589 } else 03590 ast_log(LOG_WARNING, "Trying to hangup twice!\n"); 03591 } else { 03592 ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic); 03593 res = -1; 03594 } 03595 } 03596 } 03597 #endif 03598 #ifdef HAVE_PRI 03599 if (p->pri) { 03600 #ifdef SUPPORT_USERUSER 03601 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO"); 03602 #endif 03603 03604 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */ 03605 if (p->call && (!p->bearer || (p->bearer->call == p->call))) { 03606 if (!pri_grab(p, p->pri)) { 03607 if (p->alreadyhungup) { 03608 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n"); 03609 03610 #ifdef SUPPORT_USERUSER 03611 pri_call_set_useruser(p->call, useruser); 03612 #endif 03613 03614 pri_hangup(p->pri->pri, p->call, -1); 03615 p->call = NULL; 03616 if (p->bearer) 03617 p->bearer->call = NULL; 03618 } else { 03619 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE"); 03620 int icause = ast->hangupcause ? ast->hangupcause : -1; 03621 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n"); 03622 03623 #ifdef SUPPORT_USERUSER 03624 pri_call_set_useruser(p->call, useruser); 03625 #endif 03626 03627 p->alreadyhungup = 1; 03628 if (p->bearer) 03629 p->bearer->alreadyhungup = 1; 03630 if (cause) { 03631 if (atoi(cause)) 03632 icause = atoi(cause); 03633 } 03634 pri_hangup(p->pri->pri, p->call, icause); 03635 } 03636 if (res < 0) 03637 ast_log(LOG_WARNING, "pri_disconnect failed\n"); 03638 pri_rel(p->pri); 03639 } else { 03640 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 03641 res = -1; 03642 } 03643 } else { 03644 if (p->bearer) 03645 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call); 03646 p->call = NULL; 03647 res = 0; 03648 } 03649 } 03650 #endif 03651 if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7) && (p->sig != SIG_BRI) && (p->sig != SIG_BRI_PTMP))) 03652 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 03653 if (res < 0) { 03654 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name); 03655 } 03656 switch (p->sig) { 03657 case SIG_FXOGS: 03658 case SIG_FXOLS: 03659 case SIG_FXOKS: 03660 memset(&par, 0, sizeof(par)); 03661 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 03662 if (!res) { 03663 #if 0 03664 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook); 03665 #endif 03666 /* If they're off hook, try playing congestion */ 03667 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0)))) 03668 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 03669 else 03670 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03671 } 03672 break; 03673 case SIG_FXSGS: 03674 case SIG_FXSLS: 03675 case SIG_FXSKS: 03676 /* Make sure we're not made available for at least two seconds assuming 03677 we were actually used for an inbound or outbound call. */ 03678 if (ast->_state != AST_STATE_RESERVED) { 03679 time(&p->guardtime); 03680 p->guardtime += 2; 03681 } 03682 break; 03683 default: 03684 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03685 } 03686 if (p->cidspill) 03687 ast_free(p->cidspill); 03688 if (p->sig) 03689 dahdi_disable_ec(p); 03690 x = 0; 03691 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); 03692 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0); 03693 p->didtdd = 0; 03694 p->cidspill = NULL; 03695 p->callwaitcas = 0; 03696 p->callwaiting = p->permcallwaiting; 03697 p->hidecallerid = p->permhidecallerid; 03698 p->dialing = 0; 03699 p->rdnis[0] = '\0'; 03700 update_conf(p); 03701 reset_conf(p); 03702 /* Restore data mode */ 03703 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 03704 x = 0; 03705 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 03706 } 03707 #ifdef HAVE_PRI 03708 if (p->bearer) { 03709 ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel); 03710 /* Free up the bearer channel as well, and 03711 don't use its file descriptor anymore */ 03712 update_conf(p->bearer); 03713 reset_conf(p->bearer); 03714 p->bearer->owner = NULL; 03715 p->bearer->realcall = NULL; 03716 p->bearer = NULL; 03717 p->subs[SUB_REAL].dfd = -1; 03718 p->pri = NULL; 03719 } 03720 #endif 03721 if (num_restart_pending == 0) 03722 restart_monitor(); 03723 } 03724 03725 p->callwaitingrepeat = 0; 03726 p->cidcwexpire = 0; 03727 p->oprmode = 0; 03728 ast->tech_pvt = NULL; 03729 ast_mutex_unlock(&p->lock); 03730 ast_module_unref(ast_module_info->self); 03731 ast_verb(3, "Hungup '%s'\n", ast->name); 03732 03733 ast_mutex_lock(&iflock); 03734 03735 if (p->restartpending) { 03736 num_restart_pending--; 03737 } 03738 03739 tmp = iflist; 03740 prev = NULL; 03741 if (p->destroy) { 03742 while (tmp) { 03743 if (tmp == p) { 03744 destroy_channel(prev, tmp, 0); 03745 break; 03746 } else { 03747 prev = tmp; 03748 tmp = tmp->next; 03749 } 03750 } 03751 } 03752 ast_mutex_unlock(&iflock); 03753 return 0; 03754 }
static int dahdi_indicate | ( | struct ast_channel * | chan, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 6094 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.
06095 { 06096 struct dahdi_pvt *p = chan->tech_pvt; 06097 int res=-1; 06098 int idx; 06099 int func = DAHDI_FLASH; 06100 ast_mutex_lock(&p->lock); 06101 idx = dahdi_get_index(chan, p, 0); 06102 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name); 06103 if (idx == SUB_REAL) { 06104 switch (condition) { 06105 case AST_CONTROL_BUSY: 06106 #ifdef HAVE_PRI 06107 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) { 06108 chan->hangupcause = AST_CAUSE_USER_BUSY; 06109 chan->_softhangup |= AST_SOFTHANGUP_DEV; 06110 res = 0; 06111 } else if (!p->progress && 06112 ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06113 && p->pri && !p->outgoing) { 06114 if (p->pri->pri) { 06115 if (!pri_grab(p, p->pri)) { 06116 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06117 pri_rel(p->pri); 06118 } 06119 else 06120 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06121 } 06122 p->progress = 1; 06123 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY); 06124 } else 06125 #endif 06126 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY); 06127 break; 06128 case AST_CONTROL_RINGING: 06129 #ifdef HAVE_PRI 06130 if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06131 && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) { 06132 if (p->pri->pri) { 06133 if (!pri_grab(p, p->pri)) { 06134 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06135 pri_rel(p->pri); 06136 } 06137 else 06138 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06139 } 06140 p->alerting = 1; 06141 } 06142 06143 #endif 06144 #ifdef HAVE_SS7 06145 if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) { 06146 if (p->ss7->ss7) { 06147 ss7_grab(p, p->ss7); 06148 06149 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) 06150 p->rlt = 1; 06151 if (p->rlt != 1) /* No need to send CPG if call will be RELEASE */ 06152 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING); 06153 p->alerting = 1; 06154 ss7_rel(p->ss7); 06155 } 06156 } 06157 #endif 06158 06159 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE); 06160 06161 if (chan->_state != AST_STATE_UP) { 06162 if ((chan->_state != AST_STATE_RING) || 06163 ((p->sig != SIG_FXSKS) && 06164 (p->sig != SIG_FXSLS) && 06165 (p->sig != SIG_FXSGS))) 06166 ast_setstate(chan, AST_STATE_RINGING); 06167 } 06168 break; 06169 case AST_CONTROL_PROCEEDING: 06170 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name); 06171 #ifdef HAVE_PRI 06172 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06173 && p->pri && !p->outgoing) { 06174 if (p->pri->pri) { 06175 if (!pri_grab(p, p->pri)) { 06176 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06177 pri_rel(p->pri); 06178 } 06179 else 06180 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06181 } 06182 p->proceeding = 1; 06183 p->dialing = 0; 06184 } 06185 #endif 06186 #ifdef HAVE_SS7 06187 /* This IF sends the FAR for an answered ALEG call */ 06188 if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){ 06189 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) 06190 p->rlt = 1; 06191 } 06192 06193 if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) { 06194 if (p->ss7->ss7) { 06195 ss7_grab(p, p->ss7); 06196 isup_acm(p->ss7->ss7, p->ss7call); 06197 p->proceeding = 1; 06198 ss7_rel(p->ss7); 06199 06200 } 06201 } 06202 #endif 06203 /* don't continue in ast_indicate */ 06204 res = 0; 06205 break; 06206 case AST_CONTROL_PROGRESS: 06207 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name); 06208 #ifdef HAVE_PRI 06209 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */ 06210 if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06211 && p->pri && !p->outgoing) { 06212 if (p->pri->pri) { 06213 if (!pri_grab(p, p->pri)) { 06214 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06215 pri_rel(p->pri); 06216 } 06217 else 06218 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06219 } 06220 p->progress = 1; 06221 } 06222 #endif 06223 #ifdef HAVE_SS7 06224 if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) { 06225 if (p->ss7->ss7) { 06226 ss7_grab(p, p->ss7); 06227 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO); 06228 p->progress = 1; 06229 ss7_rel(p->ss7); 06230 /* enable echo canceler here on SS7 calls */ 06231 dahdi_enable_ec(p); 06232 06233 } 06234 } 06235 #endif 06236 /* don't continue in ast_indicate */ 06237 res = 0; 06238 break; 06239 case AST_CONTROL_CONGESTION: 06240 chan->hangupcause = AST_CAUSE_CONGESTION; 06241 #ifdef HAVE_PRI 06242 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) { 06243 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 06244 chan->_softhangup |= AST_SOFTHANGUP_DEV; 06245 res = 0; 06246 } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06247 && p->pri && !p->outgoing) { 06248 if (p->pri) { 06249 if (!pri_grab(p, p->pri)) { 06250 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06251 pri_rel(p->pri); 06252 } else 06253 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06254 } 06255 p->progress = 1; 06256 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06257 } else 06258 #endif 06259 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06260 break; 06261 case AST_CONTROL_HOLD: 06262 #ifdef HAVE_PRI 06263 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 06264 if (!pri_grab(p, p->pri)) { 06265 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD); 06266 pri_rel(p->pri); 06267 } else 06268 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06269 } else 06270 #endif 06271 ast_moh_start(chan, data, p->mohinterpret); 06272 break; 06273 case AST_CONTROL_UNHOLD: 06274 #ifdef HAVE_PRI 06275 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 06276 if (!pri_grab(p, p->pri)) { 06277 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL); 06278 pri_rel(p->pri); 06279 } else 06280 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06281 } else 06282 #endif 06283 ast_moh_stop(chan); 06284 break; 06285 case AST_CONTROL_RADIO_KEY: 06286 if (p->radio) 06287 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 06288 res = 0; 06289 break; 06290 case AST_CONTROL_RADIO_UNKEY: 06291 if (p->radio) 06292 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF); 06293 res = 0; 06294 break; 06295 case AST_CONTROL_FLASH: 06296 /* flash hookswitch */ 06297 if (ISTRUNK(p) && (p->sig != SIG_PRI)) { 06298 /* Clear out the dial buffer */ 06299 p->dop.dialstr[0] = '\0'; 06300 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 06301 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 06302 chan->name, strerror(errno)); 06303 } else 06304 res = 0; 06305 } else 06306 res = 0; 06307 break; 06308 case AST_CONTROL_SRCUPDATE: 06309 res = 0; 06310 break; 06311 case -1: 06312 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 06313 break; 06314 } 06315 } else 06316 res = 0; 06317 ast_mutex_unlock(&p->lock); 06318 return res; 06319 }
Definition at line 4112 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and master.
Referenced by dahdi_bridge().
04112 { 04113 int x; 04114 if (!slave || !master) { 04115 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n"); 04116 return; 04117 } 04118 for (x = 0; x < MAX_SLAVES; x++) { 04119 if (!master->slaves[x]) { 04120 master->slaves[x] = slave; 04121 break; 04122 } 04123 } 04124 if (x >= MAX_SLAVES) { 04125 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel); 04126 master->slaves[MAX_SLAVES - 1] = slave; 04127 } 04128 if (slave->master) 04129 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel); 04130 slave->master = master; 04131 04132 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x); 04133 }
static struct ast_channel * dahdi_new | ( | struct dahdi_pvt * | , | |
int | , | |||
int | , | |||
int | , | |||
int | , | |||
int | ||||
) | [static] |
Definition at line 6321 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().
06322 { 06323 struct ast_channel *tmp; 06324 int deflaw; 06325 int res; 06326 int x,y; 06327 int features; 06328 struct ast_str *chan_name; 06329 struct ast_variable *v; 06330 struct dahdi_params ps; 06331 if (i->subs[idx].owner) { 06332 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]); 06333 return NULL; 06334 } 06335 y = 1; 06336 chan_name = ast_str_alloca(32); 06337 do { 06338 #ifdef HAVE_PRI 06339 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS))) 06340 ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y); 06341 else 06342 #endif 06343 if (i->channel == CHAN_PSEUDO) 06344 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random()); 06345 else 06346 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y); 06347 for (x = 0; x < 3; x++) { 06348 if ((idx != x) && i->subs[x].owner && !strcasecmp(chan_name->str, i->subs[x].owner->name + 6)) 06349 break; 06350 } 06351 y++; 06352 } while (x < 3); 06353 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); 06354 if (!tmp) 06355 return NULL; 06356 tmp->tech = &dahdi_tech; 06357 memset(&ps, 0, sizeof(ps)); 06358 ps.channo = i->channel; 06359 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps); 06360 if (res) { 06361 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno)); 06362 ps.curlaw = DAHDI_LAW_MULAW; 06363 } 06364 if (ps.curlaw == DAHDI_LAW_ALAW) 06365 deflaw = AST_FORMAT_ALAW; 06366 else 06367 deflaw = AST_FORMAT_ULAW; 06368 if (law) { 06369 if (law == DAHDI_LAW_ALAW) 06370 deflaw = AST_FORMAT_ALAW; 06371 else 06372 deflaw = AST_FORMAT_ULAW; 06373 } 06374 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd); 06375 tmp->nativeformats = deflaw; 06376 /* Start out assuming ulaw since it's smaller :) */ 06377 tmp->rawreadformat = deflaw; 06378 tmp->readformat = deflaw; 06379 tmp->rawwriteformat = deflaw; 06380 tmp->writeformat = deflaw; 06381 i->subs[idx].linear = 0; 06382 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear); 06383 features = 0; 06384 if (idx == SUB_REAL) { 06385 if (i->busydetect && CANBUSYDETECT(i)) 06386 features |= DSP_FEATURE_BUSY_DETECT; 06387 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i)) 06388 features |= DSP_FEATURE_CALL_PROGRESS; 06389 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) || 06390 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) { 06391 features |= DSP_FEATURE_FAX_DETECT; 06392 } 06393 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 06394 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) { 06395 i->hardwaredtmf = 0; 06396 features |= DSP_FEATURE_DIGIT_DETECT; 06397 } else if (NEED_MFDETECT(i)) { 06398 i->hardwaredtmf = 1; 06399 features |= DSP_FEATURE_DIGIT_DETECT; 06400 } 06401 } 06402 if (features) { 06403 if (i->dsp) { 06404 ast_debug(1, "Already have a dsp on %s?\n", tmp->name); 06405 } else { 06406 if (i->channel != CHAN_PSEUDO) 06407 i->dsp = ast_dsp_new(); 06408 else 06409 i->dsp = NULL; 06410 if (i->dsp) { 06411 i->dsp_features = features; 06412 #if defined(HAVE_PRI) || defined(HAVE_SS7) 06413 /* We cannot do progress detection until receives PROGRESS message */ 06414 if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) { 06415 /* Remember requested DSP features, don't treat 06416 talking as ANSWER */ 06417 i->dsp_features = features & ~DSP_PROGRESS_TALK; 06418 features = 0; 06419 } 06420 #endif 06421 ast_dsp_set_features(i->dsp, features); 06422 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax); 06423 if (!ast_strlen_zero(progzone)) 06424 ast_dsp_set_call_progress_zone(i->dsp, progzone); 06425 if (i->busydetect && CANBUSYDETECT(i)) { 06426 if(i->silencethreshold > 0) 06427 ast_dsp_set_threshold(i->dsp, i->silencethreshold); 06428 ast_dsp_set_busy_count(i->dsp, i->busycount); 06429 if(i->busytonelength > 0) 06430 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness); 06431 if((i->busytonelength == i->busyquietlength) && i->busycompare) 06432 ast_dsp_set_busy_compare(i->dsp, i->busycompare); 06433 } 06434 } 06435 } 06436 } 06437 06438 if (state == AST_STATE_RING) 06439 tmp->rings = 1; 06440 tmp->tech_pvt = i; 06441 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) { 06442 /* Only FXO signalled stuff can be picked up */ 06443 tmp->callgroup = i->callgroup; 06444 tmp->pickupgroup = i->pickupgroup; 06445 } 06446 if (!ast_strlen_zero(i->parkinglot)) 06447 ast_string_field_set(tmp, parkinglot, i->parkinglot); 06448 if (!ast_strlen_zero(i->language)) 06449 ast_string_field_set(tmp, language, i->language); 06450 if (!i->owner) 06451 i->owner = tmp; 06452 if (!ast_strlen_zero(i->accountcode)) 06453 ast_string_field_set(tmp, accountcode, i->accountcode); 06454 if (i->amaflags) 06455 tmp->amaflags = i->amaflags; 06456 i->subs[idx].owner = tmp; 06457 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 06458 ast_string_field_set(tmp, call_forward, i->call_forward); 06459 /* If we've been told "no ADSI" then enforce it */ 06460 if (!i->adsi) 06461 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 06462 if (!ast_strlen_zero(i->exten)) 06463 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 06464 if (!ast_strlen_zero(i->rdnis)) 06465 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 06466 if (!ast_strlen_zero(i->dnid)) 06467 tmp->cid.cid_dnid = ast_strdup(i->dnid); 06468 06469 /* Don't use ast_set_callerid() here because it will 06470 * generate a needless NewCallerID event */ 06471 #ifdef PRI_ANI 06472 if (!ast_strlen_zero(i->cid_ani)) 06473 tmp->cid.cid_ani = ast_strdup(i->cid_ani); 06474 else 06475 tmp->cid.cid_ani = ast_strdup(i->cid_num); 06476 #else 06477 tmp->cid.cid_ani = ast_strdup(i->cid_num); 06478 #endif 06479 tmp->cid.cid_pres = i->callingpres; 06480 tmp->cid.cid_ton = i->cid_ton; 06481 tmp->cid.cid_ani2 = i->cid_ani2; 06482 #if defined(HAVE_PRI) || defined(HAVE_SS7) 06483 tmp->transfercapability = transfercapability; 06484 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability)); 06485 if (transfercapability & AST_TRANS_CAP_DIGITAL) 06486 i->digital = 1; 06487 /* Assume calls are not idle calls unless we're told differently */ 06488 i->isidlecall = 0; 06489 i->alreadyhungup = 0; 06490 #endif 06491 /* clear the fake event in case we posted one before we had ast_channel */ 06492 i->fake_event = 0; 06493 /* Assure there is no confmute on this channel */ 06494 dahdi_confmute(i, 0); 06495 i->muting = 0; 06496 /* Configure the new channel jb */ 06497 ast_jb_configure(tmp, &global_jbconf); 06498 06499 ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name); 06500 06501 for (v = i->vars ; v ; v = v->next) 06502 pbx_builtin_setvar_helper(tmp, v->name, v->value); 06503 06504 if (startpbx) { 06505 if (ast_pbx_start(tmp)) { 06506 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 06507 ast_hangup(tmp); 06508 i->owner = NULL; 06509 return NULL; 06510 } 06511 } 06512 06513 ast_module_ref(ast_module_info->self); 06514 return tmp; 06515 }
static int dahdi_open | ( | char * | fn | ) | [static] |
Definition at line 1453 of file chan_dahdi.c.
References ast_log(), chan, errno, LOG_WARNING, and READ_SIZE.
Referenced by alloc_sub(), chandup(), and mkintf().
01454 { 01455 int fd; 01456 int isnum; 01457 int chan = 0; 01458 int bs; 01459 int x; 01460 isnum = 1; 01461 for (x = 0; x < strlen(fn); x++) { 01462 if (!isdigit(fn[x])) { 01463 isnum = 0; 01464 break; 01465 } 01466 } 01467 if (isnum) { 01468 chan = atoi(fn); 01469 if (chan < 1) { 01470 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn); 01471 return -1; 01472 } 01473 fn = "/dev/dahdi/channel"; 01474 } 01475 fd = open(fn, O_RDWR | O_NONBLOCK); 01476 if (fd < 0) { 01477 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno)); 01478 return -1; 01479 } 01480 if (chan) { 01481 if (ioctl(fd, DAHDI_SPECIFY, &chan)) { 01482 x = errno; 01483 close(fd); 01484 errno = x; 01485 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno)); 01486 return -1; 01487 } 01488 } 01489 bs = READ_SIZE; 01490 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) { 01491 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno)); 01492 x = errno; 01493 close(fd); 01494 errno = x; 01495 return -1; 01496 } 01497 return fd; 01498 }
static void dahdi_pri_error | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 10845 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().
10846 { 10847 int x, y; 10848 int dchan = -1, span = -1; 10849 int dchancount = 0; 10850 10851 if (pri) { 10852 for (x = 0; x < NUM_SPANS; x++) { 10853 for (y = 0; y < NUM_DCHANS; y++) { 10854 if (pris[x].dchans[y]) 10855 dchancount++; 10856 10857 if (pris[x].dchans[y] == pri) 10858 dchan = y; 10859 } 10860 if (dchan >= 0) { 10861 span = x; 10862 break; 10863 } 10864 dchancount = 0; 10865 } 10866 if ((dchancount > 1) && (span > -1)) 10867 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s); 10868 else 10869 ast_log(LOG_ERROR, "%s", s); 10870 } else 10871 ast_log(LOG_ERROR, "%s", s); 10872 10873 ast_mutex_lock(&pridebugfdlock); 10874 10875 if (pridebugfd >= 0) { 10876 if (write(pridebugfd, s, strlen(s)) < 0) { 10877 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 10878 } 10879 } 10880 10881 ast_mutex_unlock(&pridebugfdlock); 10882 }
static void dahdi_pri_message | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 10806 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().
10807 { 10808 int x, y; 10809 int dchan = -1, span = -1; 10810 int dchancount = 0; 10811 10812 if (pri) { 10813 for (x = 0; x < NUM_SPANS; x++) { 10814 for (y = 0; y < NUM_DCHANS; y++) { 10815 if (pris[x].dchans[y]) 10816 dchancount++; 10817 10818 if (pris[x].dchans[y] == pri) 10819 dchan = y; 10820 } 10821 if (dchan >= 0) { 10822 span = x; 10823 break; 10824 } 10825 dchancount = 0; 10826 } 10827 if (dchancount > 1 && (span > -1)) 10828 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s); 10829 else 10830 ast_verbose("%s", s); 10831 } else 10832 ast_verbose("%s", s); 10833 10834 ast_mutex_lock(&pridebugfdlock); 10835 10836 if (pridebugfd >= 0) { 10837 if (write(pridebugfd, s, strlen(s)) < 0) { 10838 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 10839 } 10840 } 10841 10842 ast_mutex_unlock(&pridebugfdlock); 10843 }
Definition at line 1359 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().
01360 { 01361 #ifdef HAVE_PRI 01362 struct dahdi_pri *pri = (struct dahdi_pri*) data; 01363 #endif 01364 #ifdef HAVE_SS7 01365 struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data; 01366 #endif 01367 /* We must unlock the PRI to avoid the possibility of a deadlock */ 01368 #if defined(HAVE_PRI) || defined(HAVE_SS7) 01369 if (data) { 01370 switch (p->sig) { 01371 #ifdef HAVE_PRI 01372 case SIG_BRI: 01373 case SIG_BRI_PTMP: 01374 case SIG_PRI: 01375 ast_mutex_unlock(&pri->lock); 01376 break; 01377 #endif 01378 #ifdef HAVE_SS7 01379 case SIG_SS7: 01380 ast_mutex_unlock(&ss7->lock); 01381 break; 01382 #endif 01383 default: 01384 break; 01385 } 01386 } 01387 #endif 01388 for (;;) { 01389 if (p->owner) { 01390 if (ast_channel_trylock(p->owner)) { 01391 DEADLOCK_AVOIDANCE(&p->lock); 01392 } else { 01393 ast_queue_frame(p->owner, f); 01394 ast_channel_unlock(p->owner); 01395 break; 01396 } 01397 } else 01398 break; 01399 } 01400 #if defined(HAVE_PRI) || defined(HAVE_SS7) 01401 if (data) { 01402 switch (p->sig) { 01403 #ifdef HAVE_PRI 01404 case SIG_BRI: 01405 case SIG_BRI_PTMP: 01406 case SIG_PRI: 01407 ast_mutex_lock(&pri->lock); 01408 break; 01409 #endif 01410 #ifdef HAVE_SS7 01411 case SIG_SS7: 01412 ast_mutex_lock(&ss7->lock); 01413 break; 01414 #endif 01415 default: 01416 break; 01417 } 01418 } 01419 01420 #endif 01421 }
static struct ast_frame * dahdi_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5687 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.
05688 { 05689 struct dahdi_pvt *p = ast->tech_pvt; 05690 int res; 05691 int idx; 05692 void *readbuf; 05693 struct ast_frame *f; 05694 05695 while (ast_mutex_trylock(&p->lock)) { 05696 CHANNEL_DEADLOCK_AVOIDANCE(ast); 05697 } 05698 05699 idx = dahdi_get_index(ast, p, 0); 05700 05701 /* Hang up if we don't really exist */ 05702 if (idx < 0) { 05703 ast_log(LOG_WARNING, "We dont exist?\n"); 05704 ast_mutex_unlock(&p->lock); 05705 return NULL; 05706 } 05707 05708 if ((p->radio || (p->oprmode < 0)) && p->inalarm) { 05709 ast_mutex_unlock(&p->lock); 05710 return NULL; 05711 } 05712 05713 p->subs[idx].f.frametype = AST_FRAME_NULL; 05714 p->subs[idx].f.datalen = 0; 05715 p->subs[idx].f.samples = 0; 05716 p->subs[idx].f.mallocd = 0; 05717 p->subs[idx].f.offset = 0; 05718 p->subs[idx].f.subclass = 0; 05719 p->subs[idx].f.delivery = ast_tv(0,0); 05720 p->subs[idx].f.src = "dahdi_read"; 05721 p->subs[idx].f.data.ptr = NULL; 05722 05723 /* make sure it sends initial key state as first frame */ 05724 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio)) 05725 { 05726 struct dahdi_params ps; 05727 05728 memset(&ps, 0, sizeof(ps)); 05729 ps.channo = p->channel; 05730 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 05731 ast_mutex_unlock(&p->lock); 05732 return NULL; 05733 } 05734 p->firstradio = 1; 05735 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05736 if (ps.rxisoffhook) 05737 { 05738 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY; 05739 } 05740 else 05741 { 05742 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY; 05743 } 05744 ast_mutex_unlock(&p->lock); 05745 return &p->subs[idx].f; 05746 } 05747 if (p->ringt == 1) { 05748 ast_mutex_unlock(&p->lock); 05749 return NULL; 05750 } 05751 else if (p->ringt > 0) 05752 p->ringt--; 05753 05754 if (p->subs[idx].needringing) { 05755 /* Send ringing frame if requested */ 05756 p->subs[idx].needringing = 0; 05757 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05758 p->subs[idx].f.subclass = AST_CONTROL_RINGING; 05759 ast_setstate(ast, AST_STATE_RINGING); 05760 ast_mutex_unlock(&p->lock); 05761 return &p->subs[idx].f; 05762 } 05763 05764 if (p->subs[idx].needbusy) { 05765 /* Send busy frame if requested */ 05766 p->subs[idx].needbusy = 0; 05767 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05768 p->subs[idx].f.subclass = AST_CONTROL_BUSY; 05769 ast_mutex_unlock(&p->lock); 05770 return &p->subs[idx].f; 05771 } 05772 05773 if (p->subs[idx].needcongestion) { 05774 /* Send congestion frame if requested */ 05775 p->subs[idx].needcongestion = 0; 05776 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05777 p->subs[idx].f.subclass = AST_CONTROL_CONGESTION; 05778 ast_mutex_unlock(&p->lock); 05779 return &p->subs[idx].f; 05780 } 05781 05782 if (p->subs[idx].needcallerid) { 05783 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL), 05784 S_OR(p->lastcid_name, NULL), 05785 S_OR(p->lastcid_num, NULL) 05786 ); 05787 p->subs[idx].needcallerid = 0; 05788 } 05789 05790 if (p->subs[idx].needanswer) { 05791 /* Send answer frame if requested */ 05792 p->subs[idx].needanswer = 0; 05793 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05794 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 05795 ast_mutex_unlock(&p->lock); 05796 return &p->subs[idx].f; 05797 } 05798 05799 if (p->subs[idx].needflash) { 05800 /* Send answer frame if requested */ 05801 p->subs[idx].needflash = 0; 05802 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05803 p->subs[idx].f.subclass = AST_CONTROL_FLASH; 05804 ast_mutex_unlock(&p->lock); 05805 return &p->subs[idx].f; 05806 } 05807 05808 if (p->subs[idx].needhold) { 05809 /* Send answer frame if requested */ 05810 p->subs[idx].needhold = 0; 05811 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05812 p->subs[idx].f.subclass = AST_CONTROL_HOLD; 05813 ast_mutex_unlock(&p->lock); 05814 ast_debug(1, "Sending hold on '%s'\n", ast->name); 05815 return &p->subs[idx].f; 05816 } 05817 05818 if (p->subs[idx].needunhold) { 05819 /* Send answer frame if requested */ 05820 p->subs[idx].needunhold = 0; 05821 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05822 p->subs[idx].f.subclass = AST_CONTROL_UNHOLD; 05823 ast_mutex_unlock(&p->lock); 05824 ast_debug(1, "Sending unhold on '%s'\n", ast->name); 05825 return &p->subs[idx].f; 05826 } 05827 05828 if (ast->rawreadformat == AST_FORMAT_SLINEAR) { 05829 if (!p->subs[idx].linear) { 05830 p->subs[idx].linear = 1; 05831 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 05832 if (res) 05833 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx); 05834 } 05835 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) || 05836 (ast->rawreadformat == AST_FORMAT_ALAW)) { 05837 if (p->subs[idx].linear) { 05838 p->subs[idx].linear = 0; 05839 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 05840 if (res) 05841 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx); 05842 } 05843 } else { 05844 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat)); 05845 ast_mutex_unlock(&p->lock); 05846 return NULL; 05847 } 05848 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET; 05849 CHECK_BLOCKING(ast); 05850 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); 05851 ast_clear_flag(ast, AST_FLAG_BLOCKING); 05852 /* Check for hangup */ 05853 if (res < 0) { 05854 f = NULL; 05855 if (res == -1) { 05856 if (errno == EAGAIN) { 05857 /* Return "NULL" frame if there is nobody there */ 05858 ast_mutex_unlock(&p->lock); 05859 return &p->subs[idx].f; 05860 } else if (errno == ELAST) { 05861 f = __dahdi_exception(ast); 05862 } else 05863 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno)); 05864 } 05865 ast_mutex_unlock(&p->lock); 05866 return f; 05867 } 05868 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) { 05869 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); 05870 f = __dahdi_exception(ast); 05871 ast_mutex_unlock(&p->lock); 05872 return f; 05873 } 05874 if (p->tdd) { /* if in TDD mode, see if we receive that */ 05875 int c; 05876 05877 c = tdd_feed(p->tdd,readbuf,READ_SIZE); 05878 if (c < 0) { 05879 ast_debug(1,"tdd_feed failed\n"); 05880 ast_mutex_unlock(&p->lock); 05881 return NULL; 05882 } 05883 if (c) { /* if a char to return */ 05884 p->subs[idx].f.subclass = 0; 05885 p->subs[idx].f.frametype = AST_FRAME_TEXT; 05886 p->subs[idx].f.mallocd = 0; 05887 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; 05888 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET; 05889 p->subs[idx].f.datalen = 1; 05890 *((char *) p->subs[idx].f.data.ptr) = c; 05891 ast_mutex_unlock(&p->lock); 05892 return &p->subs[idx].f; 05893 } 05894 } 05895 /* Ensure the CW timer decrements only on a single subchannel */ 05896 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) { 05897 p->callwaitingrepeat--; 05898 } 05899 if (p->cidcwexpire) 05900 p->cidcwexpire--; 05901 /* Repeat callwaiting */ 05902 if (p->callwaitingrepeat == 1) { 05903 p->callwaitrings++; 05904 dahdi_callwait(ast); 05905 } 05906 /* Expire CID/CW */ 05907 if (p->cidcwexpire == 1) { 05908 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n"); 05909 restore_conference(p); 05910 } 05911 if (p->subs[idx].linear) { 05912 p->subs[idx].f.datalen = READ_SIZE * 2; 05913 } else 05914 p->subs[idx].f.datalen = READ_SIZE; 05915 05916 /* Handle CallerID Transmission */ 05917 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) { 05918 send_callerid(p); 05919 } 05920 05921 p->subs[idx].f.frametype = AST_FRAME_VOICE; 05922 p->subs[idx].f.subclass = ast->rawreadformat; 05923 p->subs[idx].f.samples = READ_SIZE; 05924 p->subs[idx].f.mallocd = 0; 05925 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; 05926 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]); 05927 #if 0 05928 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name); 05929 #endif 05930 if (p->dialing || /* Transmitting something */ 05931 (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */ 05932 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */ 05933 ) { 05934 /* Whoops, we're still dialing, or in a state where we shouldn't transmit.... 05935 don't send anything */ 05936 p->subs[idx].f.frametype = AST_FRAME_NULL; 05937 p->subs[idx].f.subclass = 0; 05938 p->subs[idx].f.samples = 0; 05939 p->subs[idx].f.mallocd = 0; 05940 p->subs[idx].f.offset = 0; 05941 p->subs[idx].f.data.ptr = NULL; 05942 p->subs[idx].f.datalen= 0; 05943 } 05944 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !idx) { 05945 /* Perform busy detection. etc on the dahdi line */ 05946 int mute; 05947 05948 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f); 05949 05950 /* Check if DSP code thinks we should be muting this frame and mute the conference if so */ 05951 mute = ast_dsp_was_muted(p->dsp); 05952 if (p->muting != mute) { 05953 p->muting = mute; 05954 dahdi_confmute(p, mute); 05955 } 05956 05957 if (f) { 05958 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) { 05959 if ((ast->_state == AST_STATE_UP) && !p->outgoing) { 05960 /* Treat this as a "hangup" instead of a "busy" on the assumption that 05961 a busy */ 05962 f = NULL; 05963 } 05964 } else if (f->frametype == AST_FRAME_DTMF) { 05965 #ifdef HAVE_PRI 05966 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && 05967 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) || 05968 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) { 05969 /* Don't accept in-band DTMF when in overlap dial mode */ 05970 f->frametype = AST_FRAME_NULL; 05971 f->subclass = 0; 05972 } 05973 #endif 05974 /* DSP clears us of being pulse */ 05975 p->pulsedial = 0; 05976 } 05977 } 05978 } else 05979 f = &p->subs[idx].f; 05980 05981 if (f && (f->frametype == AST_FRAME_DTMF)) 05982 dahdi_handle_dtmfup(ast, idx, &f); 05983 05984 /* If we have a fake_event, trigger exception to handle it */ 05985 if (p->fake_event) 05986 ast_set_flag(ast, AST_FLAG_EXCEPTION); 05987 05988 ast_mutex_unlock(&p->lock); 05989 return f; 05990 }
static struct ast_channel * dahdi_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 9556 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().
09557 { 09558 ast_group_t groupmatch = 0; 09559 int channelmatch = -1; 09560 int roundrobin = 0; 09561 int callwait = 0; 09562 int busy = 0; 09563 struct dahdi_pvt *p; 09564 struct ast_channel *tmp = NULL; 09565 char *dest=NULL; 09566 int x; 09567 char *s; 09568 char opt=0; 09569 int res=0, y=0; 09570 int backwards = 0; 09571 #ifdef HAVE_PRI 09572 int crv; 09573 int bearer = -1; 09574 int trunkgroup; 09575 struct dahdi_pri *pri=NULL; 09576 #endif 09577 struct dahdi_pvt *exitpvt, *start, *end; 09578 ast_mutex_t *lock; 09579 int channelmatched = 0; 09580 int groupmatched = 0; 09581 09582 /* 09583 * data is ---v 09584 * Dial(DAHDI/pseudo[/extension]) 09585 * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension]) 09586 * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension]) 09587 * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension]) 09588 * 09589 * g - channel group allocation search forward 09590 * G - channel group allocation search backward 09591 * r - channel group allocation round robin search forward 09592 * R - channel group allocation round robin search backward 09593 * 09594 * c - Wait for DTMF digit to confirm answer 09595 * r<cadance#> - Set distintive ring cadance number 09596 * d - Force bearer capability for ISDN/SS7 call to digital. 09597 */ 09598 09599 /* Assume we're locking the iflock */ 09600 lock = &iflock; 09601 start = iflist; 09602 end = ifend; 09603 if (data) { 09604 dest = ast_strdupa((char *)data); 09605 } else { 09606 ast_log(LOG_WARNING, "Channel requested with no data\n"); 09607 return NULL; 09608 } 09609 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') { 09610 /* Retrieve the group number */ 09611 char *stringp; 09612 09613 stringp = dest + 1; 09614 s = strsep(&stringp, "/"); 09615 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) { 09616 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data); 09617 return NULL; 09618 } 09619 groupmatch = ((ast_group_t) 1 << x); 09620 if (toupper(dest[0]) == 'G') { 09621 if (dest[0] == 'G') { 09622 backwards = 1; 09623 p = ifend; 09624 } else 09625 p = iflist; 09626 } else { 09627 if (dest[0] == 'R') { 09628 backwards = 1; 09629 p = round_robin[x]?round_robin[x]->prev:ifend; 09630 if (!p) 09631 p = ifend; 09632 } else { 09633 p = round_robin[x]?round_robin[x]->next:iflist; 09634 if (!p) 09635 p = iflist; 09636 } 09637 roundrobin = 1; 09638 } 09639 } else { 09640 char *stringp; 09641 09642 stringp = dest; 09643 s = strsep(&stringp, "/"); 09644 p = iflist; 09645 if (!strcasecmp(s, "pseudo")) { 09646 /* Special case for pseudo */ 09647 x = CHAN_PSEUDO; 09648 channelmatch = x; 09649 } 09650 #ifdef HAVE_PRI 09651 else if ((res = sscanf(s, "%30d:%30d%1c%30d", &trunkgroup, &crv, &opt, &y)) > 1) { 09652 if ((trunkgroup < 1) || (crv < 1)) { 09653 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data); 09654 return NULL; 09655 } 09656 res--; 09657 for (x = 0; x < NUM_SPANS; x++) { 09658 if (pris[x].trunkgroup == trunkgroup) { 09659 pri = pris + x; 09660 lock = &pri->lock; 09661 start = pri->crvs; 09662 end = pri->crvend; 09663 break; 09664 } 09665 } 09666 if (!pri) { 09667 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup); 09668 return NULL; 09669 } 09670 channelmatch = crv; 09671 p = pris[x].crvs; 09672 } 09673 #endif 09674 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) { 09675 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data); 09676 return NULL; 09677 } else { 09678 channelmatch = x; 09679 } 09680 } 09681 /* Search for an unowned channel */ 09682 ast_mutex_lock(lock); 09683 exitpvt = p; 09684 while (p && !tmp) { 09685 if (roundrobin) 09686 round_robin[x] = p; 09687 #if 0 09688 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch); 09689 #endif 09690 09691 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) { 09692 ast_debug(1, "Using channel %d\n", p->channel); 09693 if (p->inalarm) 09694 goto next; 09695 09696 callwait = (p->owner != NULL); 09697 #ifdef HAVE_PRI 09698 if (pri && (p->subs[SUB_REAL].dfd < 0)) { 09699 if (p->sig != SIG_FXSKS) { 09700 /* Gotta find an actual channel to use for this 09701 CRV if this isn't a callwait */ 09702 bearer = pri_find_empty_chan(pri, 0); 09703 if (bearer < 0) { 09704 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv); 09705 p = NULL; 09706 break; 09707 } 09708 pri_assign_bearer(p, pri, pri->pvts[bearer]); 09709 } else { 09710 if (alloc_sub(p, 0)) { 09711 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n"); 09712 p = NULL; 09713 break; 09714 } else 09715 ast_debug(1, "Allocated placeholder pseudo channel\n"); 09716 09717 p->pri = pri; 09718 } 09719 } 09720 #endif 09721 if (p->channel == CHAN_PSEUDO) { 09722 p = chandup(p); 09723 if (!p) { 09724 break; 09725 } 09726 } 09727 if (p->owner) { 09728 if (alloc_sub(p, SUB_CALLWAIT)) { 09729 p = NULL; 09730 break; 09731 } 09732 } 09733 p->outgoing = 1; 09734 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0); 09735 if (!tmp) { 09736 p->outgoing = 0; 09737 } 09738 #ifdef HAVE_PRI 09739 if (p->bearer) { 09740 /* Log owner to bearer channel, too */ 09741 p->bearer->owner = tmp; 09742 } 09743 #endif 09744 /* Make special notes */ 09745 if (res > 1) { 09746 if (opt == 'c') { 09747 /* Confirm answer */ 09748 p->confirmanswer = 1; 09749 } else if (opt == 'r') { 09750 /* Distinctive ring */ 09751 if (res < 3) 09752 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data); 09753 else 09754 p->distinctivering = y; 09755 } else if (opt == 'd') { 09756 /* If this is an ISDN call, make it digital */ 09757 p->digital = 1; 09758 if (tmp) 09759 tmp->transfercapability = AST_TRANS_CAP_DIGITAL; 09760 } else { 09761 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data); 09762 } 09763 } 09764 /* Note if the call is a call waiting call */ 09765 if (tmp && callwait) 09766 tmp->cdrflags |= AST_CDR_CALLWAIT; 09767 break; 09768 } 09769 next: 09770 if (backwards) { 09771 p = p->prev; 09772 if (!p) 09773 p = end; 09774 } else { 09775 p = p->next; 09776 if (!p) 09777 p = start; 09778 } 09779 /* stop when you roll to the one that we started from */ 09780 if (p == exitpvt) 09781 break; 09782 } 09783 ast_mutex_unlock(lock); 09784 restart_monitor(); 09785 if (callwait) 09786 *cause = AST_CAUSE_BUSY; 09787 else if (!tmp) { 09788 if (channelmatched) { 09789 if (busy) 09790 *cause = AST_CAUSE_BUSY; 09791 } else if (groupmatched) { 09792 *cause = AST_CAUSE_CONGESTION; 09793 } 09794 } 09795 09796 return tmp; 09797 }
static int dahdi_restart | ( | void | ) | [static] |
Definition at line 12622 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().
12623 { 12624 #if defined(HAVE_PRI) || defined(HAVE_SS7) 12625 int i, j; 12626 #endif 12627 int cancel_code; 12628 struct dahdi_pvt *p; 12629 12630 ast_mutex_lock(&restart_lock); 12631 12632 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n"); 12633 dahdi_softhangup_all(); 12634 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n"); 12635 12636 #if defined(HAVE_PRI) 12637 for (i = 0; i < NUM_SPANS; i++) { 12638 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) { 12639 cancel_code = pthread_cancel(pris[i].master); 12640 pthread_kill(pris[i].master, SIGURG); 12641 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code); 12642 pthread_join(pris[i].master, NULL); 12643 ast_debug(4, "Joined thread of span %d\n", i); 12644 } 12645 } 12646 #endif 12647 12648 #if defined(HAVE_SS7) 12649 for (i = 0; i < NUM_SPANS; i++) { 12650 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) { 12651 cancel_code = pthread_cancel(linksets[i].master); 12652 pthread_kill(linksets[i].master, SIGURG); 12653 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code); 12654 pthread_join(linksets[i].master, NULL); 12655 ast_debug(4, "Joined thread of span %d\n", i); 12656 } 12657 } 12658 #endif 12659 12660 ast_mutex_lock(&monlock); 12661 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 12662 cancel_code = pthread_cancel(monitor_thread); 12663 pthread_kill(monitor_thread, SIGURG); 12664 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code); 12665 pthread_join(monitor_thread, NULL); 12666 ast_debug(4, "Joined monitor thread\n"); 12667 } 12668 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */ 12669 12670 ast_mutex_lock(&mwi_thread_lock); 12671 while (mwi_thread_count > 0) { 12672 ast_debug(3, "Waiting on %d mwi_send_thread(s) to finish\n", mwi_thread_count); 12673 ast_cond_wait(&mwi_thread_complete, &mwi_thread_lock); 12674 } 12675 ast_mutex_unlock(&mwi_thread_lock); 12676 ast_mutex_lock(&ss_thread_lock); 12677 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */ 12678 int x = DAHDI_FLASH; 12679 ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count); 12680 12681 for (p = iflist; p; p = p->next) { 12682 if (p->owner) 12683 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 */ 12684 } 12685 ast_cond_wait(&ss_thread_complete, &ss_thread_lock); 12686 } 12687 12688 /* ensure any created channels before monitor threads were stopped are hungup */ 12689 dahdi_softhangup_all(); 12690 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n"); 12691 destroy_all_channels(); 12692 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels()); 12693 12694 ast_mutex_unlock(&monlock); 12695 12696 #ifdef HAVE_PRI 12697 for (i = 0; i < NUM_SPANS; i++) { 12698 for (j = 0; j < NUM_DCHANS; j++) 12699 dahdi_close_pri_fd(&(pris[i]), j); 12700 } 12701 12702 memset(pris, 0, sizeof(pris)); 12703 for (i = 0; i < NUM_SPANS; i++) { 12704 ast_mutex_init(&pris[i].lock); 12705 pris[i].offset = -1; 12706 pris[i].master = AST_PTHREADT_NULL; 12707 for (j = 0; j < NUM_DCHANS; j++) 12708 pris[i].fds[j] = -1; 12709 } 12710 pri_set_error(dahdi_pri_error); 12711 pri_set_message(dahdi_pri_message); 12712 #endif 12713 #ifdef HAVE_SS7 12714 for (i = 0; i < NUM_SPANS; i++) { 12715 for (j = 0; j < NUM_DCHANS; j++) 12716 dahdi_close_ss7_fd(&(linksets[i]), j); 12717 } 12718 12719 memset(linksets, 0, sizeof(linksets)); 12720 for (i = 0; i < NUM_SPANS; i++) { 12721 ast_mutex_init(&linksets[i].lock); 12722 linksets[i].master = AST_PTHREADT_NULL; 12723 for (j = 0; j < NUM_DCHANS; j++) 12724 linksets[i].fds[j] = -1; 12725 } 12726 ss7_set_error(dahdi_ss7_error); 12727 ss7_set_message(dahdi_ss7_message); 12728 #endif 12729 12730 if (setup_dahdi(2) != 0) { 12731 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n"); 12732 ast_mutex_unlock(&ss_thread_lock); 12733 return 1; 12734 } 12735 ast_mutex_unlock(&ss_thread_lock); 12736 ast_mutex_unlock(&restart_lock); 12737 return 0; 12738 }
static char* dahdi_restart_cmd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12740 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.
12741 { 12742 switch (cmd) { 12743 case CLI_INIT: 12744 e->command = "dahdi restart"; 12745 e->usage = 12746 "Usage: dahdi restart\n" 12747 " Restarts the DAHDI channels: destroys them all and then\n" 12748 " re-reads them from chan_dahdi.conf.\n" 12749 " Note that this will STOP any running CALL on DAHDI channels.\n" 12750 ""; 12751 return NULL; 12752 case CLI_GENERATE: 12753 return NULL; 12754 } 12755 if (a->argc != 2) 12756 return CLI_SHOWUSAGE; 12757 12758 if (dahdi_restart() != 0) 12759 return CLI_FAILURE; 12760 return CLI_SUCCESS; 12761 }
static int dahdi_ring_phone | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4483 of file chan_dahdi.c.
References ast_log(), errno, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), and dahdi_handle_event().
04484 { 04485 int x; 04486 int res; 04487 /* Make sure our transmit state is on hook */ 04488 x = 0; 04489 x = DAHDI_ONHOOK; 04490 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04491 do { 04492 x = DAHDI_RING; 04493 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04494 if (res) { 04495 switch (errno) { 04496 case EBUSY: 04497 case EINTR: 04498 /* Wait just in case */ 04499 usleep(10000); 04500 continue; 04501 case EINPROGRESS: 04502 res = 0; 04503 break; 04504 default: 04505 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno)); 04506 res = 0; 04507 } 04508 } 04509 } while (res); 04510 return res; 04511 }
static int dahdi_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3277 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().
03278 { 03279 /* Data will be our digit string */ 03280 struct dahdi_pvt *p; 03281 char *digits = (char *) data; 03282 03283 if (ast_strlen_zero(digits)) { 03284 ast_debug(1, "No digit string sent to application!\n"); 03285 return -1; 03286 } 03287 03288 p = (struct dahdi_pvt *)chan->tech_pvt; 03289 03290 if (!p) { 03291 ast_debug(1, "Unable to find technology private\n"); 03292 return -1; 03293 } 03294 03295 ast_mutex_lock(&p->lock); 03296 03297 if (!p->pri || !p->call) { 03298 ast_debug(1, "Unable to find pri or call on channel!\n"); 03299 ast_mutex_unlock(&p->lock); 03300 return -1; 03301 } 03302 03303 if (!pri_grab(p, p->pri)) { 03304 pri_keypad_facility(p->pri->pri, p->call, digits); 03305 pri_rel(p->pri); 03306 } else { 03307 ast_debug(1, "Unable to grab pri to send keypad facility!\n"); 03308 ast_mutex_unlock(&p->lock); 03309 return -1; 03310 } 03311 03312 ast_mutex_unlock(&p->lock); 03313 03314 return 0; 03315 }
static int dahdi_sendtext | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 15501 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.
15502 { 15503 #define END_SILENCE_LEN 400 15504 #define HEADER_MS 50 15505 #define TRAILER_MS 5 15506 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) 15507 #define ASCII_BYTES_PER_CHAR 80 15508 15509 unsigned char *buf,*mybuf; 15510 struct dahdi_pvt *p = c->tech_pvt; 15511 struct pollfd fds[1]; 15512 int size,res,fd,len,x; 15513 int bytes=0; 15514 /* Initial carrier (imaginary) */ 15515 float cr = 1.0; 15516 float ci = 0.0; 15517 float scont = 0.0; 15518 int idx; 15519 15520 idx = dahdi_get_index(c, p, 0); 15521 if (idx < 0) { 15522 ast_log(LOG_WARNING, "Huh? I don't exist?\n"); 15523 return -1; 15524 } 15525 if (!text[0]) return(0); /* if nothing to send, dont */ 15526 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */ 15527 if (p->mate) 15528 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN); 15529 else 15530 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN); 15531 if (!buf) 15532 return -1; 15533 mybuf = buf; 15534 if (p->mate) { 15535 int codec = AST_LAW(p); 15536 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */ 15537 PUT_CLID_MARKMS; 15538 } 15539 /* Put actual message */ 15540 for (x = 0; text[x]; x++) { 15541 PUT_CLID(text[x]); 15542 } 15543 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */ 15544 PUT_CLID_MARKMS; 15545 } 15546 len = bytes; 15547 buf = mybuf; 15548 } else { 15549 len = tdd_generate(p->tdd, buf, text); 15550 if (len < 1) { 15551 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text)); 15552 ast_free(mybuf); 15553 return -1; 15554 } 15555 } 15556 memset(buf + len, 0x7f, END_SILENCE_LEN); 15557 len += END_SILENCE_LEN; 15558 fd = p->subs[idx].dfd; 15559 while (len) { 15560 if (ast_check_hangup(c)) { 15561 ast_free(mybuf); 15562 return -1; 15563 } 15564 size = len; 15565 if (size > READ_SIZE) 15566 size = READ_SIZE; 15567 fds[0].fd = fd; 15568 fds[0].events = POLLOUT | POLLPRI; 15569 fds[0].revents = 0; 15570 res = poll(fds, 1, -1); 15571 if (!res) { 15572 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 15573 continue; 15574 } 15575 /* if got exception */ 15576 if (fds[0].revents & POLLPRI) { 15577 ast_free(mybuf); 15578 return -1; 15579 } 15580 if (!(fds[0].revents & POLLOUT)) { 15581 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 15582 continue; 15583 } 15584 res = write(fd, buf, size); 15585 if (res != size) { 15586 if (res == -1) { 15587 ast_free(mybuf); 15588 return -1; 15589 } 15590 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 15591 break; 15592 } 15593 len -= size; 15594 buf += size; 15595 } 15596 ast_free(mybuf); 15597 return(0); 15598 }
static char* dahdi_set_dnd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 13388 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.
13389 { 13390 int channel; 13391 int on; 13392 struct dahdi_pvt *dahdi_chan = NULL; 13393 13394 switch (cmd) { 13395 case CLI_INIT: 13396 e->command = "dahdi set dnd"; 13397 e->usage = 13398 "Usage: dahdi set dnd <chan#> <on|off>\n" 13399 " Sets/resets DND (Do Not Disturb) mode on a channel.\n" 13400 " Changes take effect immediately.\n" 13401 " <chan num> is the channel number\n" 13402 " <on|off> Enable or disable DND mode?\n" 13403 ; 13404 return NULL; 13405 case CLI_GENERATE: 13406 return NULL; 13407 } 13408 13409 if (a->argc != 5) 13410 return CLI_SHOWUSAGE; 13411 13412 if ((channel = atoi(a->argv[3])) <= 0) { 13413 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]); 13414 return CLI_SHOWUSAGE; 13415 } 13416 13417 if (ast_true(a->argv[4])) 13418 on = 1; 13419 else if (ast_false(a->argv[4])) 13420 on = 0; 13421 else { 13422 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]); 13423 return CLI_SHOWUSAGE; 13424 } 13425 13426 ast_mutex_lock(&iflock); 13427 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) { 13428 if (dahdi_chan->channel != channel) 13429 continue; 13430 13431 /* Found the channel. Actually set it */ 13432 dahdi_dnd(dahdi_chan, on); 13433 break; 13434 } 13435 ast_mutex_unlock(&iflock); 13436 13437 if (!dahdi_chan) { 13438 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 13439 return CLI_FAILURE; 13440 } 13441 13442 return CLI_SUCCESS; 13443 }
static int dahdi_set_hook | ( | int | fd, | |
int | hs | |||
) | [inline, static] |
Definition at line 2224 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().
02225 { 02226 int x, res; 02227 02228 x = hs; 02229 res = ioctl(fd, DAHDI_HOOK, &x); 02230 02231 if (res < 0) { 02232 if (errno == EINPROGRESS) 02233 return 0; 02234 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno)); 02235 /* will expectedly fail if phone is off hook during operation, such as during a restart */ 02236 } 02237 02238 return res; 02239 }
static char* dahdi_set_hwgain | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 13245 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.
13246 { 13247 int channel; 13248 int gain; 13249 int tx; 13250 struct dahdi_hwgain hwgain; 13251 struct dahdi_pvt *tmp = NULL; 13252 13253 switch (cmd) { 13254 case CLI_INIT: 13255 e->command = "dahdi set hwgain"; 13256 e->usage = 13257 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n" 13258 " Sets the hardware gain on a a given channel, overriding the\n" 13259 " value provided at module loadtime, whether the channel is in\n" 13260 " use or not. Changes take effect immediately.\n" 13261 " <rx|tx> which direction do you want to change (relative to our module)\n" 13262 " <chan num> is the channel number relative to the device\n" 13263 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"; 13264 return NULL; 13265 case CLI_GENERATE: 13266 return NULL; 13267 } 13268 13269 if (a->argc != 6) 13270 return CLI_SHOWUSAGE; 13271 13272 if (!strcasecmp("rx", a->argv[3])) 13273 tx = 0; /* rx */ 13274 else if (!strcasecmp("tx", a->argv[3])) 13275 tx = 1; /* tx */ 13276 else 13277 return CLI_SHOWUSAGE; 13278 13279 channel = atoi(a->argv[4]); 13280 gain = atof(a->argv[5])*10.0; 13281 13282 ast_mutex_lock(&iflock); 13283 13284 for (tmp = iflist; tmp; tmp = tmp->next) { 13285 13286 if (tmp->channel != channel) 13287 continue; 13288 13289 if (tmp->subs[SUB_REAL].dfd == -1) 13290 break; 13291 13292 hwgain.newgain = gain; 13293 hwgain.tx = tx; 13294 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) { 13295 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno)); 13296 ast_mutex_unlock(&iflock); 13297 return CLI_FAILURE; 13298 } 13299 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n", 13300 tx ? "tx" : "rx", gain, (float)gain/10.0, channel); 13301 break; 13302 } 13303 13304 ast_mutex_unlock(&iflock); 13305 13306 if (tmp) 13307 return CLI_SUCCESS; 13308 13309 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 13310 return CLI_FAILURE; 13311 13312 }
static char* dahdi_set_swgain | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 13314 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.
13315 { 13316 int channel; 13317 float gain; 13318 int tx; 13319 int res; 13320 ast_mutex_t *lock; 13321 struct dahdi_pvt *tmp = NULL; 13322 13323 switch (cmd) { 13324 case CLI_INIT: 13325 e->command = "dahdi set swgain"; 13326 e->usage = 13327 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n" 13328 " Sets the software gain on a a given channel, overriding the\n" 13329 " value provided at module loadtime, whether the channel is in\n" 13330 " use or not. Changes take effect immediately.\n" 13331 " <rx|tx> which direction do you want to change (relative to our module)\n" 13332 " <chan num> is the channel number relative to the device\n" 13333 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"; 13334 return NULL; 13335 case CLI_GENERATE: 13336 return NULL; 13337 } 13338 13339 lock = &iflock; 13340 13341 if (a->argc != 6) 13342 return CLI_SHOWUSAGE; 13343 13344 if (!strcasecmp("rx", a->argv[3])) 13345 tx = 0; /* rx */ 13346 else if (!strcasecmp("tx", a->argv[3])) 13347 tx = 1; /* tx */ 13348 else 13349 return CLI_SHOWUSAGE; 13350 13351 channel = atoi(a->argv[4]); 13352 gain = atof(a->argv[5]); 13353 13354 ast_mutex_lock(lock); 13355 for (tmp = iflist; tmp; tmp = tmp->next) { 13356 13357 if (tmp->channel != channel) 13358 continue; 13359 13360 if (tmp->subs[SUB_REAL].dfd == -1) 13361 break; 13362 13363 if (tx) 13364 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law); 13365 else 13366 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law); 13367 13368 if (res) { 13369 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel); 13370 ast_mutex_unlock(lock); 13371 return CLI_FAILURE; 13372 } 13373 13374 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n", 13375 tx ? "tx" : "rx", gain, channel); 13376 break; 13377 } 13378 ast_mutex_unlock(lock); 13379 13380 if (tmp) 13381 return CLI_SUCCESS; 13382 13383 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 13384 return CLI_FAILURE; 13385 13386 }
static int dahdi_setlaw | ( | int | dfd, | |
int | law | |||
) | [static] |
Definition at line 9800 of file chan_dahdi.c.
09801 { 09802 return ioctl(dfd, DAHDI_SETLAW, &law); 09803 }
static int dahdi_setlinear | ( | int | dfd, | |
int | linear | |||
) | [static] |
Definition at line 1528 of file chan_dahdi.c.
Referenced by dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_write(), send_callerid(), and ss_thread().
01529 { 01530 int res; 01531 res = ioctl(dfd, DAHDI_SETLINEAR, &linear); 01532 if (res) 01533 return res; 01534 return 0; 01535 }
static int dahdi_setoption | ( | struct ast_channel * | chan, | |
int | option, | |||
void * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 3856 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.
03857 { 03858 char *cp; 03859 signed char *scp; 03860 int x; 03861 int idx; 03862 struct dahdi_pvt *p = chan->tech_pvt, *pp; 03863 struct oprmode *oprmode; 03864 03865 03866 /* all supported options require data */ 03867 if (!data || (datalen < 1)) { 03868 errno = EINVAL; 03869 return -1; 03870 } 03871 03872 switch (option) { 03873 case AST_OPTION_TXGAIN: 03874 scp = (signed char *) data; 03875 idx = dahdi_get_index(chan, p, 0); 03876 if (idx < 0) { 03877 ast_log(LOG_WARNING, "No index in TXGAIN?\n"); 03878 return -1; 03879 } 03880 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp); 03881 return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law); 03882 case AST_OPTION_RXGAIN: 03883 scp = (signed char *) data; 03884 idx = dahdi_get_index(chan, p, 0); 03885 if (idx < 0) { 03886 ast_log(LOG_WARNING, "No index in RXGAIN?\n"); 03887 return -1; 03888 } 03889 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp); 03890 return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law); 03891 case AST_OPTION_TONE_VERIFY: 03892 if (!p->dsp) 03893 break; 03894 cp = (char *) data; 03895 switch (*cp) { 03896 case 1: 03897 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name); 03898 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */ 03899 break; 03900 case 2: 03901 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name); 03902 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */ 03903 break; 03904 default: 03905 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name); 03906 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */ 03907 break; 03908 } 03909 break; 03910 case AST_OPTION_TDD: 03911 /* turn on or off TDD */ 03912 cp = (char *) data; 03913 p->mate = 0; 03914 if (!*cp) { /* turn it off */ 03915 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name); 03916 if (p->tdd) 03917 tdd_free(p->tdd); 03918 p->tdd = 0; 03919 break; 03920 } 03921 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n", 03922 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name); 03923 dahdi_disable_ec(p); 03924 /* otherwise, turn it on */ 03925 if (!p->didtdd) { /* if havent done it yet */ 03926 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */ 03927 unsigned char *buf; 03928 int size, res, fd, len; 03929 struct pollfd fds[1]; 03930 03931 buf = mybuf; 03932 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */ 03933 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */ 03934 len = 40000; 03935 idx = dahdi_get_index(chan, p, 0); 03936 if (idx < 0) { 03937 ast_log(LOG_WARNING, "No index in TDD?\n"); 03938 return -1; 03939 } 03940 fd = p->subs[idx].dfd; 03941 while (len) { 03942 if (ast_check_hangup(chan)) 03943 return -1; 03944 size = len; 03945 if (size > READ_SIZE) 03946 size = READ_SIZE; 03947 fds[0].fd = fd; 03948 fds[0].events = POLLPRI | POLLOUT; 03949 fds[0].revents = 0; 03950 res = poll(fds, 1, -1); 03951 if (!res) { 03952 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 03953 continue; 03954 } 03955 /* if got exception */ 03956 if (fds[0].revents & POLLPRI) 03957 return -1; 03958 if (!(fds[0].revents & POLLOUT)) { 03959 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 03960 continue; 03961 } 03962 res = write(fd, buf, size); 03963 if (res != size) { 03964 if (res == -1) return -1; 03965 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 03966 break; 03967 } 03968 len -= size; 03969 buf += size; 03970 } 03971 p->didtdd = 1; /* set to have done it now */ 03972 } 03973 if (*cp == 2) { /* Mate mode */ 03974 if (p->tdd) 03975 tdd_free(p->tdd); 03976 p->tdd = 0; 03977 p->mate = 1; 03978 break; 03979 } 03980 if (!p->tdd) { /* if we dont have one yet */ 03981 p->tdd = tdd_new(); /* allocate one */ 03982 } 03983 break; 03984 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */ 03985 if (!p->dsp) 03986 break; 03987 cp = (char *) data; 03988 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n", 03989 *cp ? "ON" : "OFF", (int) *cp, chan->name); 03990 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax); 03991 break; 03992 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */ 03993 cp = (char *) data; 03994 if (!*cp) { 03995 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name); 03996 x = 0; 03997 dahdi_disable_ec(p); 03998 } else { 03999 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name); 04000 x = 1; 04001 } 04002 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1) 04003 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno)); 04004 break; 04005 case AST_OPTION_OPRMODE: /* Operator services mode */ 04006 oprmode = (struct oprmode *) data; 04007 pp = oprmode->peer->tech_pvt; 04008 p->oprmode = pp->oprmode = 0; 04009 /* setup peers */ 04010 p->oprpeer = pp; 04011 pp->oprpeer = p; 04012 /* setup modes, if any */ 04013 if (oprmode->mode) 04014 { 04015 pp->oprmode = oprmode->mode; 04016 p->oprmode = -oprmode->mode; 04017 } 04018 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n", 04019 oprmode->mode, chan->name,oprmode->peer->name); 04020 break; 04021 case AST_OPTION_ECHOCAN: 04022 cp = (char *) data; 04023 if (*cp) { 04024 ast_debug(1, "Enabling echo cancelation on %s\n", chan->name); 04025 dahdi_enable_ec(p); 04026 } else { 04027 ast_debug(1, "Disabling echo cancelation on %s\n", chan->name); 04028 dahdi_disable_ec(p); 04029 } 04030 break; 04031 } 04032 errno = 0; 04033 04034 return 0; 04035 }
static char* dahdi_show_channel | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12897 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.
12898 { 12899 int channel; 12900 struct dahdi_pvt *tmp = NULL; 12901 struct dahdi_confinfo ci; 12902 struct dahdi_params ps; 12903 int x; 12904 ast_mutex_t *lock; 12905 struct dahdi_pvt *start; 12906 #ifdef HAVE_PRI 12907 char *c; 12908 int trunkgroup; 12909 struct dahdi_pri *pri=NULL; 12910 #endif 12911 switch (cmd) { 12912 case CLI_INIT: 12913 e->command = "dahdi show channel"; 12914 e->usage = 12915 "Usage: dahdi show channel <chan num>\n" 12916 " Detailed information about a given channel\n"; 12917 return NULL; 12918 case CLI_GENERATE: 12919 return NULL; 12920 } 12921 12922 lock = &iflock; 12923 start = iflist; 12924 12925 if (a->argc != 4) 12926 return CLI_SHOWUSAGE; 12927 #ifdef HAVE_PRI 12928 if ((c = strchr(a->argv[3], ':'))) { 12929 if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2) 12930 return CLI_SHOWUSAGE; 12931 if ((trunkgroup < 1) || (channel < 1)) 12932 return CLI_SHOWUSAGE; 12933 for (x = 0; x < NUM_SPANS; x++) { 12934 if (pris[x].trunkgroup == trunkgroup) { 12935 pri = pris + x; 12936 break; 12937 } 12938 } 12939 if (pri) { 12940 start = pri->crvs; 12941 lock = &pri->lock; 12942 } else { 12943 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup); 12944 return CLI_FAILURE; 12945 } 12946 } else 12947 #endif 12948 channel = atoi(a->argv[3]); 12949 12950 ast_mutex_lock(lock); 12951 tmp = start; 12952 while (tmp) { 12953 if (tmp->channel == channel) { 12954 #ifdef HAVE_PRI 12955 if (pri) 12956 ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel); 12957 else 12958 #endif 12959 ast_cli(a->fd, "Channel: %d\n", tmp->channel); 12960 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd); 12961 ast_cli(a->fd, "Span: %d\n", tmp->span); 12962 ast_cli(a->fd, "Extension: %s\n", tmp->exten); 12963 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no"); 12964 ast_cli(a->fd, "Context: %s\n", tmp->context); 12965 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num); 12966 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton); 12967 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name); 12968 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none")); 12969 if (tmp->vars) { 12970 struct ast_variable *v; 12971 ast_cli(a->fd, "Variables:\n"); 12972 for (v = tmp->vars ; v ; v = v->next) 12973 ast_cli(a->fd, " %s = %s\n", v->name, v->value); 12974 } 12975 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy); 12976 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm); 12977 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig)); 12978 ast_cli(a->fd, "Radio: %d\n", tmp->radio); 12979 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>"); 12980 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)" : ""); 12981 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)" : ""); 12982 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)" : ""); 12983 ast_cli(a->fd, "Confno: %d\n", tmp->confno); 12984 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno); 12985 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference); 12986 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no"); 12987 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no"); 12988 if (tmp->busydetect) { 12989 #if defined(BUSYDETECT_TONEONLY) 12990 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n"); 12991 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE) 12992 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n"); 12993 #endif 12994 #ifdef BUSYDETECT_DEBUG 12995 ast_cli(a->fd, " Busy Detector Debug: Enabled\n"); 12996 #endif 12997 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount); 12998 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength); 12999 } 13000 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no"); 13001 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no"); 13002 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas); 13003 ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown"); 13004 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no"); 13005 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no"); 13006 ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no"); 13007 ast_cli(a->fd, "Echo Cancellation:\n"); 13008 13009 if (tmp->echocancel.head.tap_length) { 13010 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length); 13011 for (x = 0; x < tmp->echocancel.head.param_count; x++) { 13012 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value); 13013 } 13014 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF"); 13015 } else { 13016 ast_cli(a->fd, "\tnone\n"); 13017 } 13018 if (tmp->master) 13019 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel); 13020 for (x = 0; x < MAX_SLAVES; x++) { 13021 if (tmp->slaves[x]) 13022 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel); 13023 } 13024 #ifdef HAVE_SS7 13025 if (tmp->ss7) { 13026 ast_cli(a->fd, "CIC: %d\n", tmp->cic); 13027 } 13028 #endif 13029 #ifdef HAVE_PRI 13030 if (tmp->pri) { 13031 ast_cli(a->fd, "PRI Flags: "); 13032 if (tmp->resetting) 13033 ast_cli(a->fd, "Resetting "); 13034 if (tmp->call) 13035 ast_cli(a->fd, "Call "); 13036 if (tmp->bearer) 13037 ast_cli(a->fd, "Bearer "); 13038 ast_cli(a->fd, "\n"); 13039 if (tmp->logicalspan) 13040 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan); 13041 else 13042 ast_cli(a->fd, "PRI Logical Span: Implicit\n"); 13043 } 13044 13045 #endif 13046 memset(&ci, 0, sizeof(ci)); 13047 ps.channo = tmp->channel; 13048 if (tmp->subs[SUB_REAL].dfd > -1) { 13049 memset(&ci, 0, sizeof(ci)); 13050 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 13051 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode); 13052 } 13053 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) { 13054 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No"); 13055 } 13056 memset(&ps, 0, sizeof(ps)); 13057 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 13058 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno)); 13059 } else { 13060 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook"); 13061 } 13062 } 13063 if (ISTRUNK(tmp)) { 13064 ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no"); 13065 if (!ast_strlen_zero(progzone)) 13066 ast_cli(a->fd, "Progress Zone: %s\n", progzone); 13067 ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no"); 13068 if(tmp->busydetect) { 13069 ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount); 13070 if(tmp->busytonelength > 0) { 13071 ast_cli(a->fd, "Busy Pattern:\n"); 13072 ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength); 13073 if (tmp->busyquietlength > 0) 13074 ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength); 13075 else 13076 ast_cli(a->fd, " -- Detect Tone Only\n"); 13077 if(tmp->busyfuzziness > 0) 13078 ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness); 13079 } 13080 } 13081 } 13082 ast_mutex_unlock(lock); 13083 return CLI_SUCCESS; 13084 } 13085 tmp = tmp->next; 13086 } 13087 13088 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 13089 ast_mutex_unlock(lock); 13090 return CLI_FAILURE; 13091 }
static char* dahdi_show_channels | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12773 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.
12774 { 12775 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 12776 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 12777 unsigned int targetnum = 0; 12778 int filtertype = 0; 12779 struct dahdi_pvt *tmp = NULL; 12780 char tmps[20] = ""; 12781 char statestr[20] = ""; 12782 char blockstr[20] = ""; 12783 ast_mutex_t *lock; 12784 struct dahdi_pvt *start; 12785 #ifdef HAVE_PRI 12786 int trunkgroup; 12787 struct dahdi_pri *pri = NULL; 12788 int x; 12789 #endif 12790 switch (cmd) { 12791 case CLI_INIT: 12792 e->command = "dahdi show channels [trunkgroup|group|context]"; 12793 e->usage = 12794 "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n" 12795 " Shows a list of available channels with optional filtering\n" 12796 " <group> must be a number between 0 and 63\n"; 12797 return NULL; 12798 case CLI_GENERATE: 12799 return NULL; 12800 } 12801 12802 lock = &iflock; 12803 start = iflist; 12804 12805 /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */ 12806 12807 if (!((a->argc == 3) || (a->argc == 5))) 12808 return CLI_SHOWUSAGE; 12809 12810 if (a->argc == 5) { 12811 #ifdef HAVE_PRI 12812 if (!strcasecmp(a->argv[3], "trunkgroup")) { 12813 /* this option requires no special handling, so leave filtertype to zero */ 12814 if ((trunkgroup = atoi(a->argv[4])) < 1) 12815 return CLI_SHOWUSAGE; 12816 for (x = 0; x < NUM_SPANS; x++) { 12817 if (pris[x].trunkgroup == trunkgroup) { 12818 pri = pris + x; 12819 break; 12820 } 12821 } 12822 if (pri) { 12823 start = pri->crvs; 12824 lock = &pri->lock; 12825 } else { 12826 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup); 12827 return CLI_FAILURE; 12828 } 12829 } else 12830 #endif 12831 if (!strcasecmp(a->argv[3], "group")) { 12832 targetnum = atoi(a->argv[4]); 12833 if ((targetnum < 0) || (targetnum > 63)) 12834 return CLI_SHOWUSAGE; 12835 targetnum = 1 << targetnum; 12836 filtertype = 1; 12837 } else if (!strcasecmp(a->argv[3], "context")) { 12838 filtertype = 2; 12839 } 12840 } 12841 12842 ast_mutex_lock(lock); 12843 #ifdef HAVE_PRI 12844 ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State"); 12845 #else 12846 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State"); 12847 #endif 12848 12849 tmp = start; 12850 while (tmp) { 12851 if (filtertype) { 12852 switch(filtertype) { 12853 case 1: /* dahdi show channels group <group> */ 12854 if (!(tmp->group & targetnum)) { 12855 tmp = tmp->next; 12856 continue; 12857 } 12858 break; 12859 case 2: /* dahdi show channels context <context> */ 12860 if (strcasecmp(tmp->context, a->argv[4])) { 12861 tmp = tmp->next; 12862 continue; 12863 } 12864 break; 12865 default: 12866 ; 12867 } 12868 } 12869 if (tmp->channel > 0) { 12870 snprintf(tmps, sizeof(tmps), "%d", tmp->channel); 12871 } else 12872 ast_copy_string(tmps, "pseudo", sizeof(tmps)); 12873 12874 if (tmp->locallyblocked) 12875 blockstr[0] = 'L'; 12876 else 12877 blockstr[0] = ' '; 12878 12879 if (tmp->remotelyblocked) 12880 blockstr[1] = 'R'; 12881 else 12882 blockstr[1] = ' '; 12883 12884 blockstr[2] = '\0'; 12885 12886 snprintf(statestr, sizeof(statestr), "%s", "In Service"); 12887 12888 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr); 12889 tmp = tmp->next; 12890 } 12891 ast_mutex_unlock(lock); 12892 return CLI_SUCCESS; 12893 #undef FORMAT 12894 #undef FORMAT2 12895 }
static char* dahdi_show_status | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 13130 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.
13131 { 13132 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n" 13133 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n" 13134 int span; 13135 int res; 13136 char alarmstr[50]; 13137 13138 int ctl; 13139 struct dahdi_spaninfo s; 13140 13141 switch (cmd) { 13142 case CLI_INIT: 13143 e->command = "dahdi show status"; 13144 e->usage = 13145 "Usage: dahdi show status\n" 13146 " Shows a list of DAHDI cards with status\n"; 13147 return NULL; 13148 case CLI_GENERATE: 13149 return NULL; 13150 } 13151 ctl = open("/dev/dahdi/ctl", O_RDWR); 13152 if (ctl < 0) { 13153 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno)); 13154 return CLI_FAILURE; 13155 } 13156 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO"); 13157 13158 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 13159 s.spanno = span; 13160 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 13161 if (res) { 13162 continue; 13163 } 13164 alarmstr[0] = '\0'; 13165 if (s.alarms > 0) { 13166 if (s.alarms & DAHDI_ALARM_BLUE) 13167 strcat(alarmstr, "BLU/"); 13168 if (s.alarms & DAHDI_ALARM_YELLOW) 13169 strcat(alarmstr, "YEL/"); 13170 if (s.alarms & DAHDI_ALARM_RED) 13171 strcat(alarmstr, "RED/"); 13172 if (s.alarms & DAHDI_ALARM_LOOPBACK) 13173 strcat(alarmstr, "LB/"); 13174 if (s.alarms & DAHDI_ALARM_RECOVER) 13175 strcat(alarmstr, "REC/"); 13176 if (s.alarms & DAHDI_ALARM_NOTOPEN) 13177 strcat(alarmstr, "NOP/"); 13178 if (!strlen(alarmstr)) 13179 strcat(alarmstr, "UUU/"); 13180 if (strlen(alarmstr)) { 13181 /* Strip trailing / */ 13182 alarmstr[strlen(alarmstr) - 1] = '\0'; 13183 } 13184 } else { 13185 if (s.numchans) 13186 strcpy(alarmstr, "OK"); 13187 else 13188 strcpy(alarmstr, "UNCONFIGURED"); 13189 } 13190 13191 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count 13192 , s.lineconfig & DAHDI_CONFIG_D4 ? "D4" : 13193 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" : 13194 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" : 13195 "CAS" 13196 , s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" : 13197 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" : 13198 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" : 13199 "Unk" 13200 , s.lineconfig & DAHDI_CONFIG_CRC4 ? 13201 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL" 13202 , lbostr[s.lbo] 13203 ); 13204 } 13205 close(ctl); 13206 13207 return CLI_SUCCESS; 13208 #undef FORMAT 13209 #undef FORMAT2 13210 }
static char* dahdi_show_version | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 13212 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.
13213 { 13214 int pseudo_fd = -1; 13215 struct dahdi_versioninfo vi; 13216 13217 switch (cmd) { 13218 case CLI_INIT: 13219 e->command = "dahdi show version"; 13220 e->usage = 13221 "Usage: dahdi show version\n" 13222 " Shows the DAHDI version in use\n"; 13223 return NULL; 13224 case CLI_GENERATE: 13225 return NULL; 13226 } 13227 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) { 13228 ast_cli(a->fd, "Failed to open control file to get version.\n"); 13229 return CLI_SUCCESS; 13230 } 13231 13232 strcpy(vi.version, "Unknown"); 13233 strcpy(vi.echo_canceller, "Unknown"); 13234 13235 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) 13236 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno)); 13237 else 13238 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller); 13239 13240 close(pseudo_fd); 13241 13242 return CLI_SUCCESS; 13243 }
static char* dahdi_sig2str | ( | int | sig | ) | [static] |
Definition at line 1771 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.
01772 { 01773 static char buf[256]; 01774 switch (sig) { 01775 case SIG_EM: 01776 return "E & M Immediate"; 01777 case SIG_EMWINK: 01778 return "E & M Wink"; 01779 case SIG_EM_E1: 01780 return "E & M E1"; 01781 case SIG_FEATD: 01782 return "Feature Group D (DTMF)"; 01783 case SIG_FEATDMF: 01784 return "Feature Group D (MF)"; 01785 case SIG_FEATDMF_TA: 01786 return "Feature Groud D (MF) Tandem Access"; 01787 case SIG_FEATB: 01788 return "Feature Group B (MF)"; 01789 case SIG_E911: 01790 return "E911 (MF)"; 01791 case SIG_FGC_CAMA: 01792 return "FGC/CAMA (Dialpulse)"; 01793 case SIG_FGC_CAMAMF: 01794 return "FGC/CAMA (MF)"; 01795 case SIG_FXSLS: 01796 return "FXS Loopstart"; 01797 case SIG_FXSGS: 01798 return "FXS Groundstart"; 01799 case SIG_FXSKS: 01800 return "FXS Kewlstart"; 01801 case SIG_FXOLS: 01802 return "FXO Loopstart"; 01803 case SIG_FXOGS: 01804 return "FXO Groundstart"; 01805 case SIG_FXOKS: 01806 return "FXO Kewlstart"; 01807 case SIG_PRI: 01808 return "ISDN PRI"; 01809 case SIG_BRI: 01810 return "ISDN BRI Point to Point"; 01811 case SIG_BRI_PTMP: 01812 return "ISDN BRI Point to MultiPoint"; 01813 case SIG_SS7: 01814 return "SS7"; 01815 case SIG_SF: 01816 return "SF (Tone) Immediate"; 01817 case SIG_SFWINK: 01818 return "SF (Tone) Wink"; 01819 case SIG_SF_FEATD: 01820 return "SF (Tone) with Feature Group D (DTMF)"; 01821 case SIG_SF_FEATDMF: 01822 return "SF (Tone) with Feature Group D (MF)"; 01823 case SIG_SF_FEATB: 01824 return "SF (Tone) with Feature Group B (MF)"; 01825 case SIG_GR303FXOKS: 01826 return "GR-303 with FXOKS"; 01827 case SIG_GR303FXSKS: 01828 return "GR-303 with FXSKS"; 01829 case 0: 01830 return "Pseudo"; 01831 default: 01832 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig); 01833 return buf; 01834 } 01835 }
static void dahdi_softhangup_all | ( | void | ) | [static] |
Definition at line 12593 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().
12594 { 12595 struct dahdi_pvt *p; 12596 retry: 12597 ast_mutex_lock(&iflock); 12598 for (p = iflist; p; p = p->next) { 12599 ast_mutex_lock(&p->lock); 12600 if (p->owner && !p->restartpending) { 12601 if (ast_channel_trylock(p->owner)) { 12602 if (option_debug > 2) 12603 ast_verbose("Avoiding deadlock\n"); 12604 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */ 12605 ast_mutex_unlock(&p->lock); 12606 ast_mutex_unlock(&iflock); 12607 goto retry; 12608 } 12609 if (option_debug > 2) 12610 ast_verbose("Softhanging up on %s\n", p->owner->name); 12611 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT); 12612 p->restartpending = 1; 12613 num_restart_pending++; 12614 ast_channel_unlock(p->owner); 12615 } 12616 ast_mutex_unlock(&p->lock); 12617 } 12618 ast_mutex_unlock(&iflock); 12619 }
static void dahdi_train_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2053 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().
02054 { 02055 int x; 02056 int res; 02057 02058 if (p && p->echocanon && p->echotraining) { 02059 x = p->echotraining; 02060 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x); 02061 if (res) 02062 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno)); 02063 else 02064 ast_debug(1, "Engaged echo training on channel %d\n", p->channel); 02065 } else { 02066 ast_debug(1, "No echo training requested\n"); 02067 } 02068 }
static void dahdi_unlink | ( | struct dahdi_pvt * | slave, | |
struct dahdi_pvt * | master, | |||
int | needlock | |||
) | [static] |
Definition at line 4056 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().
04057 { 04058 /* Unlink a specific slave or all slaves/masters from a given master */ 04059 int x; 04060 int hasslaves; 04061 if (!master) 04062 return; 04063 if (needlock) { 04064 ast_mutex_lock(&master->lock); 04065 if (slave) { 04066 while (ast_mutex_trylock(&slave->lock)) { 04067 DEADLOCK_AVOIDANCE(&master->lock); 04068 } 04069 } 04070 } 04071 hasslaves = 0; 04072 for (x = 0; x < MAX_SLAVES; x++) { 04073 if (master->slaves[x]) { 04074 if (!slave || (master->slaves[x] == slave)) { 04075 /* Take slave out of the conference */ 04076 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel); 04077 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL); 04078 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL); 04079 master->slaves[x]->master = NULL; 04080 master->slaves[x] = NULL; 04081 } else 04082 hasslaves = 1; 04083 } 04084 if (!hasslaves) 04085 master->inconference = 0; 04086 } 04087 if (!slave) { 04088 if (master->master) { 04089 /* Take master out of the conference */ 04090 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL); 04091 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL); 04092 hasslaves = 0; 04093 for (x = 0; x < MAX_SLAVES; x++) { 04094 if (master->master->slaves[x] == master) 04095 master->master->slaves[x] = NULL; 04096 else if (master->master->slaves[x]) 04097 hasslaves = 1; 04098 } 04099 if (!hasslaves) 04100 master->master->inconference = 0; 04101 } 04102 master->master = NULL; 04103 } 04104 update_conf(master); 04105 if (needlock) { 04106 if (slave) 04107 ast_mutex_unlock(&slave->lock); 04108 ast_mutex_unlock(&master->lock); 04109 } 04110 }
static int dahdi_wait_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition at line 313 of file chan_dahdi.c.
Referenced by flash_exec(), and ss_thread().
00314 { 00315 int i, j = 0; 00316 i = DAHDI_IOMUX_SIGEVENT; 00317 if (ioctl(fd, DAHDI_IOMUX, &i) == -1) 00318 return -1; 00319 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) 00320 return -1; 00321 return j; 00322 }
static int dahdi_wink | ( | struct dahdi_pvt * | p, | |
int | idx | |||
) | [static] |
Definition at line 6537 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by ss_thread().
06538 { 06539 int j; 06540 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK); 06541 for (;;) 06542 { 06543 /* set bits of interest */ 06544 j = DAHDI_IOMUX_SIGEVENT; 06545 /* wait for some happening */ 06546 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1); 06547 /* exit loop if we have it */ 06548 if (j & DAHDI_IOMUX_SIGEVENT) break; 06549 } 06550 /* get the event info */ 06551 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1); 06552 return 0; 06553 }
static int dahdi_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 6014 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.
06015 { 06016 struct dahdi_pvt *p = ast->tech_pvt; 06017 int res; 06018 int idx; 06019 idx = dahdi_get_index(ast, p, 0); 06020 if (idx < 0) { 06021 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name); 06022 return -1; 06023 } 06024 06025 #if 0 06026 #ifdef HAVE_PRI 06027 ast_mutex_lock(&p->lock); 06028 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { 06029 if (p->pri->pri) { 06030 if (!pri_grab(p, p->pri)) { 06031 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06032 pri_rel(p->pri); 06033 } else 06034 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06035 } 06036 p->proceeding=1; 06037 } 06038 ast_mutex_unlock(&p->lock); 06039 #endif 06040 #endif 06041 /* Write a frame of (presumably voice) data */ 06042 if (frame->frametype != AST_FRAME_VOICE) { 06043 if (frame->frametype != AST_FRAME_IMAGE) 06044 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); 06045 return 0; 06046 } 06047 if ((frame->subclass != AST_FORMAT_SLINEAR) && 06048 (frame->subclass != AST_FORMAT_ULAW) && 06049 (frame->subclass != AST_FORMAT_ALAW)) { 06050 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass); 06051 return -1; 06052 } 06053 if (p->dialing) { 06054 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name); 06055 return 0; 06056 } 06057 if (!p->owner) { 06058 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name); 06059 return 0; 06060 } 06061 if (p->cidspill) { 06062 ast_debug(1, "Dropping frame since I've still got a callerid spill\n"); 06063 return 0; 06064 } 06065 /* Return if it's not valid data */ 06066 if (!frame->data.ptr || !frame->datalen) 06067 return 0; 06068 06069 if (frame->subclass == AST_FORMAT_SLINEAR) { 06070 if (!p->subs[idx].linear) { 06071 p->subs[idx].linear = 1; 06072 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 06073 if (res) 06074 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel); 06075 } 06076 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1); 06077 } else { 06078 /* x-law already */ 06079 if (p->subs[idx].linear) { 06080 p->subs[idx].linear = 0; 06081 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 06082 if (res) 06083 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel); 06084 } 06085 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0); 06086 } 06087 if (res < 0) { 06088 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 06089 return -1; 06090 } 06091 return 0; 06092 }
static void destroy_all_channels | ( | void | ) | [static] |
Definition at line 3238 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().
03239 { 03240 int x; 03241 struct dahdi_pvt *p, *pl; 03242 03243 while (num_restart_pending) { 03244 usleep(1); 03245 } 03246 03247 ast_mutex_lock(&iflock); 03248 /* Destroy all the interfaces and free their memory */ 03249 p = iflist; 03250 while (p) { 03251 /* Free any callerid */ 03252 if (p->cidspill) 03253 ast_free(p->cidspill); 03254 pl = p; 03255 p = p->next; 03256 x = pl->channel; 03257 /* Free associated memory */ 03258 if (pl) 03259 destroy_dahdi_pvt(&pl); 03260 if (option_verbose > 2) 03261 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x); 03262 } 03263 iflist = NULL; 03264 ifcount = 0; 03265 ast_mutex_unlock(&iflock); 03266 }
Definition at line 3188 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().
03189 { 03190 int owned = 0; 03191 int i = 0; 03192 03193 if (!now) { 03194 if (cur->owner) { 03195 owned = 1; 03196 } 03197 03198 for (i = 0; i < 3; i++) { 03199 if (cur->subs[i].owner) { 03200 owned = 1; 03201 } 03202 } 03203 if (!owned) { 03204 if (prev) { 03205 prev->next = cur->next; 03206 if (prev->next) 03207 prev->next->prev = prev; 03208 else 03209 ifend = prev; 03210 } else { 03211 iflist = cur->next; 03212 if (iflist) 03213 iflist->prev = NULL; 03214 else 03215 ifend = NULL; 03216 } 03217 destroy_dahdi_pvt(&cur); 03218 } 03219 } else { 03220 if (prev) { 03221 prev->next = cur->next; 03222 if (prev->next) 03223 prev->next->prev = prev; 03224 else 03225 ifend = prev; 03226 } else { 03227 iflist = cur->next; 03228 if (iflist) 03229 iflist->prev = NULL; 03230 else 03231 ifend = NULL; 03232 } 03233 destroy_dahdi_pvt(&cur); 03234 } 03235 return 0; 03236 }
static void destroy_dahdi_pvt | ( | struct dahdi_pvt ** | pvt | ) | [static] |
Definition at line 3165 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().
03166 { 03167 struct dahdi_pvt *p = *pvt; 03168 /* Remove channel from the list */ 03169 if (p->prev) 03170 p->prev->next = p->next; 03171 if (p->next) 03172 p->next->prev = p->prev; 03173 if (p->use_smdi) 03174 ast_smdi_interface_unref(p->smdi_iface); 03175 if (p->mwi_event_sub) 03176 ast_event_unsubscribe(p->mwi_event_sub); 03177 if (p->vars) { 03178 ast_variables_destroy(p->vars); 03179 } 03180 ast_mutex_destroy(&p->lock); 03181 dahdi_close_sub(p, SUB_REAL); 03182 if (p->owner) 03183 p->owner->tech_pvt = NULL; 03184 free(p); 03185 *pvt = NULL; 03186 }
static char* dialplan2str | ( | int | dialplan | ) | [static] |
Definition at line 1762 of file chan_dahdi.c.
Referenced by dahdi_call(), and mkintf().
01763 { 01764 if (dialplan == -1 || dialplan == -2) { 01765 return("Dynamically set dialplan in ISDN"); 01766 } 01767 return (pri_plan2str(dialplan)); 01768 }
static int digit_to_dtmfindex | ( | char | digit | ) | [static] |
Definition at line 1592 of file chan_dahdi.c.
Referenced by dahdi_digit_begin().
01593 { 01594 if (isdigit(digit)) 01595 return DAHDI_TONE_DTMF_BASE + (digit - '0'); 01596 else if (digit >= 'A' && digit <= 'D') 01597 return DAHDI_TONE_DTMF_A + (digit - 'A'); 01598 else if (digit >= 'a' && digit <= 'd') 01599 return DAHDI_TONE_DTMF_A + (digit - 'a'); 01600 else if (digit == '*') 01601 return DAHDI_TONE_DTMF_s; 01602 else if (digit == '#') 01603 return DAHDI_TONE_DTMF_p; 01604 else 01605 return -1; 01606 }
static void disable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4135 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().
04136 { 04137 int val; 04138 04139 p->ignoredtmf = 1; 04140 04141 val = 0; 04142 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 04143 04144 if (!p->hardwaredtmf && p->dsp) { 04145 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT; 04146 ast_dsp_set_features(p->dsp, p->dsp_features); 04147 } 04148 }
static void* do_idle_thread | ( | void * | vchan | ) | [static] |
Definition at line 10755 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().
10756 { 10757 struct ast_channel *chan = vchan; 10758 struct dahdi_pvt *pvt = chan->tech_pvt; 10759 struct ast_frame *f; 10760 char ex[80]; 10761 /* Wait up to 30 seconds for an answer */ 10762 int newms, ms = 30000; 10763 ast_verb(3, "Initiating idle call on channel %s\n", chan->name); 10764 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial); 10765 if (ast_call(chan, ex, 0)) { 10766 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex); 10767 ast_hangup(chan); 10768 return NULL; 10769 } 10770 while ((newms = ast_waitfor(chan, ms)) > 0) { 10771 f = ast_read(chan); 10772 if (!f) { 10773 /* Got hangup */ 10774 break; 10775 } 10776 if (f->frametype == AST_FRAME_CONTROL) { 10777 switch (f->subclass) { 10778 case AST_CONTROL_ANSWER: 10779 /* Launch the PBX */ 10780 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten)); 10781 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context)); 10782 chan->priority = 1; 10783 ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context); 10784 ast_pbx_run(chan); 10785 /* It's already hungup, return immediately */ 10786 return NULL; 10787 case AST_CONTROL_BUSY: 10788 ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name); 10789 break; 10790 case AST_CONTROL_CONGESTION: 10791 ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name); 10792 break; 10793 }; 10794 } 10795 ast_frfree(f); 10796 ms = newms; 10797 } 10798 /* Hangup the channel since nothing happend */ 10799 ast_hangup(chan); 10800 return NULL; 10801 }
static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 8394 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().
08395 { 08396 int count, res, res2, spoint, pollres=0; 08397 struct dahdi_pvt *i; 08398 struct dahdi_pvt *last = NULL; 08399 struct dahdi_pvt *doomed; 08400 time_t thispass = 0, lastpass = 0; 08401 int found; 08402 char buf[1024]; 08403 struct pollfd *pfds=NULL; 08404 int lastalloc = -1; 08405 /* This thread monitors all the frame relay interfaces which are not yet in use 08406 (and thus do not have a separate thread) indefinitely */ 08407 /* From here on out, we die whenever asked */ 08408 #if 0 08409 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 08410 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 08411 return NULL; 08412 } 08413 ast_debug(1, "Monitor starting...\n"); 08414 #endif 08415 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08416 08417 for (;;) { 08418 /* Lock the interface list */ 08419 ast_mutex_lock(&iflock); 08420 if (!pfds || (lastalloc != ifcount)) { 08421 if (pfds) { 08422 ast_free(pfds); 08423 pfds = NULL; 08424 } 08425 if (ifcount) { 08426 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) { 08427 ast_mutex_unlock(&iflock); 08428 return NULL; 08429 } 08430 } 08431 lastalloc = ifcount; 08432 } 08433 /* Build the stuff we're going to poll on, that is the socket of every 08434 dahdi_pvt that does not have an associated owner channel */ 08435 count = 0; 08436 i = iflist; 08437 while (i) { 08438 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) { 08439 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive && !i->mwisendactive) { 08440 /* This needs to be watched, as it lacks an owner */ 08441 pfds[count].fd = i->subs[SUB_REAL].dfd; 08442 pfds[count].events = POLLPRI; 08443 pfds[count].revents = 0; 08444 /* If we are monitoring for VMWI or sending CID, we need to 08445 read from the channel as well */ 08446 if (i->cidspill || i->mwimonitor_fsk) 08447 pfds[count].events |= POLLIN; 08448 count++; 08449 } 08450 } 08451 i = i->next; 08452 } 08453 /* Okay, now that we know what to do, release the interface lock */ 08454 ast_mutex_unlock(&iflock); 08455 08456 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 08457 pthread_testcancel(); 08458 /* Wait at least a second for something to happen */ 08459 res = poll(pfds, count, 1000); 08460 pthread_testcancel(); 08461 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08462 08463 /* Okay, poll has finished. Let's see what happened. */ 08464 if (res < 0) { 08465 if ((errno != EAGAIN) && (errno != EINTR)) 08466 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno)); 08467 continue; 08468 } 08469 /* Alright, lock the interface list again, and let's look and see what has 08470 happened */ 08471 ast_mutex_lock(&iflock); 08472 found = 0; 08473 spoint = 0; 08474 lastpass = thispass; 08475 thispass = time(NULL); 08476 i = iflist; 08477 doomed = NULL; 08478 for (i = iflist;; i = i->next) { 08479 if (doomed) { 08480 int res; 08481 res = dahdi_destroy_channel_bynum(doomed->channel); 08482 if (!res) { 08483 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n"); 08484 } 08485 doomed = NULL; 08486 } 08487 if (!i) { 08488 break; 08489 } 08490 08491 if (thispass != lastpass) { 08492 if (!found && ((i == last) || ((i == iflist) && !last))) { 08493 last = i; 08494 if (last) { 08495 if (!last->mwisendactive && last->sig & __DAHDI_SIG_FXO) { 08496 res = has_voicemail(last); 08497 if (last->msgstate != res) { 08498 08499 /* This channel has a new voicemail state, 08500 * initiate a thread to send an MWI message 08501 */ 08502 pthread_attr_t attr; 08503 pthread_t threadid; 08504 struct mwi_thread_data *mtd; 08505 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res); 08506 if (res2) { 08507 /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */ 08508 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno)); 08509 } 08510 pthread_attr_init(&attr); 08511 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 08512 if ((mtd = ast_calloc(1, sizeof(*mtd)))) { 08513 last->msgstate = res; 08514 mtd->pvt = last; 08515 last->mwisendactive = 1; 08516 if (ast_pthread_create_background(&threadid, &attr, mwi_send_thread, mtd)) { 08517 ast_log(LOG_WARNING, "Unable to start mwi send thread on channel %d\n", last->channel); 08518 ast_free(mtd); 08519 last->mwisendactive = 0; 08520 } 08521 } 08522 found ++; 08523 } 08524 } 08525 last = last->next; 08526 } 08527 } 08528 } 08529 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) { 08530 if (i->radio && !i->owner) 08531 { 08532 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 08533 if (res) 08534 { 08535 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel); 08536 /* Don't hold iflock while handling init events */ 08537 ast_mutex_unlock(&iflock); 08538 doomed = handle_init_event(i, res); 08539 ast_mutex_lock(&iflock); 08540 } 08541 continue; 08542 } 08543 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint); 08544 if (pollres & POLLIN) { 08545 if (i->owner || i->subs[SUB_REAL].owner) { 08546 #ifdef HAVE_PRI 08547 if (!i->pri) 08548 #endif 08549 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd); 08550 continue; 08551 } 08552 if (!i->cidspill && !i->mwimonitor_fsk) { 08553 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd); 08554 continue; 08555 } 08556 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf)); 08557 if (res > 0) { 08558 if (i->mwimonitor_fsk) { 08559 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) { 08560 pthread_attr_t attr; 08561 pthread_t threadid; 08562 struct mwi_thread_data *mtd; 08563 08564 pthread_attr_init(&attr); 08565 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 08566 08567 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel); 08568 if ((mtd = ast_calloc(1, sizeof(*mtd)))) { 08569 mtd->pvt = i; 08570 memcpy(mtd->buf, buf, res); 08571 mtd->len = res; 08572 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) { 08573 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel); 08574 ast_free(mtd); 08575 } 08576 i->mwimonitoractive = 1; 08577 } 08578 } 08579 } 08580 } else { 08581 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno)); 08582 } 08583 } 08584 if (pollres & POLLPRI) { 08585 if (i->owner || i->subs[SUB_REAL].owner) { 08586 #ifdef HAVE_PRI 08587 if (!i->pri) 08588 #endif 08589 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd); 08590 continue; 08591 } 08592 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 08593 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel); 08594 /* Don't hold iflock while handling init events */ 08595 ast_mutex_unlock(&iflock); 08596 doomed = handle_init_event(i, res); 08597 ast_mutex_lock(&iflock); 08598 } 08599 } 08600 } 08601 ast_mutex_unlock(&iflock); 08602 } 08603 /* Never reached */ 08604 return NULL; 08605 08606 }
static void enable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4150 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().
04151 { 04152 int val; 04153 04154 if (p->channel == CHAN_PSEUDO) 04155 return; 04156 04157 p->ignoredtmf = 0; 04158 04159 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 04160 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 04161 04162 if (!p->hardwaredtmf && p->dsp) { 04163 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT; 04164 ast_dsp_set_features(p->dsp, p->dsp_features); 04165 } 04166 }
static char* event2str | ( | int | event | ) | [static] |
Definition at line 1752 of file chan_dahdi.c.
References ARRAY_LEN, and buf.
Referenced by __dahdi_exception(), dahdi_handle_event(), mwi_thread(), and ss_thread().
01753 { 01754 static char buf[256]; 01755 if ((event < (ARRAY_LEN(events))) && (event > -1)) 01756 return events[event]; 01757 sprintf(buf, "Event %d", event); /* safe */ 01758 return buf; 01759 }
static void fill_rxgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2122 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_rxgain().
02123 { 02124 int j; 02125 int k; 02126 float linear_gain = pow(10.0, gain / 20.0); 02127 02128 switch (law) { 02129 case DAHDI_LAW_ALAW: 02130 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 02131 if (gain) { 02132 k = (int) (((float) AST_ALAW(j)) * linear_gain); 02133 if (k > 32767) k = 32767; 02134 if (k < -32767) k = -32767; 02135 g->rxgain[j] = AST_LIN2A(k); 02136 } else { 02137 g->rxgain[j] = j; 02138 } 02139 } 02140 break; 02141 case DAHDI_LAW_MULAW: 02142 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 02143 if (gain) { 02144 k = (int) (((float) AST_MULAW(j)) * linear_gain); 02145 if (k > 32767) k = 32767; 02146 if (k < -32767) k = -32767; 02147 g->rxgain[j] = AST_LIN2MU(k); 02148 } else { 02149 g->rxgain[j] = j; 02150 } 02151 } 02152 break; 02153 } 02154 }
static void fill_txgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2088 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_txgain().
02089 { 02090 int j; 02091 int k; 02092 float linear_gain = pow(10.0, gain / 20.0); 02093 02094 switch (law) { 02095 case DAHDI_LAW_ALAW: 02096 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 02097 if (gain) { 02098 k = (int) (((float) AST_ALAW(j)) * linear_gain); 02099 if (k > 32767) k = 32767; 02100 if (k < -32767) k = -32767; 02101 g->txgain[j] = AST_LIN2A(k); 02102 } else { 02103 g->txgain[j] = j; 02104 } 02105 } 02106 break; 02107 case DAHDI_LAW_MULAW: 02108 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 02109 if (gain) { 02110 k = (int) (((float) AST_MULAW(j)) * linear_gain); 02111 if (k > 32767) k = 32767; 02112 if (k < -32767) k = -32767; 02113 g->txgain[j] = AST_LIN2MU(k); 02114 } else { 02115 g->txgain[j] = j; 02116 } 02117 } 02118 break; 02119 } 02120 }
static struct dahdi_pvt* find_channel | ( | int | channel | ) | [static] |
Definition at line 13477 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().
13478 { 13479 struct dahdi_pvt *p = iflist; 13480 while (p) { 13481 if (p->channel == channel) { 13482 break; 13483 } 13484 p = p->next; 13485 } 13486 return p; 13487 }
static int get_alarms | ( | struct dahdi_pvt * | p | ) | [static] |
Checks channel for alarms
p | a channel to check for alarms. |
Definition at line 4595 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().
04596 { 04597 int res; 04598 struct dahdi_spaninfo zi; 04599 struct dahdi_params params; 04600 04601 memset(&zi, 0, sizeof(zi)); 04602 zi.spanno = p->span; 04603 04604 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) { 04605 if (zi.alarms != DAHDI_ALARM_NONE) 04606 return zi.alarms; 04607 } else { 04608 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno)); 04609 return 0; 04610 } 04611 04612 /* No alarms on the span. Check for channel alarms. */ 04613 memset(¶ms, 0, sizeof(params)); 04614 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0) 04615 return params.chan_alarms; 04616 04617 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel); 04618 04619 return DAHDI_ALARM_NONE; 04620 }
static void handle_alarms | ( | struct dahdi_pvt * | p, | |
int | alms | |||
) | [static] |
Definition at line 4688 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().
04689 { 04690 const char *alarm_str = alarm2str(alms); 04691 04692 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); 04693 manager_event(EVENT_FLAG_SYSTEM, "Alarm", 04694 "Alarm: %s\r\n" 04695 "Channel: %d\r\n", 04696 alarm_str, p->channel); 04697 }
static char* handle_dahdi_show_cadences | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 13093 of file chan_dahdi.c.
References ast_cli(), cadences, cidrings, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, COLOR_BLACK, COLOR_GREEN, COLOR_MAGENTA, ast_cli_entry::command, ast_cli_args::fd, num_cadence, term_color(), and ast_cli_entry::usage.
13094 { 13095 int i, j; 13096 switch (cmd) { 13097 case CLI_INIT: 13098 e->command = "dahdi show cadences"; 13099 e->usage = 13100 "Usage: dahdi show cadences\n" 13101 " Shows all cadences currently defined\n"; 13102 return NULL; 13103 case CLI_GENERATE: 13104 return NULL; 13105 } 13106 for (i = 0; i < num_cadence; i++) { 13107 char output[1024]; 13108 char tmp[16], tmp2[64]; 13109 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1); 13110 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output)); 13111 13112 for (j = 0; j < 16; j++) { 13113 if (cadences[i].ringcadence[j] == 0) 13114 break; 13115 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]); 13116 if (cidrings[i] * 2 - 1 == j) 13117 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1); 13118 else 13119 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1); 13120 if (j != 0) 13121 strncat(output, ",", sizeof(output) - strlen(output) - 1); 13122 strncat(output, tmp2, sizeof(output) - strlen(output) - 1); 13123 } 13124 ast_cli(a->fd,"%s\n",output); 13125 } 13126 return CLI_SUCCESS; 13127 }
Definition at line 8171 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_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().
08172 { 08173 int res; 08174 pthread_t threadid; 08175 struct ast_channel *chan; 08176 08177 /* Handle an event on a given channel for the monitor thread. */ 08178 08179 switch (event) { 08180 case DAHDI_EVENT_NONE: 08181 case DAHDI_EVENT_BITSCHANGED: 08182 break; 08183 case DAHDI_EVENT_WINKFLASH: 08184 case DAHDI_EVENT_RINGOFFHOOK: 08185 if (i->inalarm) break; 08186 if (i->radio) break; 08187 /* Got a ring/answer. What kind of channel are we? */ 08188 switch (i->sig) { 08189 case SIG_FXOLS: 08190 case SIG_FXOGS: 08191 case SIG_FXOKS: 08192 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08193 if (res && (errno == EBUSY)) 08194 break; 08195 if (i->cidspill) { 08196 /* Cancel VMWI spill */ 08197 ast_free(i->cidspill); 08198 i->cidspill = NULL; 08199 } 08200 if (i->immediate) { 08201 dahdi_enable_ec(i); 08202 /* The channel is immediately up. Start right away */ 08203 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 08204 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0); 08205 if (!chan) { 08206 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel); 08207 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08208 if (res < 0) 08209 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08210 } 08211 } else { 08212 /* Check for callerid, digits, etc */ 08213 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0); 08214 if (chan) { 08215 if (has_voicemail(i)) 08216 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 08217 else 08218 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 08219 if (res < 0) 08220 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel); 08221 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 08222 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08223 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08224 if (res < 0) 08225 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08226 ast_hangup(chan); 08227 } 08228 } else 08229 ast_log(LOG_WARNING, "Unable to create channel\n"); 08230 } 08231 break; 08232 case SIG_FXSLS: 08233 case SIG_FXSGS: 08234 case SIG_FXSKS: 08235 i->ringt = i->ringt_base; 08236 /* Fall through */ 08237 case SIG_EMWINK: 08238 case SIG_FEATD: 08239 case SIG_FEATDMF: 08240 case SIG_FEATDMF_TA: 08241 case SIG_E911: 08242 case SIG_FGC_CAMA: 08243 case SIG_FGC_CAMAMF: 08244 case SIG_FEATB: 08245 case SIG_EM: 08246 case SIG_EM_E1: 08247 case SIG_SFWINK: 08248 case SIG_SF_FEATD: 08249 case SIG_SF_FEATDMF: 08250 case SIG_SF_FEATB: 08251 case SIG_SF: 08252 /* Check for callerid, digits, etc */ 08253 if (i->cid_start == CID_START_POLARITY_IN) { 08254 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 08255 } else { 08256 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0); 08257 } 08258 08259 if (!chan) { 08260 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 08261 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 08262 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08263 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08264 if (res < 0) { 08265 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08266 } 08267 ast_hangup(chan); 08268 } 08269 break; 08270 default: 08271 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 08272 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08273 if (res < 0) 08274 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08275 return NULL; 08276 } 08277 break; 08278 case DAHDI_EVENT_NOALARM: 08279 i->inalarm = 0; 08280 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel); 08281 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 08282 "Channel: %d\r\n", i->channel); 08283 break; 08284 case DAHDI_EVENT_ALARM: 08285 i->inalarm = 1; 08286 res = get_alarms(i); 08287 handle_alarms(i, res); 08288 /* fall thru intentionally */ 08289 case DAHDI_EVENT_ONHOOK: 08290 if (i->radio) 08291 break; 08292 /* Back on hook. Hang up. */ 08293 switch (i->sig) { 08294 case SIG_FXOLS: 08295 case SIG_FXOGS: 08296 case SIG_FEATD: 08297 case SIG_FEATDMF: 08298 case SIG_FEATDMF_TA: 08299 case SIG_E911: 08300 case SIG_FGC_CAMA: 08301 case SIG_FGC_CAMAMF: 08302 case SIG_FEATB: 08303 case SIG_EM: 08304 case SIG_EM_E1: 08305 case SIG_EMWINK: 08306 case SIG_SF_FEATD: 08307 case SIG_SF_FEATDMF: 08308 case SIG_SF_FEATB: 08309 case SIG_SF: 08310 case SIG_SFWINK: 08311 case SIG_FXSLS: 08312 case SIG_FXSGS: 08313 case SIG_FXSKS: 08314 case SIG_GR303FXSKS: 08315 dahdi_disable_ec(i); 08316 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08317 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08318 break; 08319 case SIG_GR303FXOKS: 08320 case SIG_FXOKS: 08321 dahdi_disable_ec(i); 08322 /* Diddle the battery for the zhone */ 08323 #ifdef ZHONE_HACK 08324 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08325 usleep(1); 08326 #endif 08327 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08328 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08329 break; 08330 case SIG_PRI: 08331 case SIG_SS7: 08332 case SIG_BRI: 08333 case SIG_BRI_PTMP: 08334 dahdi_disable_ec(i); 08335 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08336 break; 08337 default: 08338 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 08339 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08340 return NULL; 08341 } 08342 break; 08343 case DAHDI_EVENT_POLARITY: 08344 switch (i->sig) { 08345 case SIG_FXSLS: 08346 case SIG_FXSKS: 08347 case SIG_FXSGS: 08348 /* We have already got a PR before the channel was 08349 created, but it wasn't handled. We need polarity 08350 to be REV for remote hangup detection to work. 08351 At least in Spain */ 08352 if (i->hanguponpolarityswitch) 08353 i->polarity = POLARITY_REV; 08354 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) { 08355 i->polarity = POLARITY_REV; 08356 ast_verb(2, "Starting post polarity " 08357 "CID detection on channel %d\n", 08358 i->channel); 08359 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 08360 if (!chan) { 08361 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 08362 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 08363 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08364 } 08365 } 08366 break; 08367 default: 08368 ast_log(LOG_WARNING, "handle_init_event detected " 08369 "polarity reversal on non-FXO (SIG_FXS) " 08370 "interface %d\n", i->channel); 08371 } 08372 break; 08373 case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */ 08374 ast_log(LOG_NOTICE, 08375 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 08376 i->channel); 08377 return i; 08378 case DAHDI_EVENT_NEONMWI_ACTIVE: 08379 if (i->mwimonitor_neon) { 08380 notify_message(i->mailbox, 1); 08381 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox); 08382 } 08383 break; 08384 case DAHDI_EVENT_NEONMWI_INACTIVE: 08385 if (i->mwimonitor_neon) { 08386 notify_message(i->mailbox, 0); 08387 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox); 08388 } 08389 break; 08390 } 08391 return NULL; 08392 }
static char* handle_pri_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12286 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.
12287 { 12288 int span; 12289 int x; 12290 switch (cmd) { 12291 case CLI_INIT: 12292 e->command = "pri debug span"; 12293 e->usage = 12294 "Usage: pri debug span <span>\n" 12295 " Enables debugging on a given PRI span\n"; 12296 return NULL; 12297 case CLI_GENERATE: 12298 return complete_span_4(a->line, a->word, a->pos, a->n); 12299 } 12300 if (a->argc < 4) { 12301 return CLI_SHOWUSAGE; 12302 } 12303 span = atoi(a->argv[3]); 12304 if ((span < 1) || (span > NUM_SPANS)) { 12305 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 12306 return CLI_SUCCESS; 12307 } 12308 if (!pris[span-1].pri) { 12309 ast_cli(a->fd, "No PRI running on span %d\n", span); 12310 return CLI_SUCCESS; 12311 } 12312 for (x = 0; x < NUM_DCHANS; x++) { 12313 if (pris[span-1].dchans[x]) 12314 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 12315 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 12316 PRI_DEBUG_Q921_STATE); 12317 } 12318 ast_cli(a->fd, "Enabled debugging on span %d\n", span); 12319 return CLI_SUCCESS; 12320 }
static char* handle_pri_no_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12324 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.
12325 { 12326 int span; 12327 int x; 12328 switch (cmd) { 12329 case CLI_INIT: 12330 e->command = "pri no debug span"; 12331 e->usage = 12332 "Usage: pri no debug span <span>\n" 12333 " Disables debugging on a given PRI span\n"; 12334 return NULL; 12335 case CLI_GENERATE: 12336 return complete_span_5(a->line, a->word, a->pos, a->n); 12337 } 12338 if (a->argc < 5) 12339 return CLI_SHOWUSAGE; 12340 12341 span = atoi(a->argv[4]); 12342 if ((span < 1) || (span > NUM_SPANS)) { 12343 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS); 12344 return CLI_SUCCESS; 12345 } 12346 if (!pris[span-1].pri) { 12347 ast_cli(a->fd, "No PRI running on span %d\n", span); 12348 return CLI_SUCCESS; 12349 } 12350 for (x = 0; x < NUM_DCHANS; x++) { 12351 if (pris[span-1].dchans[x]) 12352 pri_set_debug(pris[span-1].dchans[x], 0); 12353 } 12354 ast_cli(a->fd, "Disabled debugging on span %d\n", span); 12355 return CLI_SUCCESS; 12356 }
static char* handle_pri_really_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12358 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.
12359 { 12360 int span; 12361 int x; 12362 switch (cmd) { 12363 case CLI_INIT: 12364 e->command = "pri intensive debug span"; 12365 e->usage = 12366 "Usage: pri intensive debug span <span>\n" 12367 " Enables debugging down to the Q.921 level\n"; 12368 return NULL; 12369 case CLI_GENERATE: 12370 return complete_span_5(a->line, a->word, a->pos, a->n); 12371 } 12372 12373 if (a->argc < 5) 12374 return CLI_SHOWUSAGE; 12375 span = atoi(a->argv[4]); 12376 if ((span < 1) || (span > NUM_SPANS)) { 12377 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS); 12378 return CLI_SUCCESS; 12379 } 12380 if (!pris[span-1].pri) { 12381 ast_cli(a->fd, "No PRI running on span %d\n", span); 12382 return CLI_SUCCESS; 12383 } 12384 for (x = 0; x < NUM_DCHANS; x++) { 12385 if (pris[span-1].dchans[x]) 12386 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 12387 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 12388 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE); 12389 } 12390 ast_cli(a->fd, "Enabled EXTENSIVE debugging on span %d\n", span); 12391 return CLI_SUCCESS; 12392 }
static char* handle_pri_set_debug_file | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12250 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.
12251 { 12252 int myfd; 12253 switch (cmd) { 12254 case CLI_INIT: 12255 e->command = "pri set debug file"; 12256 e->usage = "Usage: pri set debug file [output-file]\n" 12257 " Sends PRI debug output to the specified output file\n"; 12258 return NULL; 12259 case CLI_GENERATE: 12260 return NULL; 12261 } 12262 if (a->argc < 5) 12263 return CLI_SHOWUSAGE; 12264 12265 if (ast_strlen_zero(a->argv[4])) 12266 return CLI_SHOWUSAGE; 12267 12268 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE); 12269 if (myfd < 0) { 12270 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]); 12271 return CLI_SUCCESS; 12272 } 12273 12274 ast_mutex_lock(&pridebugfdlock); 12275 12276 if (pridebugfd >= 0) 12277 close(pridebugfd); 12278 12279 pridebugfd = myfd; 12280 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename)); 12281 ast_mutex_unlock(&pridebugfdlock); 12282 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]); 12283 return CLI_SUCCESS; 12284 }
static char* handle_pri_show_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12498 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.
12499 { 12500 int x; 12501 int span; 12502 int count=0; 12503 int debug=0; 12504 12505 switch (cmd) { 12506 case CLI_INIT: 12507 e->command = "pri show debug"; 12508 e->usage = 12509 "Usage: pri show debug\n" 12510 " Show the debug state of pri spans\n"; 12511 return NULL; 12512 case CLI_GENERATE: 12513 return NULL; 12514 } 12515 12516 for (span = 0; span < NUM_SPANS; span++) { 12517 if (pris[span].pri) { 12518 for (x = 0; x < NUM_DCHANS; x++) { 12519 debug = 0; 12520 if (pris[span].dchans[x]) { 12521 debug = pri_get_debug(pris[span].dchans[x]); 12522 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" ); 12523 count++; 12524 } 12525 } 12526 } 12527 12528 } 12529 ast_mutex_lock(&pridebugfdlock); 12530 if (pridebugfd >= 0) 12531 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename); 12532 ast_mutex_unlock(&pridebugfdlock); 12533 12534 if (!count) 12535 ast_cli(a->fd, "No debug set or no PRI running\n"); 12536 return CLI_SUCCESS; 12537 }
static char* handle_pri_show_span | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12448 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.
12449 { 12450 int span; 12451 int x; 12452 char status[256]; 12453 switch (cmd) { 12454 case CLI_INIT: 12455 e->command = "pri show span"; 12456 e->usage = 12457 "Usage: pri show span <span>\n" 12458 " Displays PRI Information on a given PRI span\n"; 12459 return NULL; 12460 case CLI_GENERATE: 12461 return complete_span_4(a->line, a->word, a->pos, a->n); 12462 } 12463 12464 if (a->argc < 4) 12465 return CLI_SHOWUSAGE; 12466 span = atoi(a->argv[3]); 12467 if ((span < 1) || (span > NUM_SPANS)) { 12468 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS); 12469 return CLI_SUCCESS; 12470 } 12471 if (!pris[span-1].pri) { 12472 ast_cli(a->fd, "No PRI running on span %d\n", span); 12473 return CLI_SUCCESS; 12474 } 12475 for (x = 0; x < NUM_DCHANS; x++) { 12476 if (pris[span-1].dchannels[x]) { 12477 #ifdef PRI_DUMP_INFO_STR 12478 char *info_str = NULL; 12479 #endif 12480 ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]); 12481 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri); 12482 ast_cli(a->fd, "Status: %s\n", status); 12483 #ifdef PRI_DUMP_INFO_STR 12484 info_str = pri_dump_info_str(pris[span-1].pri); 12485 if (info_str) { 12486 ast_cli(a->fd, "%s", info_str); 12487 ast_free(info_str); 12488 } 12489 #else 12490 pri_dump_info(pris[span-1].pri); 12491 #endif 12492 ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No"); 12493 } 12494 } 12495 return CLI_SUCCESS; 12496 }
static char* handle_pri_show_spans | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12415 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.
12416 { 12417 int span; 12418 int x; 12419 char status[256]; 12420 12421 switch (cmd) { 12422 case CLI_INIT: 12423 e->command = "pri show spans"; 12424 e->usage = 12425 "Usage: pri show spans\n" 12426 " Displays PRI Information\n"; 12427 return NULL; 12428 case CLI_GENERATE: 12429 return NULL; 12430 } 12431 12432 if (a->argc != 3) 12433 return CLI_SHOWUSAGE; 12434 12435 for (span = 0; span < NUM_SPANS; span++) { 12436 if (pris[span].pri) { 12437 for (x = 0; x < NUM_DCHANS; x++) { 12438 if (pris[span].dchannels[x]) { 12439 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri); 12440 ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status); 12441 } 12442 } 12443 } 12444 } 12445 return CLI_SUCCESS; 12446 }
static char* handle_pri_unset_debug_file | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12229 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.
12230 { 12231 switch (cmd) { 12232 case CLI_INIT: 12233 e->command = "pri unset debug file"; 12234 e->usage = "Usage: pri unset debug file\n" 12235 " Stop sending debug output to the previously \n" 12236 " specified file\n"; 12237 return NULL; 12238 case CLI_GENERATE: 12239 return NULL; 12240 } 12241 /* Assume it is unset */ 12242 ast_mutex_lock(&pridebugfdlock); 12243 close(pridebugfd); 12244 pridebugfd = -1; 12245 ast_cli(a->fd, "PRI debug output to file disabled\n"); 12246 ast_mutex_unlock(&pridebugfdlock); 12247 return CLI_SUCCESS; 12248 }
static char* handle_pri_version | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 12539 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.
12540 { 12541 switch (cmd) { 12542 case CLI_INIT: 12543 e->command = "pri show version"; 12544 e->usage = 12545 "Usage: pri show version\n" 12546 "Show libpri version information\n"; 12547 return NULL; 12548 case CLI_GENERATE: 12549 return NULL; 12550 } 12551 12552 ast_cli(a->fd, "libpri version: %s\n", pri_get_version()); 12553 12554 return CLI_SUCCESS; 12555 }
static int has_voicemail | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2362 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().
02363 { 02364 int new_msgs; 02365 struct ast_event *event; 02366 char *mailbox, *context; 02367 02368 mailbox = context = ast_strdupa(p->mailbox); 02369 strsep(&context, "@"); 02370 if (ast_strlen_zero(context)) 02371 context = "default"; 02372 02373 event = ast_event_get_cached(AST_EVENT_MWI, 02374 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 02375 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 02376 AST_EVENT_IE_END); 02377 02378 if (event) { 02379 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 02380 ast_event_destroy(event); 02381 } else 02382 new_msgs = ast_app_has_voicemail(p->mailbox, NULL); 02383 02384 return new_msgs; 02385 }
static int isourconf | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c | |||
) | [static] |
Definition at line 1877 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::confno, and dahdi_subchannel::curconf.
Referenced by conf_del().
01878 { 01879 /* If they're listening to our channel, they're ours */ 01880 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON)) 01881 return 1; 01882 /* If they're a talker on our (allocated) conference, they're ours */ 01883 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER)) 01884 return 1; 01885 return 0; 01886 }
Definition at line 1907 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().
01908 { 01909 int x; 01910 int useslavenative; 01911 struct dahdi_pvt *slave = NULL; 01912 /* Start out optimistic */ 01913 useslavenative = 1; 01914 /* Update conference state in a stateless fashion */ 01915 for (x = 0; x < 3; x++) { 01916 /* Any three-way calling makes slave native mode *definitely* out 01917 of the question */ 01918 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) 01919 useslavenative = 0; 01920 } 01921 /* If we don't have any 3-way calls, check to see if we have 01922 precisely one slave */ 01923 if (useslavenative) { 01924 for (x = 0; x < MAX_SLAVES; x++) { 01925 if (p->slaves[x]) { 01926 if (slave) { 01927 /* Whoops already have a slave! No 01928 slave native and stop right away */ 01929 slave = NULL; 01930 useslavenative = 0; 01931 break; 01932 } else { 01933 /* We have one slave so far */ 01934 slave = p->slaves[x]; 01935 } 01936 } 01937 } 01938 } 01939 /* If no slave, slave native definitely out */ 01940 if (!slave) 01941 useslavenative = 0; 01942 else if (slave->law != p->law) { 01943 useslavenative = 0; 01944 slave = NULL; 01945 } 01946 if (out) 01947 *out = slave; 01948 return useslavenative; 01949 }
static int load_module | ( | void | ) | [static] |
Definition at line 15434 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().
15435 { 15436 int res; 15437 #if defined(HAVE_PRI) || defined(HAVE_SS7) 15438 int y, i; 15439 #endif 15440 15441 #ifdef HAVE_PRI 15442 memset(pris, 0, sizeof(pris)); 15443 for (y = 0; y < NUM_SPANS; y++) { 15444 ast_mutex_init(&pris[y].lock); 15445 pris[y].offset = -1; 15446 pris[y].master = AST_PTHREADT_NULL; 15447 for (i = 0; i < NUM_DCHANS; i++) 15448 pris[y].fds[i] = -1; 15449 } 15450 pri_set_error(dahdi_pri_error); 15451 pri_set_message(dahdi_pri_message); 15452 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec, 15453 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip); 15454 #endif 15455 #ifdef HAVE_SS7 15456 memset(linksets, 0, sizeof(linksets)); 15457 for (y = 0; y < NUM_SPANS; y++) { 15458 ast_mutex_init(&linksets[y].lock); 15459 linksets[y].master = AST_PTHREADT_NULL; 15460 for (i = 0; i < NUM_DCHANS; i++) 15461 linksets[y].fds[i] = -1; 15462 } 15463 ss7_set_error(dahdi_ss7_error); 15464 ss7_set_message(dahdi_ss7_message); 15465 #endif /* HAVE_SS7 */ 15466 res = setup_dahdi(0); 15467 /* Make sure we can register our DAHDI channel type */ 15468 if (res) 15469 return AST_MODULE_LOAD_DECLINE; 15470 if (ast_channel_register(&dahdi_tech)) { 15471 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n"); 15472 __unload_module(); 15473 return AST_MODULE_LOAD_FAILURE; 15474 } 15475 #ifdef HAVE_PRI 15476 ast_string_field_init(&inuse, 16); 15477 ast_string_field_set(&inuse, name, "GR-303InUse"); 15478 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 15479 #endif 15480 #ifdef HAVE_SS7 15481 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli)); 15482 #endif 15483 15484 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli)); 15485 15486 memset(round_robin, 0, sizeof(round_robin)); 15487 ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" ); 15488 ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" ); 15489 ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" ); 15490 ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" ); 15491 ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" ); 15492 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels"); 15493 ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)"); 15494 15495 ast_cond_init(&mwi_thread_complete, NULL); 15496 ast_cond_init(&ss_thread_complete, NULL); 15497 15498 return res; 15499 }
static struct dahdi_pvt* mkintf | ( | int | channel, | |
const struct dahdi_chan_conf * | conf, | |||
struct dahdi_pri * | pri, | |||
int | reloading | |||
) | [static] |
Definition at line 8792 of file chan_dahdi.c.
References ast_calloc, ast_copy_string(), ast_log(), ast_mutex_init(), ast_strlen_zero(), dahdi_pvt::call, dahdi_chan_conf::chan, CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pri::crvend, dahdi_pri::crvs, dahdi_open(), destroy_dahdi_pvt(), dahdi_subchannel::dfd, 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_pvt::law, dahdi_pri::localdialplan, dahdi_pri::localprefix, LOG_ERROR, dahdi_pvt::logicalspan, 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_pvt::pri, dahdi_chan_conf::pri, pri_resolve_span(), dahdi_pvt::priindication_oob, dahdi_pri::prilogicalspan, dahdi_pvt::prioffset, 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(), dahdi_pvt::span, SUB_REAL, dahdi_pvt::subs, dahdi_pri::switchtype, and dahdi_pri::unknownprefix.
Referenced by build_channels().
08793 { 08794 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */ 08795 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL; 08796 char fn[80]; 08797 struct dahdi_bufferinfo bi; 08798 08799 int res; 08800 int span = 0; 08801 int here = 0; 08802 int x; 08803 struct dahdi_pvt **wlist; 08804 struct dahdi_pvt **wend; 08805 struct dahdi_params p; 08806 08807 wlist = &iflist; 08808 wend = &ifend; 08809 08810 #ifdef HAVE_PRI 08811 if (pri) { 08812 wlist = &pri->crvs; 08813 wend = &pri->crvend; 08814 } 08815 #endif 08816 08817 tmp2 = *wlist; 08818 prev = NULL; 08819 08820 while (tmp2) { 08821 if (!tmp2->destroy) { 08822 if (tmp2->channel == channel) { 08823 tmp = tmp2; 08824 here = 1; 08825 break; 08826 } 08827 if (tmp2->channel > channel) { 08828 break; 08829 } 08830 } 08831 prev = tmp2; 08832 tmp2 = tmp2->next; 08833 } 08834 08835 if (!here && reloading != 1) { 08836 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { 08837 if (tmp) 08838 free(tmp); 08839 return NULL; 08840 } 08841 ast_mutex_init(&tmp->lock); 08842 ifcount++; 08843 for (x = 0; x < 3; x++) 08844 tmp->subs[x].dfd = -1; 08845 tmp->channel = channel; 08846 tmp->priindication_oob = conf->chan.priindication_oob; 08847 } 08848 08849 if (tmp) { 08850 int chan_sig = conf->chan.sig; 08851 if (!here) { 08852 if ((channel != CHAN_PSEUDO) && !pri) { 08853 int count = 0; 08854 snprintf(fn, sizeof(fn), "%d", channel); 08855 /* Open non-blocking */ 08856 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 08857 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 */ 08858 usleep(1); 08859 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 08860 count++; 08861 } 08862 /* Allocate a DAHDI structure */ 08863 if (tmp->subs[SUB_REAL].dfd < 0) { 08864 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); 08865 destroy_dahdi_pvt(&tmp); 08866 return NULL; 08867 } 08868 memset(&p, 0, sizeof(p)); 08869 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 08870 if (res < 0) { 08871 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno)); 08872 destroy_dahdi_pvt(&tmp); 08873 return NULL; 08874 } 08875 if (conf->is_sig_auto) 08876 chan_sig = sigtype_to_signalling(p.sigtype); 08877 if (p.sigtype != (chan_sig & 0x3ffff)) { 08878 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)); 08879 destroy_dahdi_pvt(&tmp); 08880 return NULL; 08881 } 08882 tmp->law = p.curlaw; 08883 tmp->span = p.spanno; 08884 span = p.spanno - 1; 08885 } else { 08886 if (channel == CHAN_PSEUDO) 08887 chan_sig = 0; 08888 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) { 08889 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n"); 08890 return NULL; 08891 } 08892 } 08893 #ifdef HAVE_SS7 08894 if (chan_sig == SIG_SS7) { 08895 struct dahdi_ss7 *ss7; 08896 int clear = 0; 08897 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) { 08898 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 08899 destroy_dahdi_pvt(&tmp); 08900 return NULL; 08901 } 08902 08903 ss7 = ss7_resolve_linkset(cur_linkset); 08904 if (!ss7) { 08905 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset); 08906 destroy_dahdi_pvt(&tmp); 08907 return NULL; 08908 } 08909 if (cur_cicbeginswith < 0) { 08910 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n"); 08911 destroy_dahdi_pvt(&tmp); 08912 return NULL; 08913 } 08914 08915 tmp->cic = cur_cicbeginswith++; 08916 08917 /* DB: Add CIC's DPC information */ 08918 tmp->dpc = cur_defaultdpc; 08919 08920 tmp->ss7 = ss7; 08921 tmp->ss7call = NULL; 08922 ss7->pvts[ss7->numchans++] = tmp; 08923 08924 ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix)); 08925 ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix)); 08926 ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix)); 08927 ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix)); 08928 08929 ss7->called_nai = conf->ss7.called_nai; 08930 ss7->calling_nai = conf->ss7.calling_nai; 08931 } 08932 #endif 08933 #ifdef HAVE_PRI 08934 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) { 08935 int offset; 08936 int myswitchtype; 08937 int matchesdchan; 08938 int x,y; 08939 offset = 0; 08940 if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP)) 08941 && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) { 08942 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 08943 destroy_dahdi_pvt(&tmp); 08944 return NULL; 08945 } 08946 if (span >= NUM_SPANS) { 08947 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span); 08948 destroy_dahdi_pvt(&tmp); 08949 return NULL; 08950 } else { 08951 struct dahdi_spaninfo si; 08952 si.spanno = 0; 08953 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) { 08954 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); 08955 destroy_dahdi_pvt(&tmp); 08956 return NULL; 08957 } 08958 /* Store the logical span first based upon the real span */ 08959 tmp->logicalspan = pris[span].prilogicalspan; 08960 pri_resolve_span(&span, channel, (channel - p.chanpos), &si); 08961 if (span < 0) { 08962 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel); 08963 destroy_dahdi_pvt(&tmp); 08964 return NULL; 08965 } 08966 if ((chan_sig == SIG_PRI) || 08967 (chan_sig == SIG_BRI) || 08968 (chan_sig == SIG_BRI_PTMP)) 08969 myswitchtype = conf->pri.switchtype; 08970 else 08971 myswitchtype = PRI_SWITCH_GR303_TMC; 08972 /* Make sure this isn't a d-channel */ 08973 matchesdchan=0; 08974 for (x = 0; x < NUM_SPANS; x++) { 08975 for (y = 0; y < NUM_DCHANS; y++) { 08976 if (pris[x].dchannels[y] == tmp->channel) { 08977 matchesdchan = 1; 08978 break; 08979 } 08980 } 08981 } 08982 offset = p.chanpos; 08983 if (!matchesdchan) { 08984 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) { 08985 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype)); 08986 destroy_dahdi_pvt(&tmp); 08987 return NULL; 08988 } 08989 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) { 08990 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype)); 08991 destroy_dahdi_pvt(&tmp); 08992 return NULL; 08993 } 08994 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) { 08995 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan)); 08996 destroy_dahdi_pvt(&tmp); 08997 return NULL; 08998 } 08999 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) { 09000 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial); 09001 destroy_dahdi_pvt(&tmp); 09002 return NULL; 09003 } 09004 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) { 09005 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext); 09006 destroy_dahdi_pvt(&tmp); 09007 return NULL; 09008 } 09009 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) { 09010 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused); 09011 destroy_dahdi_pvt(&tmp); 09012 return NULL; 09013 } 09014 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) { 09015 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle); 09016 destroy_dahdi_pvt(&tmp); 09017 return NULL; 09018 } 09019 if (pris[span].numchans >= MAX_CHANNELS) { 09020 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, 09021 pris[span].trunkgroup); 09022 destroy_dahdi_pvt(&tmp); 09023 return NULL; 09024 } 09025 09026 pris[span].sig = chan_sig; 09027 pris[span].nodetype = conf->pri.nodetype; 09028 pris[span].switchtype = myswitchtype; 09029 pris[span].nsf = conf->pri.nsf; 09030 pris[span].dialplan = conf->pri.dialplan; 09031 pris[span].localdialplan = conf->pri.localdialplan; 09032 pris[span].pvts[pris[span].numchans++] = tmp; 09033 pris[span].minunused = conf->pri.minunused; 09034 pris[span].minidle = conf->pri.minidle; 09035 pris[span].overlapdial = conf->pri.overlapdial; 09036 #ifdef HAVE_PRI_INBANDDISCONNECT 09037 pris[span].inbanddisconnect = conf->pri.inbanddisconnect; 09038 #endif 09039 pris[span].facilityenable = conf->pri.facilityenable; 09040 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial)); 09041 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext)); 09042 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix)); 09043 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix)); 09044 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix)); 09045 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix)); 09046 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix)); 09047 pris[span].resetinterval = conf->pri.resetinterval; 09048 09049 tmp->pri = &pris[span]; 09050 tmp->prioffset = offset; 09051 tmp->call = NULL; 09052 } else { 09053 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset); 09054 destroy_dahdi_pvt(&tmp); 09055 return NULL; 09056 } 09057 } 09058 } else { 09059 tmp->prioffset = 0; 09060 } 09061 #endif 09062 } else { 09063 chan_sig = tmp->sig; 09064 if (tmp->subs[SUB_REAL].dfd > -1) { 09065 memset(&p, 0, sizeof(p)); 09066 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 09067 } 09068 } 09069 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */ 09070 switch (chan_sig) { 09071 case SIG_FXSKS: 09072 case SIG_FXSLS: 09073 case SIG_EM: 09074 case SIG_EM_E1: 09075 case SIG_EMWINK: 09076 case SIG_FEATD: 09077 case SIG_FEATDMF: 09078 case SIG_FEATDMF_TA: 09079 case SIG_FEATB: 09080 case SIG_E911: 09081 case SIG_SF: 09082 case SIG_SFWINK: 09083 case SIG_FGC_CAMA: 09084 case SIG_FGC_CAMAMF: 09085 case SIG_SF_FEATD: 09086 case SIG_SF_FEATDMF: 09087 case SIG_SF_FEATB: 09088 p.starttime = 250; 09089 break; 09090 } 09091 09092 if (tmp->radio) { 09093 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */ 09094 p.channo = channel; 09095 p.rxwinktime = 1; 09096 p.rxflashtime = 1; 09097 p.starttime = 1; 09098 p.debouncetime = 5; 09099 } 09100 if (!tmp->radio) { 09101 p.channo = channel; 09102 /* Override timing settings based on config file */ 09103 if (conf->timing.prewinktime >= 0) 09104 p.prewinktime = conf->timing.prewinktime; 09105 if (conf->timing.preflashtime >= 0) 09106 p.preflashtime = conf->timing.preflashtime; 09107 if (conf->timing.winktime >= 0) 09108 p.winktime = conf->timing.winktime; 09109 if (conf->timing.flashtime >= 0) 09110 p.flashtime = conf->timing.flashtime; 09111 if (conf->timing.starttime >= 0) 09112 p.starttime = conf->timing.starttime; 09113 if (conf->timing.rxwinktime >= 0) 09114 p.rxwinktime = conf->timing.rxwinktime; 09115 if (conf->timing.rxflashtime >= 0) 09116 p.rxflashtime = conf->timing.rxflashtime; 09117 if (conf->timing.debouncetime >= 0) 09118 p.debouncetime = conf->timing.debouncetime; 09119 } 09120 09121 /* dont set parms on a pseudo-channel (or CRV) */ 09122 if (tmp->subs[SUB_REAL].dfd >= 0) 09123 { 09124 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p); 09125 if (res < 0) { 09126 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno)); 09127 destroy_dahdi_pvt(&tmp); 09128 return NULL; 09129 } 09130 } 09131 #if 1 09132 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) { 09133 memset(&bi, 0, sizeof(bi)); 09134 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 09135 if (!res) { 09136 bi.txbufpolicy = conf->chan.buf_policy; 09137 bi.rxbufpolicy = conf->chan.buf_policy; 09138 bi.numbufs = conf->chan.buf_no; 09139 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 09140 if (res < 0) { 09141 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno)); 09142 } 09143 } else 09144 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno)); 09145 } 09146 #endif 09147 tmp->immediate = conf->chan.immediate; 09148 tmp->transfertobusy = conf->chan.transfertobusy; 09149 if (chan_sig & __DAHDI_SIG_FXS) { 09150 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk; 09151 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon; 09152 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas; 09153 } 09154 tmp->sig = chan_sig; 09155 tmp->outsigmod = conf->chan.outsigmod; 09156 tmp->ringt_base = ringt_base; 09157 tmp->firstradio = 0; 09158 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS)) 09159 tmp->permcallwaiting = conf->chan.callwaiting; 09160 else 09161 tmp->permcallwaiting = 0; 09162 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */ 09163 tmp->destroy = 0; 09164 tmp->drings = conf->chan.drings; 09165 09166 /* 10 is a nice default. */ 09167 if (tmp->drings.ringnum[0].range == 0) 09168 tmp->drings.ringnum[0].range = 10; 09169 if (tmp->drings.ringnum[1].range == 0) 09170 tmp->drings.ringnum[1].range = 10; 09171 if (tmp->drings.ringnum[2].range == 0) 09172 tmp->drings.ringnum[2].range = 10; 09173 09174 tmp->usedistinctiveringdetection = usedistinctiveringdetection; 09175 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid; 09176 tmp->threewaycalling = conf->chan.threewaycalling; 09177 tmp->adsi = conf->chan.adsi; 09178 tmp->use_smdi = conf->chan.use_smdi; 09179 tmp->permhidecallerid = conf->chan.hidecallerid; 09180 tmp->hidecalleridname = conf->chan.hidecalleridname; 09181 tmp->callreturn = conf->chan.callreturn; 09182 tmp->echocancel = conf->chan.echocancel; 09183 tmp->echotraining = conf->chan.echotraining; 09184 tmp->pulse = conf->chan.pulse; 09185 if (tmp->echocancel.head.tap_length) { 09186 tmp->echocanbridged = conf->chan.echocanbridged; 09187 } else { 09188 if (conf->chan.echocanbridged) 09189 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n"); 09190 tmp->echocanbridged = 0; 09191 } 09192 tmp->busydetect = conf->chan.busydetect; 09193 tmp->busycount = conf->chan.busycount; 09194 tmp->busycompare = conf->chan.busycompare; 09195 tmp->busytonelength = conf->chan.busytonelength; 09196 tmp->busyquietlength = conf->chan.busyquietlength; 09197 tmp->busyfuzziness = conf->chan.busyfuzziness; 09198 tmp->silencethreshold = conf->chan.silencethreshold; 09199 tmp->callprogress = conf->chan.callprogress; 09200 tmp->cancallforward = conf->chan.cancallforward; 09201 tmp->dtmfrelax = conf->chan.dtmfrelax; 09202 tmp->callwaiting = tmp->permcallwaiting; 09203 tmp->hidecallerid = tmp->permhidecallerid; 09204 tmp->channel = channel; 09205 tmp->stripmsd = conf->chan.stripmsd; 09206 tmp->use_callerid = conf->chan.use_callerid; 09207 tmp->cid_signalling = conf->chan.cid_signalling; 09208 tmp->cid_start = conf->chan.cid_start; 09209 tmp->dahditrcallerid = conf->chan.dahditrcallerid; 09210 tmp->restrictcid = conf->chan.restrictcid; 09211 tmp->use_callingpres = conf->chan.use_callingpres; 09212 tmp->priexclusive = conf->chan.priexclusive; 09213 if (tmp->usedistinctiveringdetection) { 09214 if (!tmp->use_callerid) { 09215 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n"); 09216 tmp->use_callerid = 1; 09217 } 09218 } 09219 09220 if (tmp->cid_signalling == CID_SIG_SMDI) { 09221 if (!tmp->use_smdi) { 09222 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n"); 09223 tmp->use_smdi = 1; 09224 } 09225 } 09226 if (tmp->use_smdi) { 09227 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port); 09228 if (!(tmp->smdi_iface)) { 09229 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n"); 09230 tmp->use_smdi = 0; 09231 } 09232 } 09233 09234 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode)); 09235 tmp->amaflags = conf->chan.amaflags; 09236 if (!here) { 09237 tmp->confno = -1; 09238 tmp->propconfno = -1; 09239 } 09240 tmp->canpark = conf->chan.canpark; 09241 tmp->transfer = conf->chan.transfer; 09242 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext)); 09243 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language)); 09244 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret)); 09245 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest)); 09246 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context)); 09247 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot)); 09248 tmp->cid_ton = 0; 09249 switch (tmp->sig) { 09250 case SIG_PRI: 09251 case SIG_BRI: 09252 case SIG_BRI_PTMP: 09253 case SIG_SS7: 09254 tmp->cid_num[0] = '\0'; 09255 tmp->cid_name[0] = '\0'; 09256 break; 09257 default: 09258 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num)); 09259 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name)); 09260 break; 09261 } 09262 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox)); 09263 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) { 09264 char *mailbox, *context; 09265 mailbox = context = ast_strdupa(tmp->mailbox); 09266 strsep(&context, "@"); 09267 if (ast_strlen_zero(context)) 09268 context = "default"; 09269 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL, 09270 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 09271 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 09272 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, 09273 AST_EVENT_IE_END); 09274 } 09275 tmp->msgstate = -1; 09276 tmp->group = conf->chan.group; 09277 tmp->callgroup = conf->chan.callgroup; 09278 tmp->pickupgroup= conf->chan.pickupgroup; 09279 if (conf->chan.vars) { 09280 struct ast_variable *v, *tmpvar; 09281 for (v = conf->chan.vars ; v ; v = v->next) { 09282 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) { 09283 tmpvar->next = tmp->vars; 09284 tmp->vars = tmpvar; 09285 } 09286 } 09287 } 09288 tmp->cid_rxgain = conf->chan.cid_rxgain; 09289 tmp->rxgain = conf->chan.rxgain; 09290 tmp->txgain = conf->chan.txgain; 09291 tmp->tonezone = conf->chan.tonezone; 09292 tmp->onhooktime = time(NULL); 09293 if (tmp->subs[SUB_REAL].dfd > -1) { 09294 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law); 09295 if (tmp->dsp) 09296 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax); 09297 update_conf(tmp); 09298 if (!here) { 09299 if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI) && (chan_sig != SIG_SS7)) 09300 /* Hang it up to be sure it's good */ 09301 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 09302 } 09303 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone); 09304 #ifdef HAVE_PRI 09305 /* the dchannel is down so put the channel in alarm */ 09306 if (tmp->pri && !pri_is_up(tmp->pri)) 09307 tmp->inalarm = 1; 09308 #endif 09309 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) { 09310 tmp->inalarm = 1; 09311 handle_alarms(tmp, res); 09312 } 09313 } 09314 09315 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 09316 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 09317 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 09318 tmp->sendcalleridafter = conf->chan.sendcalleridafter; 09319 if (!here) { 09320 tmp->locallyblocked = tmp->remotelyblocked = 0; 09321 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7)) 09322 tmp->inservice = 0; 09323 else /* We default to in service on protocols that don't have a reset */ 09324 tmp->inservice = 1; 09325 } 09326 } 09327 if (tmp && !here) { 09328 /* nothing on the iflist */ 09329 if (!*wlist) { 09330 *wlist = tmp; 09331 tmp->prev = NULL; 09332 tmp->next = NULL; 09333 *wend = tmp; 09334 } else { 09335 /* at least one member on the iflist */ 09336 struct dahdi_pvt *working = *wlist; 09337 09338 /* check if we maybe have to put it on the begining */ 09339 if (working->channel > tmp->channel) { 09340 tmp->next = *wlist; 09341 tmp->prev = NULL; 09342 (*wlist)->prev = tmp; 09343 *wlist = tmp; 09344 } else { 09345 /* go through all the members and put the member in the right place */ 09346 while (working) { 09347 /* in the middle */ 09348 if (working->next) { 09349 if (working->channel < tmp->channel && working->next->channel > tmp->channel) { 09350 tmp->next = working->next; 09351 tmp->prev = working; 09352 working->next->prev = tmp; 09353 working->next = tmp; 09354 break; 09355 } 09356 } else { 09357 /* the last */ 09358 if (working->channel < tmp->channel) { 09359 working->next = tmp; 09360 tmp->next = NULL; 09361 tmp->prev = working; 09362 *wend = tmp; 09363 break; 09364 } 09365 } 09366 working = working->next; 09367 } 09368 } 09369 } 09370 } 09371 return tmp; 09372 }
static void mwi_event_cb | ( | const struct ast_event * | event, | |
void * | userdata | |||
) | [static] |
Definition at line 295 of file chan_dahdi.c.
Referenced by add_peer_mwi_subs(), build_device(), build_gateway(), and build_peer().
00296 { 00297 /* This module does not handle MWI in an event-based manner. However, it 00298 * subscribes to MWI for each mailbox that is configured so that the core 00299 * knows that we care about it. Then, chan_dahdi will get the MWI from the 00300 * event cache instead of checking the mailbox directly. */ 00301 }
static void* mwi_send_thread | ( | void * | data | ) | [static] |
Definition at line 7998 of file chan_dahdi.c.
References AS_RP_cadence, 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().
07999 { 08000 struct mwi_thread_data *mtd = data; 08001 struct timeval timeout_basis, suspend, now; 08002 int x, i, res; 08003 int num_read; 08004 enum mwisend_states mwi_send_state = MWI_SEND_SPILL; /*Assume FSK only */ 08005 08006 ast_mutex_lock(&mwi_thread_lock); 08007 mwi_thread_count++; 08008 ast_mutex_unlock(&mwi_thread_lock); 08009 08010 /* Determine how this spill is to be sent */ 08011 if(mwisend_rpas) { 08012 mwi_send_state = MWI_SEND_SA; 08013 } 08014 08015 gettimeofday(&timeout_basis, NULL); 08016 08017 mtd->pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE); 08018 if (!mtd->pvt->cidspill) { 08019 mtd->pvt->mwisendactive = 0; 08020 ast_free(mtd); 08021 return NULL; 08022 } 08023 x = DAHDI_FLUSH_BOTH; 08024 res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 08025 x = 3000; 08026 ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x); 08027 mtd->pvt->cidlen = vmwi_generate(mtd->pvt->cidspill, has_voicemail(mtd->pvt), CID_MWI_TYPE_MDMF_FULL, 08028 AST_LAW(mtd->pvt), mtd->pvt->cid_name, mtd->pvt->cid_num, 0); 08029 mtd->pvt->cidpos = 0; 08030 08031 while (MWI_SEND_DONE != mwi_send_state) { 08032 num_read = 0; 08033 gettimeofday(&now, NULL); 08034 if ( 10 < (now.tv_sec - timeout_basis.tv_sec)) { 08035 ast_log(LOG_WARNING, "MWI Send TIMEOUT in state %d\n", mwi_send_state); 08036 goto quit; 08037 } 08038 08039 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 08040 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) { 08041 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 08042 goto quit; 08043 } 08044 08045 if (i & DAHDI_IOMUX_SIGEVENT) { 08046 /* If we get an event, screen out events that we do not act on. 08047 * Otherwise, let handle_init_event determine what is needed 08048 */ 08049 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd); 08050 switch (res) { 08051 case DAHDI_EVENT_RINGEROFF: 08052 if(mwi_send_state == MWI_SEND_SA_WAIT) { 08053 if (dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) { 08054 ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s\n", strerror(errno)); 08055 goto quit; 08056 } 08057 mwi_send_state = MWI_SEND_PAUSE; 08058 gettimeofday(&suspend, NULL); 08059 } 08060 break; 08061 case DAHDI_EVENT_RINGERON: 08062 case DAHDI_EVENT_HOOKCOMPLETE: 08063 break; 08064 default: 08065 /* Got to the default init event handler */ 08066 if (0 < handle_init_event(mtd->pvt, res)) { 08067 /* I've spawned a thread, get out */ 08068 goto quit; 08069 } 08070 break; 08071 } 08072 } else if (i & DAHDI_IOMUX_READ) { 08073 if ((num_read = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) { 08074 if (errno != ELAST) { 08075 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 08076 goto quit; 08077 } 08078 break; 08079 } 08080 } 08081 /* Perform mwi send action */ 08082 switch ( mwi_send_state) { 08083 case MWI_SEND_SA: 08084 /* Send the Ring Pulse Signal Alert */ 08085 res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence); 08086 if (res) { 08087 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno)); 08088 goto quit; 08089 } 08090 dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RING); 08091 mwi_send_state = MWI_SEND_SA_WAIT; 08092 break; 08093 case MWI_SEND_SA_WAIT: /* do nothing until I get RINGEROFF event */ 08094 break; 08095 case MWI_SEND_PAUSE: /* Wait between alert and spill - min of 500 mS*/ 08096 gettimeofday(&now, NULL); 08097 if ((int)(now.tv_sec - suspend.tv_sec) * 1000000 + (int)now.tv_usec - (int)suspend.tv_usec > 500000) { 08098 mwi_send_state = MWI_SEND_SPILL; 08099 } 08100 break; 08101 case MWI_SEND_SPILL: 08102 /* We read some number of bytes. Write an equal amount of data */ 08103 if(0 < num_read) { 08104 if (num_read > mtd->pvt->cidlen - mtd->pvt->cidpos) 08105 num_read = mtd->pvt->cidlen - mtd->pvt->cidpos; 08106 res = write(mtd->pvt->subs[SUB_REAL].dfd, mtd->pvt->cidspill + mtd->pvt->cidpos, num_read); 08107 if (res > 0) { 08108 mtd->pvt->cidpos += res; 08109 if (mtd->pvt->cidpos >= mtd->pvt->cidlen) { 08110 ast_free(mtd->pvt->cidspill); 08111 mtd->pvt->cidspill = NULL; 08112 mtd->pvt->cidpos = 0; 08113 mtd->pvt->cidlen = 0; 08114 mwi_send_state = MWI_SEND_CLEANUP; 08115 } 08116 } else { 08117 ast_log(LOG_WARNING, "MWI Send Write failed: %s\n", strerror(errno)); 08118 goto quit; 08119 } 08120 } 08121 break; 08122 case MWI_SEND_CLEANUP: 08123 /* For now, do nothing */ 08124 mwi_send_state = MWI_SEND_DONE; 08125 break; 08126 default: 08127 /* Should not get here, punt*/ 08128 goto quit; 08129 break; 08130 } 08131 } 08132 08133 quit: 08134 if(mtd->pvt->cidspill) { 08135 ast_free(mtd->pvt->cidspill); 08136 mtd->pvt->cidspill = NULL; 08137 } 08138 mtd->pvt->mwisendactive = 0; 08139 ast_free(mtd); 08140 08141 ast_mutex_lock(&mwi_thread_lock); 08142 mwi_thread_count--; 08143 ast_cond_signal(&mwi_thread_complete); 08144 ast_mutex_unlock(&mwi_thread_lock); 08145 08146 return NULL; 08147 }
static void* mwi_thread | ( | void * | data | ) | [static] |
Definition at line 7851 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.
07852 { 07853 struct mwi_thread_data *mtd = data; 07854 struct callerid_state *cs; 07855 pthread_t threadid; 07856 int samples = 0; 07857 char *name, *number; 07858 int flags; 07859 int i, res; 07860 unsigned int spill_done = 0; 07861 int spill_result = -1; 07862 07863 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) { 07864 mtd->pvt->mwimonitoractive = 0; 07865 07866 return NULL; 07867 } 07868 07869 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt)); 07870 07871 bump_gains(mtd->pvt); 07872 07873 for (;;) { 07874 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07875 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) { 07876 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07877 goto quit; 07878 } 07879 07880 if (i & DAHDI_IOMUX_SIGEVENT) { 07881 struct ast_channel *chan; 07882 07883 /* If we get an event, screen out events that we do not act on. 07884 * Otherwise, cancel and go to the simple switch to let it deal with it. 07885 */ 07886 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd); 07887 07888 switch (res) { 07889 case DAHDI_EVENT_NEONMWI_ACTIVE: 07890 case DAHDI_EVENT_NEONMWI_INACTIVE: 07891 case DAHDI_EVENT_NONE: 07892 case DAHDI_EVENT_BITSCHANGED: 07893 break; 07894 case DAHDI_EVENT_NOALARM: 07895 mtd->pvt->inalarm = 0; 07896 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel); 07897 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 07898 "Channel: %d\r\n", mtd->pvt->channel); 07899 break; 07900 case DAHDI_EVENT_ALARM: 07901 mtd->pvt->inalarm = 1; 07902 res = get_alarms(mtd->pvt); 07903 handle_alarms(mtd->pvt, res); 07904 break; /* What to do on channel alarm ???? -- fall thru intentionally?? */ 07905 default: 07906 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to ss_thread\n", res, event2str(res)); 07907 callerid_free(cs); 07908 07909 restore_gains(mtd->pvt); 07910 mtd->pvt->ringt = mtd->pvt->ringt_base; 07911 07912 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) { 07913 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 07914 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel); 07915 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07916 if (res < 0) 07917 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel); 07918 ast_hangup(chan); 07919 goto quit; 07920 } 07921 goto quit_no_clean; 07922 07923 } else { 07924 ast_log(LOG_WARNING, "Could not create channel to handle call\n"); 07925 } 07926 } 07927 } else if (i & DAHDI_IOMUX_READ) { 07928 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) { 07929 if (errno != ELAST) { 07930 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07931 goto quit; 07932 } 07933 break; 07934 } 07935 samples += res; 07936 if (!spill_done) { 07937 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) { 07938 /* 07939 * The previous diagnostic message output likely 07940 * explains why it failed. 07941 */ 07942 ast_log(LOG_WARNING, "Failed to decode CallerID\n"); 07943 break; 07944 } else if (spill_result) { 07945 spill_done = 1; 07946 } 07947 } else { 07948 /* keep reading data until the energy level drops below the threshold 07949 so we don't get another 'trigger' on the remaining carrier signal 07950 */ 07951 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel) 07952 break; 07953 } 07954 if (samples > (8000 * 4)) /*Termination case - time to give up*/ 07955 break; 07956 } 07957 } 07958 07959 if (spill_result == 1) { 07960 callerid_get(cs, &name, &number, &flags); 07961 if (flags & CID_MSGWAITING) { 07962 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel); 07963 notify_message(mtd->pvt->mailbox, 1); 07964 } else if (flags & CID_NOMSGWAITING) { 07965 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel); 07966 notify_message(mtd->pvt->mailbox, 0); 07967 } else { 07968 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel); 07969 } 07970 } 07971 07972 07973 quit: 07974 callerid_free(cs); 07975 07976 restore_gains(mtd->pvt); 07977 07978 quit_no_clean: 07979 mtd->pvt->mwimonitoractive = 0; 07980 07981 ast_free(mtd); 07982 07983 return NULL; 07984 }
static int my_dahdi_write | ( | struct dahdi_pvt * | p, | |
unsigned char * | buf, | |||
int | len, | |||
int | idx, | |||
int | linear | |||
) | [static] |
Definition at line 5992 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().
05993 { 05994 int sent=0; 05995 int size; 05996 int res; 05997 int fd; 05998 fd = p->subs[idx].dfd; 05999 while (len) { 06000 size = len; 06001 if (size > (linear ? READ_SIZE * 2 : READ_SIZE)) 06002 size = (linear ? READ_SIZE * 2 : READ_SIZE); 06003 res = write(fd, buf, size); 06004 if (res != size) { 06005 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 06006 return sent; 06007 } 06008 len -= size; 06009 buf += size; 06010 } 06011 return sent; 06012 }
static int my_getsigstr | ( | struct ast_channel * | chan, | |
char * | str, | |||
const char * | term, | |||
int | ms | |||
) | [static] |
Definition at line 6518 of file chan_dahdi.c.
References ast_waitfordigit(), and chan.
Referenced by ss_thread().
06519 { 06520 char c; 06521 06522 *str = 0; /* start with empty output buffer */ 06523 for (;;) 06524 { 06525 /* Wait for the first digit (up to specified ms). */ 06526 c = ast_waitfordigit(chan, ms); 06527 /* if timeout, hangup or error, return as such */ 06528 if (c < 1) 06529 return c; 06530 *str++ = c; 06531 *str = 0; 06532 if (strchr(term, c)) 06533 return 1; 06534 } 06535 }
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 2301 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().
02302 { 02303 char s[sizeof(mwimonitornotify) + 80]; 02304 struct ast_event *event; 02305 char *mailbox, *context; 02306 02307 /* Strip off @default */ 02308 context = mailbox = ast_strdupa(mailbox_full); 02309 strsep(&context, "@"); 02310 if (ast_strlen_zero(context)) 02311 context = "default"; 02312 02313 if (!(event = ast_event_new(AST_EVENT_MWI, 02314 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 02315 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 02316 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 02317 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 02318 AST_EVENT_IE_END))) { 02319 return; 02320 } 02321 02322 ast_event_queue_and_cache(event); 02323 02324 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) { 02325 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot); 02326 ast_safe_system(s); 02327 } 02328 }
static int pri_active_dchan_fd | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3357 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().
03358 { 03359 int x = -1; 03360 03361 for (x = 0; x < NUM_DCHANS; x++) { 03362 if ((pri->dchans[x] == pri->pri)) 03363 break; 03364 } 03365 03366 return pri->fds[x]; 03367 }
static int pri_assign_bearer | ( | struct dahdi_pvt * | crv, | |
struct dahdi_pri * | pri, | |||
struct dahdi_pvt * | bearer | |||
) | [static] |
Definition at line 3327 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().
03328 { 03329 bearer->owner = &inuse; 03330 bearer->realcall = crv; 03331 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd; 03332 if (crv->subs[SUB_REAL].owner) 03333 ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd); 03334 crv->bearer = bearer; 03335 crv->call = bearer->call; 03336 crv->pri = pri; 03337 return 0; 03338 }
static int pri_check_restart | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 10884 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().
10885 { 10886 do { 10887 pri->resetpos++; 10888 } while ((pri->resetpos < pri->numchans) && 10889 (!pri->pvts[pri->resetpos] || 10890 pri->pvts[pri->resetpos]->call || 10891 pri->pvts[pri->resetpos]->resetting)); 10892 if (pri->resetpos < pri->numchans) { 10893 /* Mark the channel as resetting and restart it */ 10894 pri->pvts[pri->resetpos]->resetting = 1; 10895 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos])); 10896 } else { 10897 pri->resetting = 0; 10898 time(&pri->lastreset); 10899 } 10900 return 0; 10901 }
static int pri_create_spanmap | ( | int | span, | |
int | trunkgroup, | |||
int | logicalspan | |||
) | [static] |
Definition at line 8744 of file chan_dahdi.c.
References ast_log(), dahdi_pri::mastertrunkgroup, dahdi_pri::prilogicalspan, and pris.
Referenced by setup_dahdi().
08745 { 08746 if (pris[span].mastertrunkgroup) { 08747 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); 08748 return -1; 08749 } 08750 pris[span].mastertrunkgroup = trunkgroup; 08751 pris[span].prilogicalspan = logicalspan; 08752 return 0; 08753 }
static int pri_create_trunkgroup | ( | int | trunkgroup, | |
int * | channels | |||
) | [static] |
Definition at line 8681 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().
08682 { 08683 struct dahdi_spaninfo si; 08684 struct dahdi_params p; 08685 int fd; 08686 int span; 08687 int ospan=0; 08688 int x,y; 08689 for (x = 0; x < NUM_SPANS; x++) { 08690 if (pris[x].trunkgroup == trunkgroup) { 08691 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]); 08692 return -1; 08693 } 08694 } 08695 for (y = 0; y < NUM_DCHANS; y++) { 08696 if (!channels[y]) 08697 break; 08698 memset(&si, 0, sizeof(si)); 08699 memset(&p, 0, sizeof(p)); 08700 fd = open("/dev/dahdi/channel", O_RDWR); 08701 if (fd < 0) { 08702 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno)); 08703 return -1; 08704 } 08705 x = channels[y]; 08706 if (ioctl(fd, DAHDI_SPECIFY, &x)) { 08707 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno)); 08708 close(fd); 08709 return -1; 08710 } 08711 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) { 08712 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno)); 08713 return -1; 08714 } 08715 if (ioctl(fd, DAHDI_SPANSTAT, &si)) { 08716 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno)); 08717 close(fd); 08718 return -1; 08719 } 08720 span = p.spanno - 1; 08721 if (pris[span].trunkgroup) { 08722 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup); 08723 close(fd); 08724 return -1; 08725 } 08726 if (pris[span].pvts[0]) { 08727 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1); 08728 close(fd); 08729 return -1; 08730 } 08731 if (!y) { 08732 pris[span].trunkgroup = trunkgroup; 08733 pris[span].offset = channels[y] - p.chanpos; 08734 ospan = span; 08735 } 08736 pris[ospan].dchannels[y] = channels[y]; 08737 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED; 08738 pris[span].span = span + 1; 08739 close(fd); 08740 } 08741 return 0; 08742 }
static void* pri_dchannel | ( | void * | vpri | ) | [static] |
Definition at line 10978 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.
10979 { 10980 struct dahdi_pri *pri = vpri; 10981 pri_event *e; 10982 struct pollfd fds[NUM_DCHANS]; 10983 int res; 10984 int chanpos = 0; 10985 int x; 10986 int haveidles; 10987 int activeidles; 10988 int nextidle = -1; 10989 struct ast_channel *c; 10990 struct timeval tv, lowest, *next; 10991 struct timeval lastidle = ast_tvnow(); 10992 int doidling=0; 10993 char *cc; 10994 char idlen[80]; 10995 struct ast_channel *idle; 10996 pthread_t p; 10997 time_t t; 10998 int i, which=-1; 10999 int numdchans; 11000 int cause=0; 11001 struct dahdi_pvt *crv; 11002 pthread_t threadid; 11003 char ani2str[6]; 11004 char plancallingnum[256]; 11005 char plancallingani[256]; 11006 char calledtonstr[10]; 11007 11008 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 11009 11010 gettimeofday(&lastidle, NULL); 11011 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) { 11012 /* Need to do idle dialing, check to be sure though */ 11013 cc = strchr(pri->idleext, '@'); 11014 if (cc) { 11015 *cc = '\0'; 11016 cc++; 11017 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext)); 11018 #if 0 11019 /* Extensions may not be loaded yet */ 11020 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL)) 11021 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext); 11022 else 11023 #endif 11024 doidling = 1; 11025 } else 11026 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext); 11027 } 11028 for (;;) { 11029 for (i = 0; i < NUM_DCHANS; i++) { 11030 if (!pri->dchannels[i]) 11031 break; 11032 fds[i].fd = pri->fds[i]; 11033 fds[i].events = POLLIN | POLLPRI; 11034 fds[i].revents = 0; 11035 } 11036 numdchans = i; 11037 time(&t); 11038 ast_mutex_lock(&pri->lock); 11039 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) { 11040 if (pri->resetting && pri_is_up(pri)) { 11041 if (pri->resetpos < 0) 11042 pri_check_restart(pri); 11043 } else { 11044 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) { 11045 pri->resetting = 1; 11046 pri->resetpos = -1; 11047 } 11048 } 11049 } 11050 /* Look for any idle channels if appropriate */ 11051 if (doidling && pri_is_up(pri)) { 11052 nextidle = -1; 11053 haveidles = 0; 11054 activeidles = 0; 11055 for (x = pri->numchans; x >= 0; x--) { 11056 if (pri->pvts[x] && !pri->pvts[x]->owner && 11057 !pri->pvts[x]->call) { 11058 if (haveidles < pri->minunused) { 11059 haveidles++; 11060 } else if (!pri->pvts[x]->resetting) { 11061 nextidle = x; 11062 break; 11063 } 11064 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) 11065 activeidles++; 11066 } 11067 if (nextidle > -1) { 11068 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) { 11069 /* Don't create a new idle call more than once per second */ 11070 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial); 11071 idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause); 11072 if (idle) { 11073 pri->pvts[nextidle]->isidlecall = 1; 11074 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) { 11075 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name); 11076 dahdi_hangup(idle); 11077 } 11078 } else 11079 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen); 11080 lastidle = ast_tvnow(); 11081 } 11082 } else if ((haveidles < pri->minunused) && 11083 (activeidles > pri->minidle)) { 11084 /* Mark something for hangup if there is something 11085 that can be hungup */ 11086 for (x = pri->numchans; x >= 0; x--) { 11087 /* find a candidate channel */ 11088 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) { 11089 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11090 haveidles++; 11091 /* Stop if we have enough idle channels or 11092 can't spare any more active idle ones */ 11093 if ((haveidles >= pri->minunused) || 11094 (activeidles <= pri->minidle)) 11095 break; 11096 } 11097 } 11098 } 11099 } 11100 /* Start with reasonable max */ 11101 lowest = ast_tv(60, 0); 11102 for (i = 0; i < NUM_DCHANS; i++) { 11103 /* Find lowest available d-channel */ 11104 if (!pri->dchannels[i]) 11105 break; 11106 if ((next = pri_schedule_next(pri->dchans[i]))) { 11107 /* We need relative time here */ 11108 tv = ast_tvsub(*next, ast_tvnow()); 11109 if (tv.tv_sec < 0) { 11110 tv = ast_tv(0,0); 11111 } 11112 if (doidling || pri->resetting) { 11113 if (tv.tv_sec > 1) { 11114 tv = ast_tv(1, 0); 11115 } 11116 } else { 11117 if (tv.tv_sec > 60) { 11118 tv = ast_tv(60, 0); 11119 } 11120 } 11121 } else if (doidling || pri->resetting) { 11122 /* Make sure we stop at least once per second if we're 11123 monitoring idle channels */ 11124 tv = ast_tv(1,0); 11125 } else { 11126 /* Don't poll for more than 60 seconds */ 11127 tv = ast_tv(60, 0); 11128 } 11129 if (!i || ast_tvcmp(tv, lowest) < 0) { 11130 lowest = tv; 11131 } 11132 } 11133 ast_mutex_unlock(&pri->lock); 11134 11135 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 11136 pthread_testcancel(); 11137 e = NULL; 11138 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000); 11139 pthread_testcancel(); 11140 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 11141 11142 ast_mutex_lock(&pri->lock); 11143 if (!res) { 11144 for (which = 0; which < NUM_DCHANS; which++) { 11145 if (!pri->dchans[which]) 11146 break; 11147 /* Just a timeout, run the scheduler */ 11148 e = pri_schedule_run(pri->dchans[which]); 11149 if (e) 11150 break; 11151 } 11152 } else if (res > -1) { 11153 for (which = 0; which < NUM_DCHANS; which++) { 11154 if (!pri->dchans[which]) 11155 break; 11156 if (fds[which].revents & POLLPRI) { 11157 /* Check for an event */ 11158 x = 0; 11159 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x); 11160 if (x) { 11161 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); 11162 manager_event(EVENT_FLAG_SYSTEM, "PRIEvent", 11163 "PRIEvent: %s\r\n" 11164 "PRIEventCode: %d\r\n" 11165 "D-channel: %s\r\n" 11166 "Span: %d\r\n", 11167 event2str(x), 11168 x, 11169 pri_order(which), 11170 pri->span 11171 ); 11172 } 11173 /* Keep track of alarm state */ 11174 if (x == DAHDI_EVENT_ALARM) { 11175 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP); 11176 pri_find_dchan(pri); 11177 } else if (x == DAHDI_EVENT_NOALARM) { 11178 pri->dchanavail[which] |= DCHAN_NOTINALARM; 11179 pri_restart(pri->dchans[which]); 11180 } 11181 11182 ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span); 11183 } else if (fds[which].revents & POLLIN) { 11184 e = pri_check_event(pri->dchans[which]); 11185 } 11186 if (e) 11187 break; 11188 } 11189 } else if (errno != EINTR) 11190 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno)); 11191 11192 if (e) { 11193 if (pri->debug) 11194 pri_dump_event(pri->dchans[which], e); 11195 11196 if (e->e != PRI_EVENT_DCHAN_DOWN) { 11197 if (!(pri->dchanavail[which] & DCHAN_UP)) { 11198 ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span); 11199 } 11200 pri->dchanavail[which] |= DCHAN_UP; 11201 } else if (pri->sig != SIG_BRI_PTMP) { 11202 if (pri->dchanavail[which] & DCHAN_UP) { 11203 ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span); 11204 } 11205 pri->dchanavail[which] &= ~DCHAN_UP; 11206 } 11207 11208 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which])) 11209 /* Must be an NFAS group that has the secondary dchan active */ 11210 pri->pri = pri->dchans[which]; 11211 11212 switch (e->e) { 11213 case PRI_EVENT_DCHAN_UP: 11214 if (!pri->pri) pri_find_dchan(pri); 11215 11216 /* Note presense of D-channel */ 11217 time(&pri->lastreset); 11218 11219 /* Restart in 5 seconds */ 11220 if (pri->resetinterval > -1) { 11221 pri->lastreset -= pri->resetinterval; 11222 pri->lastreset += 5; 11223 } 11224 pri->resetting = 0; 11225 /* Take the channels from inalarm condition */ 11226 for (i = 0; i < pri->numchans; i++) 11227 if (pri->pvts[i]) { 11228 pri->pvts[i]->inalarm = 0; 11229 } 11230 break; 11231 case PRI_EVENT_DCHAN_DOWN: 11232 pri_find_dchan(pri); 11233 if (!pri_is_up(pri)) { 11234 pri->resetting = 0; 11235 /* Hangup active channels and put them in alarm mode */ 11236 for (i = 0; i < pri->numchans; i++) { 11237 struct dahdi_pvt *p = pri->pvts[i]; 11238 if (p) { 11239 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 11240 /* T309 is not enabled : hangup calls when alarm occurs */ 11241 if (p->call) { 11242 if (p->pri && p->pri->pri) { 11243 pri_hangup(p->pri->pri, p->call, -1); 11244 pri_destroycall(p->pri->pri, p->call); 11245 p->call = NULL; 11246 } else 11247 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n"); 11248 } 11249 if (p->realcall) { 11250 pri_hangup_all(p->realcall, pri); 11251 } else if (p->owner) 11252 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11253 } 11254 p->inalarm = 1; 11255 } 11256 } 11257 } 11258 break; 11259 case PRI_EVENT_RESTART: 11260 if (e->restart.channel > -1) { 11261 chanpos = pri_find_principle(pri, e->restart.channel); 11262 if (chanpos < 0) 11263 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 11264 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 11265 else { 11266 ast_verb(3, "B-channel %d/%d restarted on span %d\n", 11267 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 11268 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11269 if (pri->pvts[chanpos]->call) { 11270 pri_destroycall(pri->pri, pri->pvts[chanpos]->call); 11271 pri->pvts[chanpos]->call = NULL; 11272 } 11273 /* Force soft hangup if appropriate */ 11274 if (pri->pvts[chanpos]->realcall) 11275 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11276 else if (pri->pvts[chanpos]->owner) 11277 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11278 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11279 } 11280 } else { 11281 ast_verb(3, "Restart on requested on entire span %d\n", pri->span); 11282 for (x = 0; x < pri->numchans; x++) 11283 if (pri->pvts[x]) { 11284 ast_mutex_lock(&pri->pvts[x]->lock); 11285 if (pri->pvts[x]->call) { 11286 pri_destroycall(pri->pri, pri->pvts[x]->call); 11287 pri->pvts[x]->call = NULL; 11288 } 11289 if (pri->pvts[x]->realcall) 11290 pri_hangup_all(pri->pvts[x]->realcall, pri); 11291 else if (pri->pvts[x]->owner) 11292 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11293 ast_mutex_unlock(&pri->pvts[x]->lock); 11294 } 11295 } 11296 break; 11297 case PRI_EVENT_KEYPAD_DIGIT: 11298 chanpos = pri_find_principle(pri, e->digit.channel); 11299 if (chanpos < 0) { 11300 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 11301 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span); 11302 } else { 11303 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call); 11304 if (chanpos > -1) { 11305 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11306 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */ 11307 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) { 11308 /* how to do that */ 11309 int digitlen = strlen(e->digit.digits); 11310 char digit; 11311 int i; 11312 for (i = 0; i < digitlen; i++) { 11313 digit = e->digit.digits[i]; 11314 { 11315 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 11316 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11317 } 11318 } 11319 } 11320 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11321 } 11322 } 11323 break; 11324 11325 case PRI_EVENT_INFO_RECEIVED: 11326 chanpos = pri_find_principle(pri, e->ring.channel); 11327 if (chanpos < 0) { 11328 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 11329 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11330 } else { 11331 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call); 11332 if (chanpos > -1) { 11333 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11334 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */ 11335 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) { 11336 /* how to do that */ 11337 int digitlen = strlen(e->ring.callednum); 11338 char digit; 11339 int i; 11340 for (i = 0; i < digitlen; i++) { 11341 digit = e->ring.callednum[i]; 11342 { 11343 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 11344 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11345 } 11346 } 11347 } 11348 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11349 } 11350 } 11351 break; 11352 case PRI_EVENT_RING: 11353 crv = NULL; 11354 if (e->ring.channel == -1) 11355 chanpos = pri_find_empty_chan(pri, 1); 11356 else 11357 chanpos = pri_find_principle(pri, e->ring.channel); 11358 /* if no channel specified find one empty */ 11359 if (chanpos < 0) { 11360 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 11361 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11362 } else { 11363 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11364 if (pri->pvts[chanpos]->owner) { 11365 if (pri->pvts[chanpos]->call == e->ring.call) { 11366 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 11367 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11368 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11369 break; 11370 } else { 11371 /* This is where we handle initial glare */ 11372 ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n", 11373 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11374 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11375 chanpos = -1; 11376 } 11377 } 11378 if (chanpos > -1) 11379 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11380 } 11381 if ((chanpos < 0) && (e->ring.flexible)) 11382 chanpos = pri_find_empty_chan(pri, 1); 11383 if (chanpos > -1) { 11384 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11385 if (pri->switchtype == PRI_SWITCH_GR303_TMC) { 11386 /* Should be safe to lock CRV AFAIK while bearer is still locked */ 11387 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL)); 11388 if (crv) 11389 ast_mutex_lock(&crv->lock); 11390 if (!crv || crv->owner) { 11391 pri->pvts[chanpos]->call = NULL; 11392 if (crv) { 11393 if (crv->owner) 11394 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11395 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); 11396 } else 11397 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); 11398 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE); 11399 if (crv) 11400 ast_mutex_unlock(&crv->lock); 11401 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11402 break; 11403 } 11404 } 11405 pri->pvts[chanpos]->call = e->ring.call; 11406 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan); 11407 if (pri->pvts[chanpos]->use_callerid) { 11408 ast_shrink_phone_number(plancallingnum); 11409 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num)); 11410 #ifdef PRI_ANI 11411 if (!ast_strlen_zero(e->ring.callingani)) { 11412 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani); 11413 ast_shrink_phone_number(plancallingani); 11414 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani)); 11415 } else { 11416 pri->pvts[chanpos]->cid_ani[0] = '\0'; 11417 } 11418 #endif 11419 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name)); 11420 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */ 11421 } else { 11422 pri->pvts[chanpos]->cid_num[0] = '\0'; 11423 pri->pvts[chanpos]->cid_ani[0] = '\0'; 11424 pri->pvts[chanpos]->cid_name[0] = '\0'; 11425 pri->pvts[chanpos]->cid_ton = 0; 11426 } 11427 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri, 11428 e->ring.redirectingnum, e->ring.callingplanrdnis); 11429 /* If immediate=yes go to s|1 */ 11430 if (pri->pvts[chanpos]->immediate) { 11431 ast_verb(3, "Going to extension s|1 because of immediate=yes\n"); 11432 pri->pvts[chanpos]->exten[0] = 's'; 11433 pri->pvts[chanpos]->exten[1] = '\0'; 11434 } 11435 /* Get called number */ 11436 else if (!ast_strlen_zero(e->ring.callednum)) { 11437 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten)); 11438 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 11439 } else if (pri->overlapdial) 11440 pri->pvts[chanpos]->exten[0] = '\0'; 11441 else { 11442 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */ 11443 pri->pvts[chanpos]->exten[0] = 's'; 11444 pri->pvts[chanpos]->exten[1] = '\0'; 11445 } 11446 /* Set DNID on all incoming calls -- even immediate */ 11447 if (!ast_strlen_zero(e->ring.callednum)) 11448 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 11449 /* No number yet, but received "sending complete"? */ 11450 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) { 11451 ast_verb(3, "Going to extension s|1 because of Complete received\n"); 11452 pri->pvts[chanpos]->exten[0] = 's'; 11453 pri->pvts[chanpos]->exten[1] = '\0'; 11454 } 11455 11456 /* Make sure extension exists (or in overlap dial mode, can exist) */ 11457 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) || 11458 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 11459 /* Setup law */ 11460 int law; 11461 if (pri->switchtype != PRI_SWITCH_GR303_TMC) { 11462 /* Set to audio mode at this point */ 11463 law = 1; 11464 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1) 11465 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno)); 11466 } 11467 if (e->ring.layer1 == PRI_LAYER_1_ALAW) 11468 law = DAHDI_LAW_ALAW; 11469 else 11470 law = DAHDI_LAW_MULAW; 11471 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law); 11472 if (res < 0) 11473 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel); 11474 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law); 11475 if (res < 0) 11476 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel); 11477 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 11478 /* Just announce proceeding */ 11479 pri->pvts[chanpos]->proceeding = 1; 11480 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0); 11481 } else { 11482 if (pri->switchtype != PRI_SWITCH_GR303_TMC) 11483 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 11484 else 11485 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 11486 } 11487 /* Get the use_callingpres state */ 11488 pri->pvts[chanpos]->callingpres = e->ring.callingpres; 11489 11490 /* Start PBX */ 11491 if (!e->ring.complete 11492 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) 11493 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 11494 /* 11495 * Release the PRI lock while we create the channel 11496 * so other threads can send D channel messages. 11497 */ 11498 ast_mutex_unlock(&pri->lock); 11499 if (crv) { 11500 /* Set bearer and such */ 11501 pri_assign_bearer(crv, pri, pri->pvts[chanpos]); 11502 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 11503 pri->pvts[chanpos]->owner = &inuse; 11504 ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel); 11505 } else { 11506 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 11507 } 11508 ast_mutex_lock(&pri->lock); 11509 if (c) { 11510 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 11511 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 11512 } 11513 if (e->ring.ani2 >= 0) { 11514 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2); 11515 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 11516 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2; 11517 } 11518 11519 #ifdef SUPPORT_USERUSER 11520 if (!ast_strlen_zero(e->ring.useruserinfo)) { 11521 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 11522 } 11523 #endif 11524 11525 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 11526 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 11527 if (e->ring.redirectingreason >= 0) 11528 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 11529 } 11530 if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) { 11531 ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n", 11532 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"), 11533 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11534 } else { 11535 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 11536 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11537 if (c) 11538 ast_hangup(c); 11539 else { 11540 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 11541 pri->pvts[chanpos]->call = NULL; 11542 } 11543 } 11544 } else { 11545 /* 11546 * Release the PRI lock while we create the channel 11547 * so other threads can send D channel messages. 11548 */ 11549 ast_mutex_unlock(&pri->lock); 11550 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype); 11551 ast_mutex_lock(&pri->lock); 11552 if (c) { 11553 /* 11554 * It is reasonably safe to set the following 11555 * channel variables while the PRI and DAHDI private 11556 * structures are locked. The PBX has not been 11557 * started yet and it is unlikely that any other task 11558 * will do anything with the channel we have just 11559 * created. 11560 */ 11561 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 11562 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 11563 } 11564 if (e->ring.ani2 >= 0) { 11565 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2); 11566 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 11567 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2; 11568 } 11569 11570 #ifdef SUPPORT_USERUSER 11571 if (!ast_strlen_zero(e->ring.useruserinfo)) { 11572 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 11573 } 11574 #endif 11575 11576 if (e->ring.redirectingreason >= 0) 11577 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 11578 11579 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 11580 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 11581 } 11582 if (c && !ast_pbx_start(c)) { 11583 ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n", 11584 plancallingnum, pri->pvts[chanpos]->exten, 11585 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11586 11587 dahdi_enable_ec(pri->pvts[chanpos]); 11588 } else { 11589 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 11590 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11591 if (c) { 11592 ast_hangup(c); 11593 } else { 11594 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 11595 pri->pvts[chanpos]->call = NULL; 11596 } 11597 } 11598 } 11599 } else { 11600 ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n", 11601 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 11602 pri->pvts[chanpos]->prioffset, pri->span); 11603 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED); 11604 pri->pvts[chanpos]->call = NULL; 11605 pri->pvts[chanpos]->exten[0] = '\0'; 11606 } 11607 if (crv) 11608 ast_mutex_unlock(&crv->lock); 11609 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11610 } else { 11611 if (e->ring.flexible) 11612 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION); 11613 else 11614 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL); 11615 } 11616 break; 11617 case PRI_EVENT_RINGING: 11618 chanpos = pri_find_principle(pri, e->ringing.channel); 11619 if (chanpos < 0) { 11620 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 11621 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 11622 } else { 11623 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call); 11624 if (chanpos < 0) { 11625 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 11626 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 11627 } else { 11628 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11629 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 11630 dahdi_enable_ec(pri->pvts[chanpos]); 11631 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1; 11632 pri->pvts[chanpos]->alerting = 1; 11633 } else 11634 ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n"); 11635 11636 #ifdef PRI_PROGRESS_MASK 11637 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) { 11638 #else 11639 if (e->ringing.progress == 8) { 11640 #endif 11641 /* Now we can do call progress detection */ 11642 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11643 /* RINGING detection isn't required because we got ALERTING signal */ 11644 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING); 11645 pri->pvts[chanpos]->dsp_features = 0; 11646 } 11647 } 11648 11649 #ifdef SUPPORT_USERUSER 11650 if (!ast_strlen_zero(e->ringing.useruserinfo)) { 11651 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11652 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11653 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo); 11654 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11655 } 11656 #endif 11657 11658 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11659 } 11660 } 11661 break; 11662 case PRI_EVENT_PROGRESS: 11663 /* Get chan value if e->e is not PRI_EVNT_RINGING */ 11664 chanpos = pri_find_principle(pri, e->proceeding.channel); 11665 if (chanpos > -1) { 11666 #ifdef PRI_PROGRESS_MASK 11667 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) { 11668 #else 11669 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) { 11670 #endif 11671 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, }; 11672 11673 if (e->proceeding.cause > -1) { 11674 ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause); 11675 11676 /* Work around broken, out of spec USER_BUSY cause in a progress message */ 11677 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) { 11678 if (pri->pvts[chanpos]->owner) { 11679 ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n"); 11680 11681 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause; 11682 f.subclass = AST_CONTROL_BUSY; 11683 } 11684 } 11685 } 11686 11687 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11688 ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n", 11689 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 11690 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11691 #ifdef PRI_PROGRESS_MASK 11692 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 11693 #else 11694 if (e->proceeding.progress == 8) { 11695 #endif 11696 /* Now we can do call progress detection */ 11697 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11698 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 11699 pri->pvts[chanpos]->dsp_features = 0; 11700 } 11701 /* Bring voice path up */ 11702 f.subclass = AST_CONTROL_PROGRESS; 11703 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11704 } 11705 pri->pvts[chanpos]->progress = 1; 11706 pri->pvts[chanpos]->dialing = 0; 11707 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11708 } 11709 } 11710 break; 11711 case PRI_EVENT_PROCEEDING: 11712 chanpos = pri_find_principle(pri, e->proceeding.channel); 11713 if (chanpos > -1) { 11714 if (!pri->pvts[chanpos]->proceeding) { 11715 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, }; 11716 11717 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11718 ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n", 11719 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 11720 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11721 #ifdef PRI_PROGRESS_MASK 11722 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 11723 #else 11724 if (e->proceeding.progress == 8) { 11725 #endif 11726 /* Now we can do call progress detection */ 11727 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11728 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 11729 pri->pvts[chanpos]->dsp_features = 0; 11730 } 11731 /* Bring voice path up */ 11732 f.subclass = AST_CONTROL_PROGRESS; 11733 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11734 } 11735 pri->pvts[chanpos]->proceeding = 1; 11736 pri->pvts[chanpos]->dialing = 0; 11737 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11738 } 11739 } 11740 break; 11741 case PRI_EVENT_FACNAME: 11742 chanpos = pri_find_principle(pri, e->facname.channel); 11743 if (chanpos < 0) { 11744 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 11745 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 11746 } else { 11747 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call); 11748 if (chanpos < 0) { 11749 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 11750 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 11751 } else { 11752 /* Re-use *69 field for PRI */ 11753 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11754 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num)); 11755 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name)); 11756 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1; 11757 dahdi_enable_ec(pri->pvts[chanpos]); 11758 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11759 } 11760 } 11761 break; 11762 case PRI_EVENT_ANSWER: 11763 chanpos = pri_find_principle(pri, e->answer.channel); 11764 if (chanpos < 0) { 11765 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 11766 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 11767 } else { 11768 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call); 11769 if (chanpos < 0) { 11770 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 11771 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 11772 } else { 11773 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11774 /* Now we can do call progress detection */ 11775 11776 /* We changed this so it turns on the DSP no matter what... progress or no progress. 11777 * By this time, we need DTMF detection and other features that were previously disabled 11778 * -- Matt F */ 11779 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11780 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 11781 pri->pvts[chanpos]->dsp_features = 0; 11782 } 11783 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) { 11784 ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n"); 11785 x = DAHDI_START; 11786 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 11787 if (res < 0) { 11788 if (errno != EINPROGRESS) { 11789 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 11790 } 11791 } 11792 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 11793 pri->pvts[chanpos]->dialing = 1; 11794 /* Send any "w" waited stuff */ 11795 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop); 11796 if (res < 0) { 11797 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno)); 11798 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 11799 } else 11800 ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr); 11801 11802 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 11803 } else if (pri->pvts[chanpos]->confirmanswer) { 11804 ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel); 11805 } else { 11806 pri->pvts[chanpos]->dialing = 0; 11807 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1; 11808 /* Enable echo cancellation if it's not on already */ 11809 dahdi_enable_ec(pri->pvts[chanpos]); 11810 } 11811 11812 #ifdef SUPPORT_USERUSER 11813 if (!ast_strlen_zero(e->answer.useruserinfo)) { 11814 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11815 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11816 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo); 11817 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11818 } 11819 #endif 11820 11821 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11822 } 11823 } 11824 break; 11825 case PRI_EVENT_HANGUP: 11826 chanpos = pri_find_principle(pri, e->hangup.channel); 11827 if (chanpos < 0) { 11828 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %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 if (!pri->pvts[chanpos]->alreadyhungup) { 11835 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */ 11836 pri->pvts[chanpos]->alreadyhungup = 1; 11837 if (pri->pvts[chanpos]->realcall) 11838 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11839 else if (pri->pvts[chanpos]->owner) { 11840 /* Queue a BUSY instead of a hangup if our cause is appropriate */ 11841 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 11842 switch (pri->pvts[chanpos]->owner->_state) { 11843 case AST_STATE_BUSY: 11844 case AST_STATE_UP: 11845 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11846 break; 11847 default: 11848 switch (e->hangup.cause) { 11849 case PRI_CAUSE_USER_BUSY: 11850 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 11851 break; 11852 case PRI_CAUSE_CALL_REJECTED: 11853 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 11854 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 11855 case PRI_CAUSE_SWITCH_CONGESTION: 11856 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 11857 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 11858 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 11859 break; 11860 default: 11861 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11862 } 11863 break; 11864 } 11865 } 11866 ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n", 11867 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause); 11868 } else { 11869 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 11870 pri->pvts[chanpos]->call = NULL; 11871 } 11872 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 11873 ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 11874 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11875 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 11876 pri->pvts[chanpos]->resetting = 1; 11877 } 11878 if (e->hangup.aoc_units > -1) 11879 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 11880 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 11881 11882 #ifdef SUPPORT_USERUSER 11883 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) { 11884 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11885 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11886 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 11887 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11888 } 11889 #endif 11890 11891 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11892 } else { 11893 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 11894 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11895 } 11896 } 11897 break; 11898 #ifndef PRI_EVENT_HANGUP_REQ 11899 #error please update libpri 11900 #endif 11901 case PRI_EVENT_HANGUP_REQ: 11902 chanpos = pri_find_principle(pri, e->hangup.channel); 11903 if (chanpos < 0) { 11904 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 11905 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11906 } else { 11907 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 11908 if (chanpos > -1) { 11909 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11910 if (pri->pvts[chanpos]->realcall) 11911 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11912 else if (pri->pvts[chanpos]->owner) { 11913 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 11914 switch (pri->pvts[chanpos]->owner->_state) { 11915 case AST_STATE_BUSY: 11916 case AST_STATE_UP: 11917 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11918 break; 11919 default: 11920 switch (e->hangup.cause) { 11921 case PRI_CAUSE_USER_BUSY: 11922 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 11923 break; 11924 case PRI_CAUSE_CALL_REJECTED: 11925 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 11926 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 11927 case PRI_CAUSE_SWITCH_CONGESTION: 11928 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 11929 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 11930 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 11931 break; 11932 default: 11933 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11934 } 11935 break; 11936 } 11937 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); 11938 if (e->hangup.aoc_units > -1) 11939 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 11940 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 11941 } else { 11942 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 11943 pri->pvts[chanpos]->call = NULL; 11944 } 11945 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 11946 ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n", 11947 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11948 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 11949 pri->pvts[chanpos]->resetting = 1; 11950 } 11951 11952 #ifdef SUPPORT_USERUSER 11953 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 11954 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11955 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11956 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 11957 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11958 } 11959 #endif 11960 11961 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11962 } else { 11963 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); 11964 } 11965 } 11966 break; 11967 case PRI_EVENT_HANGUP_ACK: 11968 chanpos = pri_find_principle(pri, e->hangup.channel); 11969 if (chanpos < 0) { 11970 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 11971 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11972 } else { 11973 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 11974 if (chanpos > -1) { 11975 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11976 pri->pvts[chanpos]->call = NULL; 11977 pri->pvts[chanpos]->resetting = 0; 11978 if (pri->pvts[chanpos]->owner) { 11979 ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11980 } 11981 11982 #ifdef SUPPORT_USERUSER 11983 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 11984 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11985 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11986 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 11987 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11988 } 11989 #endif 11990 11991 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11992 } 11993 } 11994 break; 11995 case PRI_EVENT_CONFIG_ERR: 11996 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err); 11997 break; 11998 case PRI_EVENT_RESTART_ACK: 11999 chanpos = pri_find_principle(pri, e->restartack.channel); 12000 if (chanpos < 0) { 12001 /* Sometime switches (e.g. I421 / British Telecom) don't give us the 12002 channel number, so we have to figure it out... This must be why 12003 everybody resets exactly a channel at a time. */ 12004 for (x = 0; x < pri->numchans; x++) { 12005 if (pri->pvts[x] && pri->pvts[x]->resetting) { 12006 chanpos = x; 12007 ast_mutex_lock(&pri->pvts[chanpos]->lock); 12008 ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 12009 pri->pvts[chanpos]->prioffset, pri->span); 12010 if (pri->pvts[chanpos]->realcall) 12011 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 12012 else if (pri->pvts[chanpos]->owner) { 12013 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 12014 pri->pvts[chanpos]->prioffset, pri->span); 12015 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 12016 } 12017 pri->pvts[chanpos]->resetting = 0; 12018 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 12019 pri->pvts[chanpos]->prioffset, pri->span); 12020 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12021 if (pri->resetting) 12022 pri_check_restart(pri); 12023 break; 12024 } 12025 } 12026 if (chanpos < 0) { 12027 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 12028 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 12029 } 12030 } else { 12031 if (pri->pvts[chanpos]) { 12032 ast_mutex_lock(&pri->pvts[chanpos]->lock); 12033 if (pri->pvts[chanpos]->realcall) 12034 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 12035 else if (pri->pvts[chanpos]->owner) { 12036 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n", 12037 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 12038 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 12039 } 12040 pri->pvts[chanpos]->resetting = 0; 12041 pri->pvts[chanpos]->inservice = 1; 12042 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 12043 pri->pvts[chanpos]->prioffset, pri->span); 12044 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12045 if (pri->resetting) 12046 pri_check_restart(pri); 12047 } 12048 } 12049 break; 12050 case PRI_EVENT_SETUP_ACK: 12051 chanpos = pri_find_principle(pri, e->setup_ack.channel); 12052 if (chanpos < 0) { 12053 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 12054 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span); 12055 } else { 12056 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call); 12057 if (chanpos > -1) { 12058 ast_mutex_lock(&pri->pvts[chanpos]->lock); 12059 pri->pvts[chanpos]->setup_ack = 1; 12060 /* Send any queued digits */ 12061 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) { 12062 ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]); 12063 pri_information(pri->pri, pri->pvts[chanpos]->call, 12064 pri->pvts[chanpos]->dialdest[x]); 12065 } 12066 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12067 } else 12068 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel); 12069 } 12070 break; 12071 case PRI_EVENT_NOTIFY: 12072 chanpos = pri_find_principle(pri, e->notify.channel); 12073 if (chanpos < 0) { 12074 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n", 12075 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span); 12076 } else { 12077 struct ast_frame f = { AST_FRAME_CONTROL, }; 12078 ast_mutex_lock(&pri->pvts[chanpos]->lock); 12079 switch (e->notify.info) { 12080 case PRI_NOTIFY_REMOTE_HOLD: 12081 f.subclass = AST_CONTROL_HOLD; 12082 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 12083 break; 12084 case PRI_NOTIFY_REMOTE_RETRIEVAL: 12085 f.subclass = AST_CONTROL_UNHOLD; 12086 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 12087 break; 12088 } 12089 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12090 } 12091 break; 12092 default: 12093 ast_debug(1, "Event: %d\n", e->e); 12094 } 12095 } 12096 ast_mutex_unlock(&pri->lock); 12097 } 12098 /* Never reached */ 12099 return NULL; 12100 }
Definition at line 10631 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pri::crvs, dahdi_pvt::next, and dahdi_pvt::pri.
10632 { 10633 struct dahdi_pvt *p; 10634 p = pri->crvs; 10635 while (p) { 10636 if (p->channel == crv) 10637 return p; 10638 p = p->next; 10639 } 10640 return NULL; 10641 }
static int pri_find_dchan | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3369 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, dahdi_pri::dchans, NUM_DCHANS, and dahdi_pri::pri.
03370 { 03371 int oldslot = -1; 03372 struct pri *old; 03373 int newslot = -1; 03374 int x; 03375 old = pri->pri; 03376 for (x = 0; x < NUM_DCHANS; x++) { 03377 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0)) 03378 newslot = x; 03379 if (pri->dchans[x] == old) { 03380 oldslot = x; 03381 } 03382 } 03383 if (newslot < 0) { 03384 newslot = 0; 03385 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n", 03386 pri->dchannels[newslot]); 03387 } 03388 if (old && (oldslot != newslot)) 03389 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n", 03390 pri->dchannels[oldslot], pri->dchannels[newslot]); 03391 pri->pri = pri->dchans[newslot]; 03392 return 0; 03393 }
static int pri_find_empty_chan | ( | struct dahdi_pri * | pri, | |
int | backwards | |||
) | [static] |
Definition at line 9530 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().
09531 { 09532 int x; 09533 if (backwards) 09534 x = pri->numchans; 09535 else 09536 x = 0; 09537 for (;;) { 09538 if (backwards && (x < 0)) 09539 break; 09540 if (!backwards && (x >= pri->numchans)) 09541 break; 09542 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) { 09543 ast_debug(1, "Found empty available channel %d/%d\n", 09544 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset); 09545 return x; 09546 } 09547 if (backwards) 09548 x--; 09549 else 09550 x++; 09551 } 09552 return -1; 09553 }
static int pri_find_principle | ( | struct dahdi_pri * | pri, | |
int | channel | |||
) | [static] |
Definition at line 10644 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.
10645 { 10646 int x; 10647 int span = PRI_SPAN(channel); 10648 int spanfd; 10649 struct dahdi_params param; 10650 int principle = -1; 10651 int explicit = PRI_EXPLICIT(channel); 10652 channel = PRI_CHANNEL(channel); 10653 10654 if (!explicit) { 10655 spanfd = pri_active_dchan_fd(pri); 10656 memset(¶m, 0, sizeof(param)); 10657 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m)) 10658 return -1; 10659 span = pris[param.spanno - 1].prilogicalspan; 10660 } 10661 10662 for (x = 0; x < pri->numchans; x++) { 10663 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) { 10664 principle = x; 10665 break; 10666 } 10667 } 10668 10669 return principle; 10670 }
static int pri_fixup_principle | ( | struct dahdi_pri * | pri, | |
int | principle, | |||
q931_call * | c | |||
) | [static] |
Definition at line 10672 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.
10673 { 10674 int x; 10675 struct dahdi_pvt *crv; 10676 if (!c) { 10677 if (principle < 0) 10678 return -1; 10679 return principle; 10680 } 10681 if ((principle > -1) && 10682 (principle < pri->numchans) && 10683 (pri->pvts[principle]) && 10684 (pri->pvts[principle]->call == c)) 10685 return principle; 10686 /* First, check for other bearers */ 10687 for (x = 0; x < pri->numchans; x++) { 10688 if (!pri->pvts[x]) 10689 continue; 10690 if (pri->pvts[x]->call == c) { 10691 /* Found our call */ 10692 if (principle != x) { 10693 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x]; 10694 10695 ast_verb(3, "Moving call from channel %d to channel %d\n", 10696 old->channel, new->channel); 10697 if (new->owner) { 10698 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n", 10699 old->channel, new->channel, new->channel); 10700 return -1; 10701 } 10702 /* Fix it all up now */ 10703 new->owner = old->owner; 10704 old->owner = NULL; 10705 if (new->owner) { 10706 ast_string_field_build(new->owner, name, 10707 "DAHDI/%d:%d-%d", pri->trunkgroup, 10708 new->channel, 1); 10709 new->owner->tech_pvt = new; 10710 ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd); 10711 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner; 10712 old->subs[SUB_REAL].owner = NULL; 10713 } else 10714 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); 10715 new->call = old->call; 10716 old->call = NULL; 10717 10718 /* Copy any DSP that may be present */ 10719 new->dsp = old->dsp; 10720 new->dsp_features = old->dsp_features; 10721 old->dsp = NULL; 10722 old->dsp_features = 0; 10723 } 10724 return principle; 10725 } 10726 } 10727 /* Now check for a CRV with no bearer */ 10728 crv = pri->crvs; 10729 while (crv) { 10730 if (crv->call == c) { 10731 /* This is our match... Perform some basic checks */ 10732 if (crv->bearer) 10733 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n"); 10734 else if (pri->pvts[principle]->owner) 10735 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n"); 10736 else { 10737 /* Looks good. Drop the pseudo channel now, clear up the assignment, and 10738 wakeup the potential sleeper */ 10739 dahdi_close_sub(crv, SUB_REAL); 10740 pri->pvts[principle]->call = crv->call; 10741 pri_assign_bearer(crv, pri, pri->pvts[principle]); 10742 ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n", 10743 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset, 10744 pri->trunkgroup, crv->channel); 10745 wakeup_sub(crv, SUB_REAL, pri); 10746 } 10747 return principle; 10748 } 10749 crv = crv->next; 10750 } 10751 ast_log(LOG_WARNING, "Call specified, but not found?\n"); 10752 return -1; 10753 }
Definition at line 1248 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(), dahdi_write(), and ss_thread().
01249 { 01250 int res; 01251 /* Grab the lock first */ 01252 do { 01253 res = ast_mutex_trylock(&pri->lock); 01254 if (res) { 01255 DEADLOCK_AVOIDANCE(&pvt->lock); 01256 } 01257 } while (res); 01258 /* Then break the poll */ 01259 if (pri->master != AST_PTHREADT_NULL) 01260 pthread_kill(pri->master, SIGURG); 01261 return 0; 01262 }
Definition at line 10903 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.
10904 { 10905 int x; 10906 int redo; 10907 ast_mutex_unlock(&pri->lock); 10908 ast_mutex_lock(&p->lock); 10909 do { 10910 redo = 0; 10911 for (x = 0; x < 3; x++) { 10912 while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) { 10913 redo++; 10914 DEADLOCK_AVOIDANCE(&p->lock); 10915 } 10916 if (p->subs[x].owner) { 10917 ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED); 10918 ast_channel_unlock(p->subs[x].owner); 10919 } 10920 } 10921 } while (redo); 10922 ast_mutex_unlock(&p->lock); 10923 ast_mutex_lock(&pri->lock); 10924 return 0; 10925 }
static int pri_is_up | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3317 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, NUM_DCHANS, and dahdi_pvt::pri.
Referenced by pri_dchannel().
03318 { 03319 int x; 03320 for (x = 0; x < NUM_DCHANS; x++) { 03321 if (pri->dchanavail[x] == DCHAN_AVAILABLE) 03322 return 1; 03323 } 03324 return 0; 03325 }
static char* pri_order | ( | int | level | ) | [static] |
Definition at line 3340 of file chan_dahdi.c.
Referenced by handle_pri_show_span().
03341 { 03342 switch (level) { 03343 case 0: 03344 return "Primary"; 03345 case 1: 03346 return "Secondary"; 03347 case 2: 03348 return "Tertiary"; 03349 case 3: 03350 return "Quaternary"; 03351 default: 03352 return "<Unknown>"; 03353 } 03354 }
static void pri_rel | ( | struct dahdi_pri * | pri | ) | [inline, static] |
Definition at line 456 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(), dahdi_write(), and ss_thread().
00457 { 00458 ast_mutex_unlock(&pri->lock); 00459 }
static int pri_resolve_span | ( | int * | span, | |
int | channel, | |||
int | offset, | |||
struct dahdi_spaninfo * | si | |||
) | [static] |
Definition at line 8635 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().
08636 { 08637 int x; 08638 int trunkgroup; 08639 /* Get appropriate trunk group if there is one */ 08640 trunkgroup = pris[*span].mastertrunkgroup; 08641 if (trunkgroup) { 08642 /* Select a specific trunk group */ 08643 for (x = 0; x < NUM_SPANS; x++) { 08644 if (pris[x].trunkgroup == trunkgroup) { 08645 *span = x; 08646 return 0; 08647 } 08648 } 08649 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup); 08650 *span = -1; 08651 } else { 08652 if (pris[*span].trunkgroup) { 08653 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup); 08654 *span = -1; 08655 } else if (pris[*span].mastertrunkgroup) { 08656 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup); 08657 *span = -1; 08658 } else { 08659 if (si->totalchans == 31) { 08660 /* E1 */ 08661 pris[*span].dchannels[0] = 16 + offset; 08662 } else if (si->totalchans == 24) { 08663 /* T1 or J1 */ 08664 pris[*span].dchannels[0] = 24 + offset; 08665 } else if (si->totalchans == 3) { 08666 /* BRI */ 08667 pris[*span].dchannels[0] = 3 + offset; 08668 } else { 08669 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); 08670 *span = -1; 08671 return 0; 08672 } 08673 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED; 08674 pris[*span].offset = offset; 08675 pris[*span].span = *span + 1; 08676 } 08677 } 08678 return 0; 08679 }
static int process_dahdi | ( | struct dahdi_chan_conf * | confp, | |
const char * | cat, | |||
struct ast_variable * | v, | |||
int | reload, | |||
int | options | |||
) | [static] |
Definition at line 14376 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().
14377 { 14378 struct dahdi_pvt *tmp; 14379 int y; 14380 int found_pseudo = 0; 14381 char dahdichan[MAX_CHANLIST_LEN] = {}; 14382 14383 for (; v; v = v->next) { 14384 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 14385 continue; 14386 14387 /* must have parkinglot in confp before build_channels is called */ 14388 if (!strcasecmp(v->name, "parkinglot")) { 14389 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot)); 14390 } 14391 14392 /* Create the interface list */ 14393 if (!strcasecmp(v->name, "channel") 14394 #ifdef HAVE_PRI 14395 || !strcasecmp(v->name, "crv") 14396 #endif 14397 ) { 14398 int iscrv; 14399 if (options & PROC_DAHDI_OPT_NOCHAN) { 14400 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value); 14401 continue; 14402 } 14403 iscrv = !strcasecmp(v->name, "crv"); 14404 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo)) 14405 return -1; 14406 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value); 14407 } else if (!strcasecmp(v->name, "buffers")) { 14408 int res; 14409 char policy[21] = ""; 14410 14411 res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy); 14412 if (res != 2) { 14413 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n"); 14414 confp->chan.buf_no = numbufs; 14415 continue; 14416 } 14417 if (confp->chan.buf_no < 0) 14418 confp->chan.buf_no = numbufs; 14419 if (!strcasecmp(policy, "full")) { 14420 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL; 14421 } else if (!strcasecmp(policy, "immediate")) { 14422 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE; 14423 } else { 14424 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy); 14425 } 14426 } else if (!strcasecmp(v->name, "dahdichan")) { 14427 ast_copy_string(dahdichan, v->value, sizeof(dahdichan)); 14428 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) { 14429 usedistinctiveringdetection = ast_true(v->value); 14430 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) { 14431 distinctiveringaftercid = ast_true(v->value); 14432 } else if (!strcasecmp(v->name, "dring1context")) { 14433 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData)); 14434 } else if (!strcasecmp(v->name, "dring2context")) { 14435 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData)); 14436 } else if (!strcasecmp(v->name, "dring3context")) { 14437 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData)); 14438 } else if (!strcasecmp(v->name, "dring1range")) { 14439 confp->chan.drings.ringnum[0].range = atoi(v->value); 14440 } else if (!strcasecmp(v->name, "dring2range")) { 14441 confp->chan.drings.ringnum[1].range = atoi(v->value); 14442 } else if (!strcasecmp(v->name, "dring3range")) { 14443 confp->chan.drings.ringnum[2].range = atoi(v->value); 14444 } else if (!strcasecmp(v->name, "dring1")) { 14445 sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[0].ring[0], &confp->chan.drings.ringnum[0].ring[1], &confp->chan.drings.ringnum[0].ring[2]); 14446 } else if (!strcasecmp(v->name, "dring2")) { 14447 sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[1].ring[0], &confp->chan.drings.ringnum[1].ring[1], &confp->chan.drings.ringnum[1].ring[2]); 14448 } else if (!strcasecmp(v->name, "dring3")) { 14449 sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[2].ring[0], &confp->chan.drings.ringnum[2].ring[1], &confp->chan.drings.ringnum[2].ring[2]); 14450 } else if (!strcasecmp(v->name, "usecallerid")) { 14451 confp->chan.use_callerid = ast_true(v->value); 14452 } else if (!strcasecmp(v->name, "cidsignalling")) { 14453 if (!strcasecmp(v->value, "bell")) 14454 confp->chan.cid_signalling = CID_SIG_BELL; 14455 else if (!strcasecmp(v->value, "v23")) 14456 confp->chan.cid_signalling = CID_SIG_V23; 14457 else if (!strcasecmp(v->value, "dtmf")) 14458 confp->chan.cid_signalling = CID_SIG_DTMF; 14459 else if (!strcasecmp(v->value, "smdi")) 14460 confp->chan.cid_signalling = CID_SIG_SMDI; 14461 else if (!strcasecmp(v->value, "v23_jp")) 14462 confp->chan.cid_signalling = CID_SIG_V23_JP; 14463 else if (ast_true(v->value)) 14464 confp->chan.cid_signalling = CID_SIG_BELL; 14465 } else if (!strcasecmp(v->name, "cidstart")) { 14466 if (!strcasecmp(v->value, "ring")) 14467 confp->chan.cid_start = CID_START_RING; 14468 else if (!strcasecmp(v->value, "polarity_in")) 14469 confp->chan.cid_start = CID_START_POLARITY_IN; 14470 else if (!strcasecmp(v->value, "polarity")) 14471 confp->chan.cid_start = CID_START_POLARITY; 14472 else if (ast_true(v->value)) 14473 confp->chan.cid_start = CID_START_RING; 14474 } else if (!strcasecmp(v->name, "threewaycalling")) { 14475 confp->chan.threewaycalling = ast_true(v->value); 14476 } else if (!strcasecmp(v->name, "cancallforward")) { 14477 confp->chan.cancallforward = ast_true(v->value); 14478 } else if (!strcasecmp(v->name, "relaxdtmf")) { 14479 if (ast_true(v->value)) 14480 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 14481 else 14482 confp->chan.dtmfrelax = 0; 14483 } else if (!strcasecmp(v->name, "mailbox")) { 14484 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox)); 14485 } else if (!strcasecmp(v->name, "hasvoicemail")) { 14486 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) { 14487 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox)); 14488 } 14489 } else if (!strcasecmp(v->name, "adsi")) { 14490 confp->chan.adsi = ast_true(v->value); 14491 } else if (!strcasecmp(v->name, "usesmdi")) { 14492 confp->chan.use_smdi = ast_true(v->value); 14493 } else if (!strcasecmp(v->name, "smdiport")) { 14494 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port)); 14495 } else if (!strcasecmp(v->name, "transfer")) { 14496 confp->chan.transfer = ast_true(v->value); 14497 } else if (!strcasecmp(v->name, "canpark")) { 14498 confp->chan.canpark = ast_true(v->value); 14499 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) { 14500 confp->chan.echocanbridged = ast_true(v->value); 14501 } else if (!strcasecmp(v->name, "busydetect")) { 14502 confp->chan.busydetect = ast_true(v->value); 14503 } else if (!strcasecmp(v->name, "busycount")) { 14504 confp->chan.busycount = atoi(v->value); 14505 } else if (!strcasecmp(v->name, "silencethreshold")) { 14506 confp->chan.silencethreshold = atoi(v->value); 14507 } else if (!strcasecmp(v->name, "busycompare")) { 14508 confp->chan.busycompare = ast_true(v->value); 14509 } else if (!strcasecmp(v->name, "busypattern")) { 14510 if (sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) { 14511 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno); 14512 } 14513 int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength); 14514 if (count == 1) 14515 confp->chan.busyquietlength = 0; 14516 else if (count < 1) 14517 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno); 14518 } else if (!strcasecmp(v->name, "busyfuzziness")) { 14519 confp->chan.busyfuzziness = atoi(v->value); 14520 } else if (!strcasecmp(v->name, "callprogress")) { 14521 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS; 14522 if (ast_true(v->value)) 14523 confp->chan.callprogress |= CALLPROGRESS_PROGRESS; 14524 } else if (!strcasecmp(v->name, "faxdetect")) { 14525 confp->chan.callprogress &= ~CALLPROGRESS_FAX; 14526 if (!strcasecmp(v->value, "incoming")) { 14527 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING; 14528 } else if (!strcasecmp(v->value, "outgoing")) { 14529 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING; 14530 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) 14531 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING; 14532 } else if (!strcasecmp(v->name, "echocancel")) { 14533 process_echocancel(confp, v->value, v->lineno); 14534 } else if (!strcasecmp(v->name, "echotraining")) { 14535 if (sscanf(v->value, "%30d", &y) == 1) { 14536 if ((y < 10) || (y > 4000)) { 14537 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno); 14538 } else { 14539 confp->chan.echotraining = y; 14540 } 14541 } else if (ast_true(v->value)) { 14542 confp->chan.echotraining = 400; 14543 } else 14544 confp->chan.echotraining = 0; 14545 } else if (!strcasecmp(v->name, "hidecallerid")) { 14546 confp->chan.hidecallerid = ast_true(v->value); 14547 } else if (!strcasecmp(v->name, "hidecalleridname")) { 14548 confp->chan.hidecalleridname = ast_true(v->value); 14549 } else if (!strcasecmp(v->name, "pulsedial")) { 14550 confp->chan.pulse = ast_true(v->value); 14551 } else if (!strcasecmp(v->name, "callreturn")) { 14552 confp->chan.callreturn = ast_true(v->value); 14553 } else if (!strcasecmp(v->name, "callwaiting")) { 14554 confp->chan.callwaiting = ast_true(v->value); 14555 } else if (!strcasecmp(v->name, "callwaitingcallerid")) { 14556 confp->chan.callwaitingcallerid = ast_true(v->value); 14557 } else if (!strcasecmp(v->name, "context")) { 14558 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context)); 14559 } else if (!strcasecmp(v->name, "language")) { 14560 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language)); 14561 } else if (!strcasecmp(v->name, "progzone")) { 14562 ast_copy_string(progzone, v->value, sizeof(progzone)); 14563 } else if (!strcasecmp(v->name, "mohinterpret") 14564 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) { 14565 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret)); 14566 } else if (!strcasecmp(v->name, "mohsuggest")) { 14567 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest)); 14568 } else if (!strcasecmp(v->name, "parkinglot")) { 14569 ast_copy_string(parkinglot, v->value, sizeof(parkinglot)); 14570 } else if (!strcasecmp(v->name, "stripmsd")) { 14571 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name); 14572 confp->chan.stripmsd = atoi(v->value); 14573 } else if (!strcasecmp(v->name, "jitterbuffers")) { 14574 numbufs = atoi(v->value); 14575 } else if (!strcasecmp(v->name, "group")) { 14576 confp->chan.group = ast_get_group(v->value); 14577 } else if (!strcasecmp(v->name, "callgroup")) { 14578 if (!strcasecmp(v->value, "none")) 14579 confp->chan.callgroup = 0; 14580 else 14581 confp->chan.callgroup = ast_get_group(v->value); 14582 } else if (!strcasecmp(v->name, "pickupgroup")) { 14583 if (!strcasecmp(v->value, "none")) 14584 confp->chan.pickupgroup = 0; 14585 else 14586 confp->chan.pickupgroup = ast_get_group(v->value); 14587 } else if (!strcasecmp(v->name, "setvar")) { 14588 char *varname = ast_strdupa(v->value), *varval = NULL; 14589 struct ast_variable *tmpvar; 14590 if (varname && (varval = strchr(varname, '='))) { 14591 *varval++ = '\0'; 14592 if ((tmpvar = ast_variable_new(varname, varval, ""))) { 14593 tmpvar->next = confp->chan.vars; 14594 confp->chan.vars = tmpvar; 14595 } 14596 } 14597 } else if (!strcasecmp(v->name, "immediate")) { 14598 confp->chan.immediate = ast_true(v->value); 14599 } else if (!strcasecmp(v->name, "transfertobusy")) { 14600 confp->chan.transfertobusy = ast_true(v->value); 14601 } else if (!strcasecmp(v->name, "mwimonitor")) { 14602 confp->chan.mwimonitor_neon = 0; 14603 confp->chan.mwimonitor_fsk = 0; 14604 confp->chan.mwimonitor_rpas = 0; 14605 if (strcasestr(v->value, "fsk")) { 14606 confp->chan.mwimonitor_fsk = 1; 14607 } 14608 if (strcasestr(v->value, "rpas")) { 14609 confp->chan.mwimonitor_rpas = 1; 14610 } 14611 if (strcasestr(v->value, "neon")) { 14612 confp->chan.mwimonitor_neon = 1; 14613 } 14614 /* If set to true or yes, assume that simple fsk is desired */ 14615 if (ast_true(v->value)) { 14616 confp->chan.mwimonitor_fsk = 1; 14617 } 14618 } else if (!strcasecmp(v->name, "cid_rxgain")) { 14619 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) { 14620 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno); 14621 } 14622 } else if (!strcasecmp(v->name, "rxgain")) { 14623 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) { 14624 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno); 14625 } 14626 } else if (!strcasecmp(v->name, "txgain")) { 14627 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) { 14628 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno); 14629 } 14630 } else if (!strcasecmp(v->name, "tonezone")) { 14631 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) { 14632 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno); 14633 } 14634 } else if (!strcasecmp(v->name, "callerid")) { 14635 if (!strcasecmp(v->value, "asreceived")) { 14636 confp->chan.cid_num[0] = '\0'; 14637 confp->chan.cid_name[0] = '\0'; 14638 } else { 14639 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num)); 14640 } 14641 } else if (!strcasecmp(v->name, "fullname")) { 14642 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name)); 14643 } else if (!strcasecmp(v->name, "cid_number")) { 14644 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num)); 14645 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) { 14646 confp->chan.dahditrcallerid = ast_true(v->value); 14647 } else if (!strcasecmp(v->name, "restrictcid")) { 14648 confp->chan.restrictcid = ast_true(v->value); 14649 } else if (!strcasecmp(v->name, "usecallingpres")) { 14650 confp->chan.use_callingpres = ast_true(v->value); 14651 } else if (!strcasecmp(v->name, "accountcode")) { 14652 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode)); 14653 } else if (!strcasecmp(v->name, "amaflags")) { 14654 y = ast_cdr_amaflags2int(v->value); 14655 if (y < 0) 14656 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno); 14657 else 14658 confp->chan.amaflags = y; 14659 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) { 14660 confp->chan.polarityonanswerdelay = atoi(v->value); 14661 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) { 14662 confp->chan.answeronpolarityswitch = ast_true(v->value); 14663 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) { 14664 confp->chan.hanguponpolarityswitch = ast_true(v->value); 14665 } else if (!strcasecmp(v->name, "sendcalleridafter")) { 14666 confp->chan.sendcalleridafter = atoi(v->value); 14667 } else if (!strcasecmp(v->name, "mwimonitornotify")) { 14668 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify)); 14669 } else if (!strcasecmp(v->name, "mwisendtype")) { 14670 if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */ 14671 mwisend_rpas = 1; 14672 } else { 14673 mwisend_rpas = 0; 14674 } 14675 } else if (reload != 1) { 14676 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) { 14677 int orig_radio = confp->chan.radio; 14678 int orig_outsigmod = confp->chan.outsigmod; 14679 int orig_auto = confp->is_sig_auto; 14680 14681 confp->chan.radio = 0; 14682 confp->chan.outsigmod = -1; 14683 confp->is_sig_auto = 0; 14684 if (!strcasecmp(v->value, "em")) { 14685 confp->chan.sig = SIG_EM; 14686 } else if (!strcasecmp(v->value, "em_e1")) { 14687 confp->chan.sig = SIG_EM_E1; 14688 } else if (!strcasecmp(v->value, "em_w")) { 14689 confp->chan.sig = SIG_EMWINK; 14690 } else if (!strcasecmp(v->value, "fxs_ls")) { 14691 confp->chan.sig = SIG_FXSLS; 14692 } else if (!strcasecmp(v->value, "fxs_gs")) { 14693 confp->chan.sig = SIG_FXSGS; 14694 } else if (!strcasecmp(v->value, "fxs_ks")) { 14695 confp->chan.sig = SIG_FXSKS; 14696 } else if (!strcasecmp(v->value, "fxo_ls")) { 14697 confp->chan.sig = SIG_FXOLS; 14698 } else if (!strcasecmp(v->value, "fxo_gs")) { 14699 confp->chan.sig = SIG_FXOGS; 14700 } else if (!strcasecmp(v->value, "fxo_ks")) { 14701 confp->chan.sig = SIG_FXOKS; 14702 } else if (!strcasecmp(v->value, "fxs_rx")) { 14703 confp->chan.sig = SIG_FXSKS; 14704 confp->chan.radio = 1; 14705 } else if (!strcasecmp(v->value, "fxo_rx")) { 14706 confp->chan.sig = SIG_FXOLS; 14707 confp->chan.radio = 1; 14708 } else if (!strcasecmp(v->value, "fxs_tx")) { 14709 confp->chan.sig = SIG_FXSLS; 14710 confp->chan.radio = 1; 14711 } else if (!strcasecmp(v->value, "fxo_tx")) { 14712 confp->chan.sig = SIG_FXOGS; 14713 confp->chan.radio = 1; 14714 } else if (!strcasecmp(v->value, "em_rx")) { 14715 confp->chan.sig = SIG_EM; 14716 confp->chan.radio = 1; 14717 } else if (!strcasecmp(v->value, "em_tx")) { 14718 confp->chan.sig = SIG_EM; 14719 confp->chan.radio = 1; 14720 } else if (!strcasecmp(v->value, "em_rxtx")) { 14721 confp->chan.sig = SIG_EM; 14722 confp->chan.radio = 2; 14723 } else if (!strcasecmp(v->value, "em_txrx")) { 14724 confp->chan.sig = SIG_EM; 14725 confp->chan.radio = 2; 14726 } else if (!strcasecmp(v->value, "sf")) { 14727 confp->chan.sig = SIG_SF; 14728 } else if (!strcasecmp(v->value, "sf_w")) { 14729 confp->chan.sig = SIG_SFWINK; 14730 } else if (!strcasecmp(v->value, "sf_featd")) { 14731 confp->chan.sig = SIG_FEATD; 14732 } else if (!strcasecmp(v->value, "sf_featdmf")) { 14733 confp->chan.sig = SIG_FEATDMF; 14734 } else if (!strcasecmp(v->value, "sf_featb")) { 14735 confp->chan.sig = SIG_SF_FEATB; 14736 } else if (!strcasecmp(v->value, "sf")) { 14737 confp->chan.sig = SIG_SF; 14738 } else if (!strcasecmp(v->value, "sf_rx")) { 14739 confp->chan.sig = SIG_SF; 14740 confp->chan.radio = 1; 14741 } else if (!strcasecmp(v->value, "sf_tx")) { 14742 confp->chan.sig = SIG_SF; 14743 confp->chan.radio = 1; 14744 } else if (!strcasecmp(v->value, "sf_rxtx")) { 14745 confp->chan.sig = SIG_SF; 14746 confp->chan.radio = 2; 14747 } else if (!strcasecmp(v->value, "sf_txrx")) { 14748 confp->chan.sig = SIG_SF; 14749 confp->chan.radio = 2; 14750 } else if (!strcasecmp(v->value, "featd")) { 14751 confp->chan.sig = SIG_FEATD; 14752 } else if (!strcasecmp(v->value, "featdmf")) { 14753 confp->chan.sig = SIG_FEATDMF; 14754 } else if (!strcasecmp(v->value, "featdmf_ta")) { 14755 confp->chan.sig = SIG_FEATDMF_TA; 14756 } else if (!strcasecmp(v->value, "e911")) { 14757 confp->chan.sig = SIG_E911; 14758 } else if (!strcasecmp(v->value, "fgccama")) { 14759 confp->chan.sig = SIG_FGC_CAMA; 14760 } else if (!strcasecmp(v->value, "fgccamamf")) { 14761 confp->chan.sig = SIG_FGC_CAMAMF; 14762 } else if (!strcasecmp(v->value, "featb")) { 14763 confp->chan.sig = SIG_FEATB; 14764 #ifdef HAVE_PRI 14765 } else if (!strcasecmp(v->value, "pri_net")) { 14766 confp->chan.sig = SIG_PRI; 14767 confp->pri.nodetype = PRI_NETWORK; 14768 } else if (!strcasecmp(v->value, "pri_cpe")) { 14769 confp->chan.sig = SIG_PRI; 14770 confp->pri.nodetype = PRI_CPE; 14771 } else if (!strcasecmp(v->value, "bri_cpe")) { 14772 confp->chan.sig = SIG_BRI; 14773 confp->pri.nodetype = PRI_CPE; 14774 } else if (!strcasecmp(v->value, "bri_net")) { 14775 confp->chan.sig = SIG_BRI; 14776 confp->pri.nodetype = PRI_NETWORK; 14777 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) { 14778 confp->chan.sig = SIG_BRI_PTMP; 14779 confp->pri.nodetype = PRI_CPE; 14780 } else if (!strcasecmp(v->value, "bri_net_ptmp")) { 14781 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno); 14782 } else if (!strcasecmp(v->value, "gr303fxoks_net")) { 14783 confp->chan.sig = SIG_GR303FXOKS; 14784 confp->pri.nodetype = PRI_NETWORK; 14785 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) { 14786 confp->chan.sig = SIG_GR303FXSKS; 14787 confp->pri.nodetype = PRI_CPE; 14788 #endif 14789 #ifdef HAVE_SS7 14790 } else if (!strcasecmp(v->value, "ss7")) { 14791 confp->chan.sig = SIG_SS7; 14792 #endif 14793 } else if (!strcasecmp(v->value, "auto")) { 14794 confp->is_sig_auto = 1; 14795 } else { 14796 confp->chan.outsigmod = orig_outsigmod; 14797 confp->chan.radio = orig_radio; 14798 confp->is_sig_auto = orig_auto; 14799 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 14800 } 14801 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) { 14802 if (!strcasecmp(v->value, "em")) { 14803 confp->chan.outsigmod = SIG_EM; 14804 } else if (!strcasecmp(v->value, "em_e1")) { 14805 confp->chan.outsigmod = SIG_EM_E1; 14806 } else if (!strcasecmp(v->value, "em_w")) { 14807 confp->chan.outsigmod = SIG_EMWINK; 14808 } else if (!strcasecmp(v->value, "sf")) { 14809 confp->chan.outsigmod = SIG_SF; 14810 } else if (!strcasecmp(v->value, "sf_w")) { 14811 confp->chan.outsigmod = SIG_SFWINK; 14812 } else if (!strcasecmp(v->value, "sf_featd")) { 14813 confp->chan.outsigmod = SIG_FEATD; 14814 } else if (!strcasecmp(v->value, "sf_featdmf")) { 14815 confp->chan.outsigmod = SIG_FEATDMF; 14816 } else if (!strcasecmp(v->value, "sf_featb")) { 14817 confp->chan.outsigmod = SIG_SF_FEATB; 14818 } else if (!strcasecmp(v->value, "sf")) { 14819 confp->chan.outsigmod = SIG_SF; 14820 } else if (!strcasecmp(v->value, "featd")) { 14821 confp->chan.outsigmod = SIG_FEATD; 14822 } else if (!strcasecmp(v->value, "featdmf")) { 14823 confp->chan.outsigmod = SIG_FEATDMF; 14824 } else if (!strcasecmp(v->value, "featdmf_ta")) { 14825 confp->chan.outsigmod = SIG_FEATDMF_TA; 14826 } else if (!strcasecmp(v->value, "e911")) { 14827 confp->chan.outsigmod = SIG_E911; 14828 } else if (!strcasecmp(v->value, "fgccama")) { 14829 confp->chan.outsigmod = SIG_FGC_CAMA; 14830 } else if (!strcasecmp(v->value, "fgccamamf")) { 14831 confp->chan.outsigmod = SIG_FGC_CAMAMF; 14832 } else if (!strcasecmp(v->value, "featb")) { 14833 confp->chan.outsigmod = SIG_FEATB; 14834 } else { 14835 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 14836 } 14837 #ifdef HAVE_PRI 14838 } else if (!strcasecmp(v->name, "pridialplan")) { 14839 if (!strcasecmp(v->value, "national")) { 14840 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1; 14841 } else if (!strcasecmp(v->value, "unknown")) { 14842 confp->pri.dialplan = PRI_UNKNOWN + 1; 14843 } else if (!strcasecmp(v->value, "private")) { 14844 confp->pri.dialplan = PRI_PRIVATE + 1; 14845 } else if (!strcasecmp(v->value, "international")) { 14846 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1; 14847 } else if (!strcasecmp(v->value, "local")) { 14848 confp->pri.dialplan = PRI_LOCAL_ISDN + 1; 14849 } else if (!strcasecmp(v->value, "dynamic")) { 14850 confp->pri.dialplan = -1; 14851 } else if (!strcasecmp(v->value, "redundant")) { 14852 confp->pri.dialplan = -2; 14853 } else { 14854 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 14855 } 14856 } else if (!strcasecmp(v->name, "prilocaldialplan")) { 14857 if (!strcasecmp(v->value, "national")) { 14858 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1; 14859 } else if (!strcasecmp(v->value, "unknown")) { 14860 confp->pri.localdialplan = PRI_UNKNOWN + 1; 14861 } else if (!strcasecmp(v->value, "private")) { 14862 confp->pri.localdialplan = PRI_PRIVATE + 1; 14863 } else if (!strcasecmp(v->value, "international")) { 14864 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1; 14865 } else if (!strcasecmp(v->value, "local")) { 14866 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1; 14867 } else if (!strcasecmp(v->value, "dynamic")) { 14868 confp->pri.localdialplan = -1; 14869 } else if (!strcasecmp(v->value, "redundant")) { 14870 confp->pri.localdialplan = -2; 14871 } else { 14872 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno); 14873 } 14874 } else if (!strcasecmp(v->name, "switchtype")) { 14875 if (!strcasecmp(v->value, "national")) 14876 confp->pri.switchtype = PRI_SWITCH_NI2; 14877 else if (!strcasecmp(v->value, "ni1")) 14878 confp->pri.switchtype = PRI_SWITCH_NI1; 14879 else if (!strcasecmp(v->value, "dms100")) 14880 confp->pri.switchtype = PRI_SWITCH_DMS100; 14881 else if (!strcasecmp(v->value, "4ess")) 14882 confp->pri.switchtype = PRI_SWITCH_ATT4ESS; 14883 else if (!strcasecmp(v->value, "5ess")) 14884 confp->pri.switchtype = PRI_SWITCH_LUCENT5E; 14885 else if (!strcasecmp(v->value, "euroisdn")) 14886 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1; 14887 else if (!strcasecmp(v->value, "qsig")) 14888 confp->pri.switchtype = PRI_SWITCH_QSIG; 14889 else { 14890 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno); 14891 return -1; 14892 } 14893 } else if (!strcasecmp(v->name, "nsf")) { 14894 if (!strcasecmp(v->value, "sdn")) 14895 confp->pri.nsf = PRI_NSF_SDN; 14896 else if (!strcasecmp(v->value, "megacom")) 14897 confp->pri.nsf = PRI_NSF_MEGACOM; 14898 else if (!strcasecmp(v->value, "tollfreemegacom")) 14899 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM; 14900 else if (!strcasecmp(v->value, "accunet")) 14901 confp->pri.nsf = PRI_NSF_ACCUNET; 14902 else if (!strcasecmp(v->value, "none")) 14903 confp->pri.nsf = PRI_NSF_NONE; 14904 else { 14905 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno); 14906 confp->pri.nsf = PRI_NSF_NONE; 14907 } 14908 } else if (!strcasecmp(v->name, "priindication")) { 14909 if (!strcasecmp(v->value, "outofband")) 14910 confp->chan.priindication_oob = 1; 14911 else if (!strcasecmp(v->value, "inband")) 14912 confp->chan.priindication_oob = 0; 14913 else 14914 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n", 14915 v->value, v->lineno); 14916 } else if (!strcasecmp(v->name, "priexclusive")) { 14917 confp->chan.priexclusive = ast_true(v->value); 14918 } else if (!strcasecmp(v->name, "internationalprefix")) { 14919 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix)); 14920 } else if (!strcasecmp(v->name, "nationalprefix")) { 14921 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix)); 14922 } else if (!strcasecmp(v->name, "localprefix")) { 14923 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix)); 14924 } else if (!strcasecmp(v->name, "privateprefix")) { 14925 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix)); 14926 } else if (!strcasecmp(v->name, "unknownprefix")) { 14927 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix)); 14928 } else if (!strcasecmp(v->name, "resetinterval")) { 14929 if (!strcasecmp(v->value, "never")) 14930 confp->pri.resetinterval = -1; 14931 else if (atoi(v->value) >= 60) 14932 confp->pri.resetinterval = atoi(v->value); 14933 else 14934 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n", 14935 v->value, v->lineno); 14936 } else if (!strcasecmp(v->name, "minunused")) { 14937 confp->pri.minunused = atoi(v->value); 14938 } else if (!strcasecmp(v->name, "minidle")) { 14939 confp->pri.minidle = atoi(v->value); 14940 } else if (!strcasecmp(v->name, "idleext")) { 14941 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext)); 14942 } else if (!strcasecmp(v->name, "idledial")) { 14943 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial)); 14944 } else if (!strcasecmp(v->name, "overlapdial")) { 14945 if (ast_true(v->value)) { 14946 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 14947 } else if (!strcasecmp(v->value, "incoming")) { 14948 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING; 14949 } else if (!strcasecmp(v->value, "outgoing")) { 14950 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING; 14951 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) { 14952 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 14953 } else { 14954 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE; 14955 } 14956 #ifdef HAVE_PRI_INBANDDISCONNECT 14957 } else if (!strcasecmp(v->name, "inbanddisconnect")) { 14958 confp->pri.inbanddisconnect = ast_true(v->value); 14959 #endif 14960 } else if (!strcasecmp(v->name, "pritimer")) { 14961 #ifdef PRI_GETSET_TIMERS 14962 char tmp[20]; 14963 char *timerc; 14964 char *c; 14965 int timer; 14966 int timeridx; 14967 14968 ast_copy_string(tmp, v->value, sizeof(tmp)); 14969 c = tmp; 14970 timerc = strsep(&c, ","); 14971 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) { 14972 timeridx = pri_timer2idx(timerc); 14973 timer = atoi(c); 14974 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) { 14975 ast_log(LOG_WARNING, 14976 "'%s' is not a valid ISDN timer at line %d.\n", timerc, 14977 v->lineno); 14978 } else if (!timer) { 14979 ast_log(LOG_WARNING, 14980 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n", 14981 c, timerc, v->lineno); 14982 } else { 14983 pritimers[timeridx] = timer; 14984 } 14985 } else { 14986 ast_log(LOG_WARNING, 14987 "'%s' is not a valid ISDN timer configuration string at line %d.\n", 14988 v->value, v->lineno); 14989 } 14990 14991 } else if (!strcasecmp(v->name, "facilityenable")) { 14992 confp->pri.facilityenable = ast_true(v->value); 14993 #endif /* PRI_GETSET_TIMERS */ 14994 #endif /* HAVE_PRI */ 14995 #ifdef HAVE_SS7 14996 } else if (!strcasecmp(v->name, "ss7type")) { 14997 if (!strcasecmp(v->value, "itu")) { 14998 cur_ss7type = SS7_ITU; 14999 } else if (!strcasecmp(v->value, "ansi")) { 15000 cur_ss7type = SS7_ANSI; 15001 } else 15002 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno); 15003 } else if (!strcasecmp(v->name, "linkset")) { 15004 cur_linkset = atoi(v->value); 15005 } else if (!strcasecmp(v->name, "pointcode")) { 15006 cur_pointcode = parse_pointcode(v->value); 15007 } else if (!strcasecmp(v->name, "adjpointcode")) { 15008 cur_adjpointcode = parse_pointcode(v->value); 15009 } else if (!strcasecmp(v->name, "defaultdpc")) { 15010 cur_defaultdpc = parse_pointcode(v->value); 15011 } else if (!strcasecmp(v->name, "cicbeginswith")) { 15012 cur_cicbeginswith = atoi(v->value); 15013 } else if (!strcasecmp(v->name, "networkindicator")) { 15014 if (!strcasecmp(v->value, "national")) 15015 cur_networkindicator = SS7_NI_NAT; 15016 else if (!strcasecmp(v->value, "national_spare")) 15017 cur_networkindicator = SS7_NI_NAT_SPARE; 15018 else if (!strcasecmp(v->value, "international")) 15019 cur_networkindicator = SS7_NI_INT; 15020 else if (!strcasecmp(v->value, "international_spare")) 15021 cur_networkindicator = SS7_NI_INT_SPARE; 15022 else 15023 cur_networkindicator = -1; 15024 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) { 15025 ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix)); 15026 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) { 15027 ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix)); 15028 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) { 15029 ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix)); 15030 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) { 15031 ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix)); 15032 } else if (!strcasecmp(v->name, "ss7_called_nai")) { 15033 if (!strcasecmp(v->value, "national")) { 15034 confp->ss7.called_nai = SS7_NAI_NATIONAL; 15035 } else if (!strcasecmp(v->value, "international")) { 15036 confp->ss7.called_nai = SS7_NAI_INTERNATIONAL; 15037 } else if (!strcasecmp(v->value, "subscriber")) { 15038 confp->ss7.called_nai = SS7_NAI_SUBSCRIBER; 15039 } else if (!strcasecmp(v->value, "dynamic")) { 15040 confp->ss7.called_nai = SS7_NAI_DYNAMIC; 15041 } else { 15042 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno); 15043 } 15044 } else if (!strcasecmp(v->name, "ss7_calling_nai")) { 15045 if (!strcasecmp(v->value, "national")) { 15046 confp->ss7.calling_nai = SS7_NAI_NATIONAL; 15047 } else if (!strcasecmp(v->value, "international")) { 15048 confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL; 15049 } else if (!strcasecmp(v->value, "subscriber")) { 15050 confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER; 15051 } else if (!strcasecmp(v->value, "dynamic")) { 15052 confp->ss7.calling_nai = SS7_NAI_DYNAMIC; 15053 } else { 15054 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno); 15055 } 15056 } else if (!strcasecmp(v->name, "sigchan")) { 15057 int sigchan, res; 15058 sigchan = atoi(v->value); 15059 res = linkset_addsigchan(sigchan); 15060 if (res < 0) 15061 return -1; 15062 15063 } else if (!strcasecmp(v->name, "ss7_explicitacm")) { 15064 struct dahdi_ss7 *link; 15065 link = ss7_resolve_linkset(cur_linkset); 15066 if (!link) { 15067 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1); 15068 return -1; 15069 } 15070 if (ast_true(v->value)) 15071 link->flags |= LINKSET_FLAG_EXPLICITACM; 15072 15073 #endif /* HAVE_SS7 */ 15074 } else if (!strcasecmp(v->name, "cadence")) { 15075 /* setup to scan our argument */ 15076 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 15077 int i; 15078 struct dahdi_ring_cadence new_cadence; 15079 int cid_location = -1; 15080 int firstcadencepos = 0; 15081 char original_args[80]; 15082 int cadence_is_ok = 1; 15083 15084 ast_copy_string(original_args, v->value, sizeof(original_args)); 15085 /* 16 cadences allowed (8 pairs) */ 15086 element_count = sscanf(v->value, "%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d", &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]); 15087 15088 /* Cadence must be even (on/off) */ 15089 if (element_count % 2 == 1) { 15090 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno); 15091 cadence_is_ok = 0; 15092 } 15093 15094 /* Ring cadences cannot be negative */ 15095 for (i = 0; i < element_count; i++) { 15096 if (c[i] == 0) { 15097 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno); 15098 cadence_is_ok = 0; 15099 break; 15100 } else if (c[i] < 0) { 15101 if (i % 2 == 1) { 15102 /* Silence duration, negative possibly okay */ 15103 if (cid_location == -1) { 15104 cid_location = i; 15105 c[i] *= -1; 15106 } else { 15107 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno); 15108 cadence_is_ok = 0; 15109 break; 15110 } 15111 } else { 15112 if (firstcadencepos == 0) { 15113 firstcadencepos = i; /* only recorded to avoid duplicate specification */ 15114 /* duration will be passed negative to the DAHDI driver */ 15115 } else { 15116 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno); 15117 cadence_is_ok = 0; 15118 break; 15119 } 15120 } 15121 } 15122 } 15123 15124 /* Substitute our scanned cadence */ 15125 for (i = 0; i < 16; i++) { 15126 new_cadence.ringcadence[i] = c[i]; 15127 } 15128 15129 if (cadence_is_ok) { 15130 /* ---we scanned it without getting annoyed; now some sanity checks--- */ 15131 if (element_count < 2) { 15132 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno); 15133 } else { 15134 if (cid_location == -1) { 15135 /* user didn't say; default to first pause */ 15136 cid_location = 1; 15137 } else { 15138 /* convert element_index to cidrings value */ 15139 cid_location = (cid_location + 1) / 2; 15140 } 15141 /* ---we like their cadence; try to install it--- */ 15142 if (!user_has_defined_cadences++) 15143 /* this is the first user-defined cadence; clear the default user cadences */ 15144 num_cadence = 0; 15145 if ((num_cadence+1) >= NUM_CADENCE_MAX) 15146 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno); 15147 else { 15148 cadences[num_cadence] = new_cadence; 15149 cidrings[num_cadence++] = cid_location; 15150 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args); 15151 } 15152 } 15153 } 15154 } else if (!strcasecmp(v->name, "ringtimeout")) { 15155 ringt_base = (atoi(v->value) * 8) / READ_SIZE; 15156 } else if (!strcasecmp(v->name, "prewink")) { 15157 confp->timing.prewinktime = atoi(v->value); 15158 } else if (!strcasecmp(v->name, "preflash")) { 15159 confp->timing.preflashtime = atoi(v->value); 15160 } else if (!strcasecmp(v->name, "wink")) { 15161 confp->timing.winktime = atoi(v->value); 15162 } else if (!strcasecmp(v->name, "flash")) { 15163 confp->timing.flashtime = atoi(v->value); 15164 } else if (!strcasecmp(v->name, "start")) { 15165 confp->timing.starttime = atoi(v->value); 15166 } else if (!strcasecmp(v->name, "rxwink")) { 15167 confp->timing.rxwinktime = atoi(v->value); 15168 } else if (!strcasecmp(v->name, "rxflash")) { 15169 confp->timing.rxflashtime = atoi(v->value); 15170 } else if (!strcasecmp(v->name, "debounce")) { 15171 confp->timing.debouncetime = atoi(v->value); 15172 } else if (!strcasecmp(v->name, "toneduration")) { 15173 int toneduration; 15174 int ctlfd; 15175 int res; 15176 struct dahdi_dialparams dps; 15177 15178 ctlfd = open("/dev/dahdi/ctl", O_RDWR); 15179 if (ctlfd == -1) { 15180 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno); 15181 return -1; 15182 } 15183 15184 toneduration = atoi(v->value); 15185 if (toneduration > -1) { 15186 memset(&dps, 0, sizeof(dps)); 15187 15188 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration; 15189 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps); 15190 if (res < 0) { 15191 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno)); 15192 return -1; 15193 } 15194 } 15195 close(ctlfd); 15196 } else if (!strcasecmp(v->name, "defaultcic")) { 15197 ast_copy_string(defaultcic, v->value, sizeof(defaultcic)); 15198 } else if (!strcasecmp(v->name, "defaultozz")) { 15199 ast_copy_string(defaultozz, v->value, sizeof(defaultozz)); 15200 } else if (!strcasecmp(v->name, "mwilevel")) { 15201 mwilevel = atoi(v->value); 15202 } 15203 } else if (!(options & PROC_DAHDI_OPT_NOWARN) ) 15204 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno); 15205 } 15206 if (dahdichan[0]) { 15207 /* The user has set 'dahdichan' */ 15208 /*< \todo pass proper line number instead of 0 */ 15209 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) { 15210 return -1; 15211 } 15212 } 15213 /*< \todo why check for the pseudo in the per-channel section. 15214 * Any actual use for manual setup of the pseudo channel? */ 15215 if (!found_pseudo && reload != 1) { 15216 /* use the default configuration for a channel, so 15217 that any settings from real configured channels 15218 don't "leak" into the pseudo channel config 15219 */ 15220 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 15221 15222 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload); 15223 15224 if (tmp) { 15225 ast_verb(3, "Automatically generated pseudo channel\n"); 15226 } else { 15227 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n"); 15228 } 15229 } 15230 return 0; 15231 }
static void process_echocancel | ( | struct dahdi_chan_conf * | confp, | |
const char * | data, | |||
unsigned int | line | |||
) | [static] |
Definition at line 14320 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().
14321 { 14322 char *parse = ast_strdupa(data); 14323 char *params[DAHDI_MAX_ECHOCANPARAMS + 1]; 14324 unsigned int param_count; 14325 unsigned int x; 14326 14327 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params)))) 14328 return; 14329 14330 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel)); 14331 14332 /* first parameter is tap length, process it here */ 14333 14334 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]); 14335 14336 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024)) 14337 confp->chan.echocancel.head.tap_length = x; 14338 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0]))) 14339 confp->chan.echocancel.head.tap_length = 128; 14340 14341 /* now process any remaining parameters */ 14342 14343 for (x = 1; x < param_count; x++) { 14344 struct { 14345 char *name; 14346 char *value; 14347 } param; 14348 14349 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) { 14350 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]); 14351 continue; 14352 } 14353 14354 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) { 14355 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name); 14356 continue; 14357 } 14358 14359 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name); 14360 14361 if (param.value) { 14362 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) { 14363 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value); 14364 continue; 14365 } 14366 } 14367 confp->chan.echocancel.head.param_count++; 14368 } 14369 }
static char* redirectingreason2str | ( | int | redirectingreason | ) | [static] |
Definition at line 10927 of file chan_dahdi.c.
Referenced by __oh323_new().
10928 { 10929 switch (redirectingreason) { 10930 case 0: 10931 return "UNKNOWN"; 10932 case 1: 10933 return "BUSY"; 10934 case 2: 10935 return "NO_REPLY"; 10936 case 0xF: 10937 return "UNCONDITIONAL"; 10938 default: 10939 return "NOREDIRECT"; 10940 } 10941 }
static int reload | ( | void | ) | [static] |
Definition at line 15601 of file chan_dahdi.c.
References ast_log(), and setup_dahdi().
15602 { 15603 int res = 0; 15604 15605 res = setup_dahdi(1); 15606 if (res) { 15607 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n"); 15608 return -1; 15609 } 15610 return 0; 15611 }
static int reset_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1951 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().
01952 { 01953 p->confno = -1; 01954 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf)); 01955 if (p->subs[SUB_REAL].dfd > -1) { 01956 struct dahdi_confinfo zi; 01957 01958 memset(&zi, 0, sizeof(zi)); 01959 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi)) 01960 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno)); 01961 } 01962 return 0; 01963 }
static int restart_monitor | ( | void | ) | [static] |
Definition at line 8608 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().
08609 { 08610 /* If we're supposed to be stopped -- stay stopped */ 08611 if (monitor_thread == AST_PTHREADT_STOP) 08612 return 0; 08613 ast_mutex_lock(&monlock); 08614 if (monitor_thread == pthread_self()) { 08615 ast_mutex_unlock(&monlock); 08616 ast_log(LOG_WARNING, "Cannot kill myself\n"); 08617 return -1; 08618 } 08619 if (monitor_thread != AST_PTHREADT_NULL) { 08620 /* Wake up the thread */ 08621 pthread_kill(monitor_thread, SIGURG); 08622 } else { 08623 /* Start a new monitor */ 08624 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 08625 ast_mutex_unlock(&monlock); 08626 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 08627 return -1; 08628 } 08629 } 08630 ast_mutex_unlock(&monlock); 08631 return 0; 08632 }
static int restore_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2330 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().
02331 { 02332 int res; 02333 if (p->saveconf.confmode) { 02334 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf); 02335 p->saveconf.confmode = 0; 02336 if (res) { 02337 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno)); 02338 return -1; 02339 } 02340 } 02341 ast_debug(1, "Restored conferencing\n"); 02342 return 0; 02343 }
static int restore_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2211 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().
02212 { 02213 int res; 02214 02215 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02216 if (res) { 02217 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno)); 02218 return -1; 02219 } 02220 02221 return 0; 02222 }
static int save_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2257 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().
02258 { 02259 struct dahdi_confinfo c; 02260 int res; 02261 if (p->saveconf.confmode) { 02262 ast_log(LOG_WARNING, "Can't save conference -- already in use\n"); 02263 return -1; 02264 } 02265 p->saveconf.chan = 0; 02266 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf); 02267 if (res) { 02268 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno)); 02269 p->saveconf.confmode = 0; 02270 return -1; 02271 } 02272 memset(&c, 0, sizeof(c)); 02273 c.confmode = DAHDI_CONF_NORMAL; 02274 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c); 02275 if (res) { 02276 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno)); 02277 return -1; 02278 } 02279 ast_debug(1, "Disabled conferencing\n"); 02280 return 0; 02281 }
static int send_callerid | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2387 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().
02388 { 02389 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */ 02390 int res; 02391 /* Take out of linear mode if necessary */ 02392 if (p->subs[SUB_REAL].linear) { 02393 p->subs[SUB_REAL].linear = 0; 02394 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 02395 } 02396 while (p->cidpos < p->cidlen) { 02397 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos); 02398 if (res < 0) { 02399 if (errno == EAGAIN) 02400 return 0; 02401 else { 02402 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 02403 return -1; 02404 } 02405 } 02406 if (!res) 02407 return 0; 02408 p->cidpos += res; 02409 } 02410 ast_free(p->cidspill); 02411 p->cidspill = NULL; 02412 if (p->callwaitcas) { 02413 /* Wait for CID/CW to expire */ 02414 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES; 02415 } else 02416 restore_conference(p); 02417 return 0; 02418 }
static int send_cwcidspill | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2347 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().
02348 { 02349 p->callwaitcas = 0; 02350 p->cidcwexpire = 0; 02351 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) 02352 return -1; 02353 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p)); 02354 /* Make sure we account for the end */ 02355 p->cidlen += READ_SIZE * 4; 02356 p->cidpos = 0; 02357 send_callerid(p); 02358 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num); 02359 return 0; 02360 }
static int set_actual_gain | ( | int | fd, | |
int | chan, | |||
float | rxgain, | |||
float | txgain, | |||
int | law | |||
) | [static] |
Definition at line 2192 of file chan_dahdi.c.
References set_actual_rxgain(), and set_actual_txgain().
Referenced by bump_gains(), dahdi_call(), and restore_gains().
02193 { 02194 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law); 02195 }
static int set_actual_rxgain | ( | int | fd, | |
int | chan, | |||
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2174 of file chan_dahdi.c.
References ast_debug, errno, and fill_rxgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
02175 { 02176 struct dahdi_gains g; 02177 int res; 02178 02179 memset(&g, 0, sizeof(g)); 02180 g.chan = chan; 02181 res = ioctl(fd, DAHDI_GETGAINS, &g); 02182 if (res) { 02183 ast_debug(1, "Failed to read gains: %s\n", strerror(errno)); 02184 return res; 02185 } 02186 02187 fill_rxgain(&g, gain, law); 02188 02189 return ioctl(fd, DAHDI_SETGAINS, &g); 02190 }
static int set_actual_txgain | ( | int | fd, | |
int | chan, | |||
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2156 of file chan_dahdi.c.
References ast_debug, errno, and fill_txgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
02157 { 02158 struct dahdi_gains g; 02159 int res; 02160 02161 memset(&g, 0, sizeof(g)); 02162 g.chan = chan; 02163 res = ioctl(fd, DAHDI_GETGAINS, &g); 02164 if (res) { 02165 ast_debug(1, "Failed to read gains: %s\n", strerror(errno)); 02166 return res; 02167 } 02168 02169 fill_txgain(&g, gain, law); 02170 02171 return ioctl(fd, DAHDI_SETGAINS, &g); 02172 }
static int setup_dahdi | ( | int | reload | ) | [static] |
Definition at line 15233 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().
15234 { 15235 struct ast_config *cfg, *ucfg; 15236 struct ast_variable *v; 15237 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default(); 15238 struct dahdi_chan_conf conf; 15239 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 15240 const char *cat; 15241 int res; 15242 15243 #ifdef HAVE_PRI 15244 char *c; 15245 int spanno; 15246 int i; 15247 int logicalspan; 15248 int trunkgroup; 15249 int dchannels[NUM_DCHANS]; 15250 #endif 15251 15252 cfg = ast_config_load(config, config_flags); 15253 15254 /* Error if we have no config file */ 15255 if (!cfg) { 15256 ast_log(LOG_ERROR, "Unable to load config %s\n", config); 15257 return 0; 15258 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 15259 ucfg = ast_config_load("users.conf", config_flags); 15260 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) 15261 return 0; 15262 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 15263 cfg = ast_config_load(config, config_flags); 15264 } else { 15265 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 15266 ucfg = ast_config_load("users.conf", config_flags); 15267 } 15268 15269 /* It's a little silly to lock it, but we mind as well just to be sure */ 15270 ast_mutex_lock(&iflock); 15271 #ifdef HAVE_PRI 15272 if (reload != 1) { 15273 /* Process trunkgroups first */ 15274 v = ast_variable_browse(cfg, "trunkgroups"); 15275 while (v) { 15276 if (!strcasecmp(v->name, "trunkgroup")) { 15277 trunkgroup = atoi(v->value); 15278 if (trunkgroup > 0) { 15279 if ((c = strchr(v->value, ','))) { 15280 i = 0; 15281 memset(dchannels, 0, sizeof(dchannels)); 15282 while (c && (i < NUM_DCHANS)) { 15283 dchannels[i] = atoi(c + 1); 15284 if (dchannels[i] < 0) { 15285 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); 15286 } else 15287 i++; 15288 c = strchr(c + 1, ','); 15289 } 15290 if (i) { 15291 if (pri_create_trunkgroup(trunkgroup, dchannels)) { 15292 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); 15293 } else 15294 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"); 15295 } else 15296 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 15297 } else 15298 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 15299 } else 15300 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno); 15301 } else if (!strcasecmp(v->name, "spanmap")) { 15302 spanno = atoi(v->value); 15303 if (spanno > 0) { 15304 if ((c = strchr(v->value, ','))) { 15305 trunkgroup = atoi(c + 1); 15306 if (trunkgroup > 0) { 15307 if ((c = strchr(c + 1, ','))) 15308 logicalspan = atoi(c + 1); 15309 else 15310 logicalspan = 0; 15311 if (logicalspan >= 0) { 15312 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { 15313 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 15314 } else 15315 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 15316 } else 15317 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); 15318 } else 15319 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno); 15320 } else 15321 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno); 15322 } else 15323 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno); 15324 } else { 15325 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); 15326 } 15327 v = v->next; 15328 } 15329 } 15330 #endif 15331 15332 /* Copy the default jb config over global_jbconf */ 15333 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf)); 15334 15335 mwimonitornotify[0] = '\0'; 15336 15337 v = ast_variable_browse(cfg, "channels"); 15338 if ((res = process_dahdi(&base_conf, "", v, reload, 0))) { 15339 ast_mutex_unlock(&iflock); 15340 ast_config_destroy(cfg); 15341 if (ucfg) { 15342 ast_config_destroy(ucfg); 15343 } 15344 return res; 15345 } 15346 15347 /* Now get configuration from all normal sections in chan_dahdi.conf: */ 15348 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) { 15349 /* [channels] and [trunkgroups] are used. Let's also reserve 15350 * [globals] and [general] for future use 15351 */ 15352 if (!strcasecmp(cat, "general") || 15353 !strcasecmp(cat, "trunkgroups") || 15354 !strcasecmp(cat, "globals") || 15355 !strcasecmp(cat, "channels")) { 15356 continue; 15357 } 15358 15359 memcpy(&conf, &base_conf, sizeof(conf)); 15360 15361 if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) { 15362 ast_mutex_unlock(&iflock); 15363 ast_config_destroy(cfg); 15364 if (ucfg) { 15365 ast_config_destroy(ucfg); 15366 } 15367 return res; 15368 } 15369 } 15370 15371 ast_config_destroy(cfg); 15372 15373 if (ucfg) { 15374 const char *chans; 15375 15376 process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0); 15377 15378 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) { 15379 if (!strcasecmp(cat, "general")) { 15380 continue; 15381 } 15382 15383 chans = ast_variable_retrieve(ucfg, cat, "dahdichan"); 15384 15385 if (ast_strlen_zero(chans)) { 15386 continue; 15387 } 15388 15389 memcpy(&conf, &base_conf, sizeof(conf)); 15390 15391 if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) { 15392 ast_config_destroy(ucfg); 15393 ast_mutex_unlock(&iflock); 15394 return res; 15395 } 15396 } 15397 ast_config_destroy(ucfg); 15398 } 15399 ast_mutex_unlock(&iflock); 15400 15401 #ifdef HAVE_PRI 15402 if (reload != 1) { 15403 int x; 15404 for (x = 0; x < NUM_SPANS; x++) { 15405 if (pris[x].pvts[0]) { 15406 if (start_pri(pris + x)) { 15407 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1); 15408 return -1; 15409 } else 15410 ast_verb(2, "Starting D-Channel on span %d\n", x + 1); 15411 } 15412 } 15413 } 15414 #endif 15415 #ifdef HAVE_SS7 15416 if (reload != 1) { 15417 int x; 15418 for (x = 0; x < NUM_SPANS; x++) { 15419 if (linksets[x].ss7) { 15420 if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) { 15421 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1); 15422 return -1; 15423 } else 15424 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1); 15425 } 15426 } 15427 } 15428 #endif 15429 /* And start the monitor for the first time */ 15430 restart_monitor(); 15431 return 0; 15432 }
static int sigtype_to_signalling | ( | int | sigtype | ) | [static] |
static void * ss_thread | ( | void * | data | ) | [static] |
Definition at line 6577 of file chan_dahdi.c.
References ast_channel::_state, alloc_sub(), ARRAY_LEN, ast_bridged_channel(), ast_canmatch_extension(), AST_CAUSE_UNALLOCATED, ast_clear_flag, 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_FLAG_END_DTMF_ONLY, 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_set_flag, 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_OVERLAPDIAL_INCOMING, 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, dahdi_pvt::inalarm, ISTRUNK, ast_channel::language, dahdi_pvt::lastcid_num, len(), dahdi_subchannel::linear, LOG_NOTICE, my_getsigstr(), ast_channel::name, name, NEED_MFDETECT, dahdi_pri::overlapdial, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, PVT_TO_CHANNEL, 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, dahdi_pvt::span, 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().
06578 { 06579 struct ast_channel *chan = data; 06580 struct dahdi_pvt *p = chan->tech_pvt; 06581 char exten[AST_MAX_EXTENSION] = ""; 06582 char exten2[AST_MAX_EXTENSION] = ""; 06583 unsigned char buf[256]; 06584 char dtmfcid[300]; 06585 char dtmfbuf[300]; 06586 struct callerid_state *cs = NULL; 06587 char *name = NULL, *number = NULL; 06588 int distMatches; 06589 int curRingData[3]; 06590 int receivedRingT; 06591 int counter1; 06592 int counter; 06593 int samples = 0; 06594 struct ast_smdi_md_message *smdi_msg = NULL; 06595 int flags = 0; 06596 int i; 06597 int timeout; 06598 int getforward = 0; 06599 char *s1, *s2; 06600 int len = 0; 06601 int res; 06602 int idx; 06603 06604 ast_mutex_lock(&ss_thread_lock); 06605 ss_thread_count++; 06606 ast_mutex_unlock(&ss_thread_lock); 06607 /* in the bizarre case where the channel has become a zombie before we 06608 even get started here, abort safely 06609 */ 06610 if (!p) { 06611 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name); 06612 ast_hangup(chan); 06613 goto quit; 06614 } 06615 ast_verb(3, "Starting simple switch on '%s'\n", chan->name); 06616 idx = dahdi_get_index(chan, p, 1); 06617 if (idx < 0) { 06618 ast_log(LOG_WARNING, "Huh?\n"); 06619 ast_hangup(chan); 06620 goto quit; 06621 } 06622 if (p->dsp) 06623 ast_dsp_digitreset(p->dsp); 06624 switch (p->sig) { 06625 #ifdef HAVE_PRI 06626 case SIG_PRI: 06627 case SIG_BRI: 06628 case SIG_BRI_PTMP: 06629 /* Now loop looking for an extension */ 06630 ast_copy_string(exten, p->exten, sizeof(exten)); 06631 len = strlen(exten); 06632 res = 0; 06633 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 06634 if (len && !ast_ignore_pattern(chan->context, exten)) 06635 tone_zone_play_tone(p->subs[idx].dfd, -1); 06636 else 06637 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 06638 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) 06639 timeout = matchdigittimeout; 06640 else 06641 timeout = gendigittimeout; 06642 res = ast_waitfordigit(chan, timeout); 06643 if (res < 0) { 06644 ast_debug(1, "waitfordigit returned < 0...\n"); 06645 ast_hangup(chan); 06646 goto quit; 06647 } else if (res) { 06648 exten[len++] = res; 06649 exten[len] = '\0'; 06650 } else 06651 break; 06652 } 06653 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */ 06654 if (ast_strlen_zero(exten)) { 06655 ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n"); 06656 exten[0] = 's'; 06657 exten[1] = '\0'; 06658 } 06659 tone_zone_play_tone(p->subs[idx].dfd, -1); 06660 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) { 06661 /* Start the real PBX */ 06662 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06663 if (p->dsp) { 06664 ast_dsp_digitreset(p->dsp); 06665 } 06666 if (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) { 06667 if (p->pri->pri) { 06668 if (!pri_grab(p, p->pri)) { 06669 pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0); 06670 p->proceeding = 1; 06671 pri_rel(p->pri); 06672 } else { 06673 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06674 } 06675 } 06676 } 06677 dahdi_enable_ec(p); 06678 ast_setstate(chan, AST_STATE_RING); 06679 res = ast_pbx_run(chan); 06680 if (res) { 06681 ast_log(LOG_WARNING, "PBX exited non-zero!\n"); 06682 } 06683 } else { 06684 ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context); 06685 chan->hangupcause = AST_CAUSE_UNALLOCATED; 06686 ast_hangup(chan); 06687 p->exten[0] = '\0'; 06688 /* Since we send release complete here, we won't get one */ 06689 p->call = NULL; 06690 } 06691 goto quit; 06692 break; 06693 #endif 06694 case SIG_FEATD: 06695 case SIG_FEATDMF: 06696 case SIG_FEATDMF_TA: 06697 case SIG_E911: 06698 case SIG_FGC_CAMAMF: 06699 case SIG_FEATB: 06700 case SIG_EMWINK: 06701 case SIG_SF_FEATD: 06702 case SIG_SF_FEATDMF: 06703 case SIG_SF_FEATB: 06704 case SIG_SFWINK: 06705 if (dahdi_wink(p, idx)) 06706 goto quit; 06707 /* Fall through */ 06708 case SIG_EM: 06709 case SIG_EM_E1: 06710 case SIG_SF: 06711 case SIG_FGC_CAMA: 06712 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 06713 if (p->dsp) 06714 ast_dsp_digitreset(p->dsp); 06715 /* set digit mode appropriately */ 06716 if (p->dsp) { 06717 if (NEED_MFDETECT(p)) 06718 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 06719 else 06720 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 06721 } 06722 memset(dtmfbuf, 0, sizeof(dtmfbuf)); 06723 /* Wait for the first digit only if immediate=no */ 06724 if (!p->immediate) 06725 /* Wait for the first digit (up to 5 seconds). */ 06726 res = ast_waitfordigit(chan, 5000); 06727 else 06728 res = 0; 06729 if (res > 0) { 06730 /* save first char */ 06731 dtmfbuf[0] = res; 06732 switch (p->sig) { 06733 case SIG_FEATD: 06734 case SIG_SF_FEATD: 06735 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06736 if (res > 0) 06737 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06738 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06739 break; 06740 case SIG_FEATDMF_TA: 06741 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06742 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06743 if (dahdi_wink(p, idx)) goto quit; 06744 dtmfbuf[0] = 0; 06745 /* Wait for the first digit (up to 5 seconds). */ 06746 res = ast_waitfordigit(chan, 5000); 06747 if (res <= 0) break; 06748 dtmfbuf[0] = res; 06749 /* fall through intentionally */ 06750 case SIG_FEATDMF: 06751 case SIG_E911: 06752 case SIG_FGC_CAMAMF: 06753 case SIG_SF_FEATDMF: 06754 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06755 /* if international caca, do it again to get real ANO */ 06756 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14)) 06757 { 06758 if (dahdi_wink(p, idx)) goto quit; 06759 dtmfbuf[0] = 0; 06760 /* Wait for the first digit (up to 5 seconds). */ 06761 res = ast_waitfordigit(chan, 5000); 06762 if (res <= 0) break; 06763 dtmfbuf[0] = res; 06764 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06765 } 06766 if (res > 0) { 06767 /* if E911, take off hook */ 06768 if (p->sig == SIG_E911) 06769 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06770 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000); 06771 } 06772 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06773 break; 06774 case SIG_FEATB: 06775 case SIG_SF_FEATB: 06776 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06777 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06778 break; 06779 case SIG_EMWINK: 06780 /* if we received a '*', we are actually receiving Feature Group D 06781 dial syntax, so use that mode; otherwise, fall through to normal 06782 mode 06783 */ 06784 if (res == '*') { 06785 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06786 if (res > 0) 06787 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06788 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06789 break; 06790 } 06791 default: 06792 /* If we got the first digit, get the rest */ 06793 len = 1; 06794 dtmfbuf[len] = '\0'; 06795 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06796 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06797 timeout = matchdigittimeout; 06798 } else { 06799 timeout = gendigittimeout; 06800 } 06801 res = ast_waitfordigit(chan, timeout); 06802 if (res < 0) { 06803 ast_debug(1, "waitfordigit returned < 0...\n"); 06804 ast_hangup(chan); 06805 goto quit; 06806 } else if (res) { 06807 dtmfbuf[len++] = res; 06808 dtmfbuf[len] = '\0'; 06809 } else { 06810 break; 06811 } 06812 } 06813 break; 06814 } 06815 } 06816 if (res == -1) { 06817 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno)); 06818 ast_hangup(chan); 06819 goto quit; 06820 } else if (res < 0) { 06821 ast_debug(1, "Got hung up before digits finished\n"); 06822 ast_hangup(chan); 06823 goto quit; 06824 } 06825 06826 if (p->sig == SIG_FGC_CAMA) { 06827 char anibuf[100]; 06828 06829 if (ast_safe_sleep(chan,1000) == -1) { 06830 ast_hangup(chan); 06831 goto quit; 06832 } 06833 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06834 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 06835 res = my_getsigstr(chan, anibuf, "#", 10000); 06836 if ((res > 0) && (strlen(anibuf) > 2)) { 06837 if (anibuf[strlen(anibuf) - 1] == '#') 06838 anibuf[strlen(anibuf) - 1] = 0; 06839 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2); 06840 } 06841 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 06842 } 06843 06844 ast_copy_string(exten, dtmfbuf, sizeof(exten)); 06845 if (ast_strlen_zero(exten)) 06846 ast_copy_string(exten, "s", sizeof(exten)); 06847 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) { 06848 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */ 06849 if (exten[0] == '*') { 06850 char *stringp=NULL; 06851 ast_copy_string(exten2, exten, sizeof(exten2)); 06852 /* Parse out extension and callerid */ 06853 stringp=exten2 +1; 06854 s1 = strsep(&stringp, "*"); 06855 s2 = strsep(&stringp, "*"); 06856 if (s2) { 06857 if (!ast_strlen_zero(p->cid_num)) 06858 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 06859 else 06860 ast_set_callerid(chan, s1, NULL, s1); 06861 ast_copy_string(exten, s2, sizeof(exten)); 06862 } else 06863 ast_copy_string(exten, s1, sizeof(exten)); 06864 } else if (p->sig == SIG_FEATD) 06865 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 06866 } 06867 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 06868 if (exten[0] == '*') { 06869 char *stringp=NULL; 06870 ast_copy_string(exten2, exten, sizeof(exten2)); 06871 /* Parse out extension and callerid */ 06872 stringp=exten2 +1; 06873 s1 = strsep(&stringp, "#"); 06874 s2 = strsep(&stringp, "#"); 06875 if (s2) { 06876 if (!ast_strlen_zero(p->cid_num)) 06877 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 06878 else 06879 if (*(s1 + 2)) 06880 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2); 06881 ast_copy_string(exten, s2 + 1, sizeof(exten)); 06882 } else 06883 ast_copy_string(exten, s1 + 2, sizeof(exten)); 06884 } else 06885 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 06886 } 06887 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) { 06888 if (exten[0] == '*') { 06889 char *stringp=NULL; 06890 ast_copy_string(exten2, exten, sizeof(exten2)); 06891 /* Parse out extension and callerid */ 06892 stringp=exten2 +1; 06893 s1 = strsep(&stringp, "#"); 06894 s2 = strsep(&stringp, "#"); 06895 if (s2 && (*(s2 + 1) == '0')) { 06896 if (*(s2 + 2)) 06897 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2); 06898 } 06899 if (s1) ast_copy_string(exten, s1, sizeof(exten)); 06900 else ast_copy_string(exten, "911", sizeof(exten)); 06901 } else 06902 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel); 06903 } 06904 if (p->sig == SIG_FEATB) { 06905 if (exten[0] == '*') { 06906 char *stringp=NULL; 06907 ast_copy_string(exten2, exten, sizeof(exten2)); 06908 /* Parse out extension and callerid */ 06909 stringp=exten2 +1; 06910 s1 = strsep(&stringp, "#"); 06911 ast_copy_string(exten, exten2 + 1, sizeof(exten)); 06912 } else 06913 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel); 06914 } 06915 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 06916 dahdi_wink(p, idx); 06917 /* some switches require a minimum guard time between 06918 the last FGD wink and something that answers 06919 immediately. This ensures it */ 06920 if (ast_safe_sleep(chan,100)) goto quit; 06921 } 06922 dahdi_enable_ec(p); 06923 if (NEED_MFDETECT(p)) { 06924 if (p->dsp) { 06925 if (!p->hardwaredtmf) 06926 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 06927 else { 06928 ast_dsp_free(p->dsp); 06929 p->dsp = NULL; 06930 } 06931 } 06932 } 06933 06934 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) { 06935 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06936 if (p->dsp) ast_dsp_digitreset(p->dsp); 06937 res = ast_pbx_run(chan); 06938 if (res) { 06939 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 06940 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06941 } 06942 goto quit; 06943 } else { 06944 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context); 06945 sleep(2); 06946 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO); 06947 if (res < 0) 06948 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel); 06949 else 06950 sleep(1); 06951 res = ast_streamfile(chan, "ss-noservice", chan->language); 06952 if (res >= 0) 06953 ast_waitstream(chan, ""); 06954 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06955 ast_hangup(chan); 06956 goto quit; 06957 } 06958 break; 06959 case SIG_FXOLS: 06960 case SIG_FXOGS: 06961 case SIG_FXOKS: 06962 /* Read the first digit */ 06963 timeout = firstdigittimeout; 06964 /* If starting a threeway call, never timeout on the first digit so someone 06965 can use flash-hook as a "hold" feature */ 06966 if (p->subs[SUB_THREEWAY].owner) 06967 timeout = 999999; 06968 while (len < AST_MAX_EXTENSION-1) { 06969 /* Read digit unless it's supposed to be immediate, in which case the 06970 only answer is 's' */ 06971 if (p->immediate) 06972 res = 's'; 06973 else 06974 res = ast_waitfordigit(chan, timeout); 06975 timeout = 0; 06976 if (res < 0) { 06977 ast_debug(1, "waitfordigit returned < 0...\n"); 06978 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 06979 ast_hangup(chan); 06980 goto quit; 06981 } else if (res) { 06982 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout); 06983 exten[len++]=res; 06984 exten[len] = '\0'; 06985 } 06986 if (!ast_ignore_pattern(chan->context, exten)) 06987 tone_zone_play_tone(p->subs[idx].dfd, -1); 06988 else 06989 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 06990 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) { 06991 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 06992 if (getforward) { 06993 /* Record this as the forwarding extension */ 06994 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 06995 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel); 06996 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 06997 if (res) 06998 break; 06999 usleep(500000); 07000 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 07001 sleep(1); 07002 memset(exten, 0, sizeof(exten)); 07003 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 07004 len = 0; 07005 getforward = 0; 07006 } else { 07007 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 07008 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 07009 if (!ast_strlen_zero(p->cid_num)) { 07010 if (!p->hidecallerid) 07011 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 07012 else 07013 ast_set_callerid(chan, NULL, NULL, p->cid_num); 07014 } 07015 if (!ast_strlen_zero(p->cid_name)) { 07016 if (!p->hidecallerid) 07017 ast_set_callerid(chan, NULL, p->cid_name, NULL); 07018 } 07019 ast_setstate(chan, AST_STATE_RING); 07020 dahdi_enable_ec(p); 07021 res = ast_pbx_run(chan); 07022 if (res) { 07023 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07024 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07025 } 07026 goto quit; 07027 } 07028 } else { 07029 /* It's a match, but they just typed a digit, and there is an ambiguous match, 07030 so just set the timeout to matchdigittimeout and wait some more */ 07031 timeout = matchdigittimeout; 07032 } 07033 } else if (res == 0) { 07034 ast_debug(1, "not enough digits (and no ambiguous match)...\n"); 07035 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07036 dahdi_wait_event(p->subs[idx].dfd); 07037 ast_hangup(chan); 07038 goto quit; 07039 } else if (p->callwaiting && !strcmp(exten, "*70")) { 07040 ast_verb(3, "Disabling call waiting on %s\n", chan->name); 07041 /* Disable call waiting if enabled */ 07042 p->callwaiting = 0; 07043 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07044 if (res) { 07045 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07046 chan->name, strerror(errno)); 07047 } 07048 len = 0; 07049 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len); 07050 memset(exten, 0, sizeof(exten)); 07051 timeout = firstdigittimeout; 07052 07053 } else if (!strcmp(exten,ast_pickup_ext())) { 07054 /* Scan all channels and see if there are any 07055 * ringing channels that have call groups 07056 * that equal this channels pickup group 07057 */ 07058 if (idx == SUB_REAL) { 07059 /* Switch us from Third call to Call Wait */ 07060 if (p->subs[SUB_THREEWAY].owner) { 07061 /* If you make a threeway call and the *8# a call, it should actually 07062 look like a callwait */ 07063 alloc_sub(p, SUB_CALLWAIT); 07064 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 07065 unalloc_sub(p, SUB_THREEWAY); 07066 } 07067 dahdi_enable_ec(p); 07068 if (ast_pickup_call(chan)) { 07069 ast_debug(1, "No call pickup possible...\n"); 07070 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07071 dahdi_wait_event(p->subs[idx].dfd); 07072 } 07073 ast_hangup(chan); 07074 goto quit; 07075 } else { 07076 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n"); 07077 ast_hangup(chan); 07078 goto quit; 07079 } 07080 07081 } else if (!p->hidecallerid && !strcmp(exten, "*67")) { 07082 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name); 07083 /* Disable Caller*ID if enabled */ 07084 p->hidecallerid = 1; 07085 if (chan->cid.cid_num) 07086 ast_free(chan->cid.cid_num); 07087 chan->cid.cid_num = NULL; 07088 if (chan->cid.cid_name) 07089 ast_free(chan->cid.cid_name); 07090 chan->cid.cid_name = NULL; 07091 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07092 if (res) { 07093 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07094 chan->name, strerror(errno)); 07095 } 07096 len = 0; 07097 memset(exten, 0, sizeof(exten)); 07098 timeout = firstdigittimeout; 07099 } else if (p->callreturn && !strcmp(exten, "*69")) { 07100 res = 0; 07101 if (!ast_strlen_zero(p->lastcid_num)) { 07102 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language); 07103 } 07104 if (!res) 07105 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07106 break; 07107 } else if (!strcmp(exten, "*78")) { 07108 dahdi_dnd(p, 1); 07109 /* Do not disturb */ 07110 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07111 getforward = 0; 07112 memset(exten, 0, sizeof(exten)); 07113 len = 0; 07114 } else if (!strcmp(exten, "*79")) { 07115 dahdi_dnd(p, 0); 07116 /* Do not disturb */ 07117 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07118 getforward = 0; 07119 memset(exten, 0, sizeof(exten)); 07120 len = 0; 07121 } else if (p->cancallforward && !strcmp(exten, "*72")) { 07122 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07123 getforward = 1; 07124 memset(exten, 0, sizeof(exten)); 07125 len = 0; 07126 } else if (p->cancallforward && !strcmp(exten, "*73")) { 07127 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel); 07128 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07129 memset(p->call_forward, 0, sizeof(p->call_forward)); 07130 getforward = 0; 07131 memset(exten, 0, sizeof(exten)); 07132 len = 0; 07133 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 07134 p->subs[SUB_THREEWAY].owner && 07135 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 07136 /* This is a three way call, the main call being a real channel, 07137 and we're parking the first call. */ 07138 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL); 07139 ast_verb(3, "Parking call to '%s'\n", chan->name); 07140 break; 07141 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) { 07142 ast_verb(3, "Blacklisting number %s\n", p->lastcid_num); 07143 res = ast_db_put("blacklist", p->lastcid_num, "1"); 07144 if (!res) { 07145 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07146 memset(exten, 0, sizeof(exten)); 07147 len = 0; 07148 } 07149 } else if (p->hidecallerid && !strcmp(exten, "*82")) { 07150 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name); 07151 /* Enable Caller*ID if enabled */ 07152 p->hidecallerid = 0; 07153 if (chan->cid.cid_num) 07154 ast_free(chan->cid.cid_num); 07155 chan->cid.cid_num = NULL; 07156 if (chan->cid.cid_name) 07157 ast_free(chan->cid.cid_name); 07158 chan->cid.cid_name = NULL; 07159 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 07160 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07161 if (res) { 07162 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07163 chan->name, strerror(errno)); 07164 } 07165 len = 0; 07166 memset(exten, 0, sizeof(exten)); 07167 timeout = firstdigittimeout; 07168 } else if (!strcmp(exten, "*0")) { 07169 struct ast_channel *nbridge = 07170 p->subs[SUB_THREEWAY].owner; 07171 struct dahdi_pvt *pbridge = NULL; 07172 /* set up the private struct of the bridged one, if any */ 07173 if (nbridge && ast_bridged_channel(nbridge)) 07174 pbridge = ast_bridged_channel(nbridge)->tech_pvt; 07175 if (nbridge && pbridge && 07176 (nbridge->tech == &dahdi_tech) && 07177 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) && 07178 ISTRUNK(pbridge)) { 07179 int func = DAHDI_FLASH; 07180 /* Clear out the dial buffer */ 07181 p->dop.dialstr[0] = '\0'; 07182 /* flash hookswitch */ 07183 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 07184 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 07185 nbridge->name, strerror(errno)); 07186 } 07187 swap_subs(p, SUB_REAL, SUB_THREEWAY); 07188 unalloc_sub(p, SUB_THREEWAY); 07189 p->owner = p->subs[SUB_REAL].owner; 07190 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 07191 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 07192 ast_hangup(chan); 07193 goto quit; 07194 } else { 07195 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07196 dahdi_wait_event(p->subs[idx].dfd); 07197 tone_zone_play_tone(p->subs[idx].dfd, -1); 07198 swap_subs(p, SUB_REAL, SUB_THREEWAY); 07199 unalloc_sub(p, SUB_THREEWAY); 07200 p->owner = p->subs[SUB_REAL].owner; 07201 ast_hangup(chan); 07202 goto quit; 07203 } 07204 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) && 07205 ((exten[0] != '*') || (strlen(exten) > 2))) { 07206 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); 07207 break; 07208 } 07209 if (!timeout) 07210 timeout = gendigittimeout; 07211 if (len && !ast_ignore_pattern(chan->context, exten)) 07212 tone_zone_play_tone(p->subs[idx].dfd, -1); 07213 } 07214 break; 07215 case SIG_FXSLS: 07216 case SIG_FXSGS: 07217 case SIG_FXSKS: 07218 #ifdef HAVE_PRI 07219 if (p->pri) { 07220 /* This is a GR-303 trunk actually. Wait for the first ring... */ 07221 struct ast_frame *f; 07222 int res; 07223 time_t start; 07224 07225 time(&start); 07226 ast_setstate(chan, AST_STATE_RING); 07227 while (time(NULL) < start + 3) { 07228 res = ast_waitfor(chan, 1000); 07229 if (res) { 07230 f = ast_read(chan); 07231 if (!f) { 07232 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n"); 07233 ast_hangup(chan); 07234 goto quit; 07235 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) { 07236 res = 1; 07237 } else 07238 res = 0; 07239 ast_frfree(f); 07240 if (res) { 07241 ast_debug(1, "Got ring!\n"); 07242 res = 0; 07243 break; 07244 } 07245 } 07246 } 07247 } 07248 #endif 07249 /* check for SMDI messages */ 07250 if (p->use_smdi && p->smdi_iface) { 07251 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); 07252 07253 if (smdi_msg != NULL) { 07254 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten)); 07255 07256 if (smdi_msg->type == 'B') 07257 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b"); 07258 else if (smdi_msg->type == 'N') 07259 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u"); 07260 07261 ast_debug(1, "Received SMDI message on %s\n", chan->name); 07262 } else { 07263 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n"); 07264 } 07265 } 07266 07267 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) { 07268 number = smdi_msg->calling_st; 07269 07270 /* If we want caller id, we're in a prering state due to a polarity reversal 07271 * and we're set to use a polarity reversal to trigger the start of caller id, 07272 * grab the caller id and wait for ringing to start... */ 07273 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) { 07274 /* If set to use DTMF CID signalling, listen for DTMF */ 07275 if (p->cid_signalling == CID_SIG_DTMF) { 07276 int k = 0; 07277 cs = NULL; 07278 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name); 07279 dahdi_setlinear(p->subs[idx].dfd, 0); 07280 /* 07281 * We are the only party interested in the Rx stream since 07282 * we have not answered yet. We don't need or even want DTMF 07283 * emulation. The DTMF digits can come so fast that emulation 07284 * can drop some of them. 07285 */ 07286 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY); 07287 res = 4000;/* This is a typical OFF time between rings. */ 07288 for (;;) { 07289 struct ast_frame *f; 07290 res = ast_waitfor(chan, res); 07291 if (res <= 0) { 07292 /* 07293 * We do not need to restore the dahdi_setlinear() 07294 * or AST_FLAG_END_DTMF_ONLY flag settings since we 07295 * are hanging up the channel. 07296 */ 07297 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 07298 "Exiting simple switch\n"); 07299 ast_hangup(chan); 07300 goto quit; 07301 } 07302 f = ast_read(chan); 07303 if (!f) 07304 break; 07305 if (f->frametype == AST_FRAME_DTMF) { 07306 if (k < ARRAY_LEN(dtmfbuf) - 1) { 07307 dtmfbuf[k++] = f->subclass; 07308 } 07309 ast_debug(1, "CID got digit '%c'\n", f->subclass); 07310 res = 4000;/* This is a typical OFF time between rings. */ 07311 } 07312 ast_frfree(f); 07313 if (chan->_state == AST_STATE_RING || 07314 chan->_state == AST_STATE_RINGING) 07315 break; /* Got ring */ 07316 } 07317 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY); 07318 dtmfbuf[k] = '\0'; 07319 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 07320 /* Got cid and ring. */ 07321 ast_debug(1, "CID got string '%s'\n", dtmfbuf); 07322 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 07323 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags); 07324 /* If first byte is NULL, we have no cid */ 07325 if (!ast_strlen_zero(dtmfcid)) 07326 number = dtmfcid; 07327 else 07328 number = NULL; 07329 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 07330 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { 07331 cs = callerid_new(p->cid_signalling); 07332 if (cs) { 07333 samples = 0; 07334 #if 1 07335 bump_gains(p); 07336 #endif 07337 /* Take out of linear mode for Caller*ID processing */ 07338 dahdi_setlinear(p->subs[idx].dfd, 0); 07339 07340 /* First we wait and listen for the Caller*ID */ 07341 for (;;) { 07342 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07343 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 07344 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07345 callerid_free(cs); 07346 ast_hangup(chan); 07347 goto quit; 07348 } 07349 if (i & DAHDI_IOMUX_SIGEVENT) { 07350 res = dahdi_get_event(p->subs[idx].dfd); 07351 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07352 if (res == DAHDI_EVENT_NOALARM) { 07353 p->inalarm = 0; 07354 } 07355 07356 if (p->cid_signalling == CID_SIG_V23_JP) { 07357 if (res == DAHDI_EVENT_RINGBEGIN) { 07358 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07359 usleep(1); 07360 } 07361 } else { 07362 res = 0; 07363 break; 07364 } 07365 } else if (i & DAHDI_IOMUX_READ) { 07366 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 07367 if (res < 0) { 07368 if (errno != ELAST) { 07369 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07370 callerid_free(cs); 07371 ast_hangup(chan); 07372 goto quit; 07373 } 07374 break; 07375 } 07376 samples += res; 07377 07378 if (p->cid_signalling == CID_SIG_V23_JP) { 07379 res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); 07380 } else { 07381 res = callerid_feed(cs, buf, res, AST_LAW(p)); 07382 } 07383 if (res < 0) { 07384 /* 07385 * The previous diagnostic message output likely 07386 * explains why it failed. 07387 */ 07388 ast_log(LOG_WARNING, 07389 "Failed to decode CallerID on channel '%s'\n", 07390 chan->name); 07391 break; 07392 } else if (res) 07393 break; 07394 else if (samples > (8000 * 10)) 07395 break; 07396 } 07397 } 07398 if (res == 1) { 07399 callerid_get(cs, &name, &number, &flags); 07400 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 07401 } 07402 07403 if (p->cid_signalling == CID_SIG_V23_JP) { 07404 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 07405 usleep(1); 07406 } 07407 07408 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 07409 res = 4000;/* This is a typical OFF time between rings. */ 07410 for (;;) { 07411 struct ast_frame *f; 07412 res = ast_waitfor(chan, res); 07413 if (res <= 0) { 07414 ast_log(LOG_WARNING, "CID timed out waiting for ring. " 07415 "Exiting simple switch\n"); 07416 ast_hangup(chan); 07417 goto quit; 07418 } 07419 if (!(f = ast_read(chan))) { 07420 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); 07421 ast_hangup(chan); 07422 goto quit; 07423 } 07424 ast_frfree(f); 07425 if (chan->_state == AST_STATE_RING || 07426 chan->_state == AST_STATE_RINGING) 07427 break; /* Got ring */ 07428 } 07429 07430 /* We must have a ring by now, so, if configured, lets try to listen for 07431 * distinctive ringing */ 07432 if (p->usedistinctiveringdetection) { 07433 len = 0; 07434 distMatches = 0; 07435 /* Clear the current ring data array so we dont have old data in it. */ 07436 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 07437 curRingData[receivedRingT] = 0; 07438 receivedRingT = 0; 07439 counter = 0; 07440 counter1 = 0; 07441 /* Check to see if context is what it should be, if not set to be. */ 07442 if (strcmp(p->context,p->defcontext) != 0) { 07443 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 07444 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 07445 } 07446 07447 for (;;) { 07448 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07449 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 07450 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07451 callerid_free(cs); 07452 ast_hangup(chan); 07453 goto quit; 07454 } 07455 if (i & DAHDI_IOMUX_SIGEVENT) { 07456 res = dahdi_get_event(p->subs[idx].dfd); 07457 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07458 if (res == DAHDI_EVENT_NOALARM) { 07459 p->inalarm = 0; 07460 } 07461 res = 0; 07462 /* Let us detect distinctive ring */ 07463 07464 curRingData[receivedRingT] = p->ringt; 07465 07466 if (p->ringt < p->ringt_base/2) 07467 break; 07468 /* Increment the ringT counter so we can match it against 07469 values in chan_dahdi.conf for distinctive ring */ 07470 if (++receivedRingT == ARRAY_LEN(curRingData)) 07471 break; 07472 } else if (i & DAHDI_IOMUX_READ) { 07473 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 07474 if (res < 0) { 07475 if (errno != ELAST) { 07476 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07477 callerid_free(cs); 07478 ast_hangup(chan); 07479 goto quit; 07480 } 07481 break; 07482 } 07483 if (p->ringt) 07484 p->ringt--; 07485 if (p->ringt == 1) { 07486 res = -1; 07487 break; 07488 } 07489 } 07490 } 07491 /* this only shows up if you have n of the dring patterns filled in */ 07492 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 07493 for (counter = 0; counter < 3; counter++) { 07494 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 07495 channel */ 07496 distMatches = 0; 07497 for (counter1 = 0; counter1 < 3; counter1++) { 07498 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 07499 if (p->drings.ringnum[counter].ring[counter1] == -1) { 07500 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 07501 curRingData[counter1]); 07502 distMatches++; 07503 } 07504 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 07505 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 07506 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 07507 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 07508 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 07509 distMatches++; 07510 } 07511 } 07512 07513 if (distMatches == 3) { 07514 /* The ring matches, set the context to whatever is for distinctive ring.. */ 07515 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 07516 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 07517 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 07518 break; 07519 } 07520 } 07521 } 07522 /* Restore linear mode (if appropriate) for Caller*ID processing */ 07523 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 07524 #if 1 07525 restore_gains(p); 07526 #endif 07527 } else 07528 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 07529 } else { 07530 ast_log(LOG_WARNING, "Channel %s in prering " 07531 "state, but I have nothing to do. " 07532 "Terminating simple switch, should be " 07533 "restarted by the actual ring.\n", 07534 chan->name); 07535 ast_hangup(chan); 07536 goto quit; 07537 } 07538 } else if (p->use_callerid && p->cid_start == CID_START_RING) { 07539 if (p->cid_signalling == CID_SIG_DTMF) { 07540 int k = 0; 07541 cs = NULL; 07542 dahdi_setlinear(p->subs[idx].dfd, 0); 07543 res = 2000; 07544 for (;;) { 07545 struct ast_frame *f; 07546 res = ast_waitfor(chan, res); 07547 if (res <= 0) { 07548 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 07549 "Exiting simple switch\n"); 07550 ast_hangup(chan); 07551 return NULL; 07552 } 07553 f = ast_read(chan); 07554 if (f->frametype == AST_FRAME_DTMF) { 07555 dtmfbuf[k++] = f->subclass; 07556 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass); 07557 res = 2000; 07558 } 07559 ast_frfree(f); 07560 07561 if (p->ringt_base == p->ringt) 07562 break; 07563 07564 } 07565 dtmfbuf[k] = '\0'; 07566 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 07567 /* Got cid and ring. */ 07568 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 07569 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 07570 dtmfcid, flags); 07571 /* If first byte is NULL, we have no cid */ 07572 if (!ast_strlen_zero(dtmfcid)) 07573 number = dtmfcid; 07574 else 07575 number = NULL; 07576 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 07577 } else { 07578 /* FSK Bell202 callerID */ 07579 cs = callerid_new(p->cid_signalling); 07580 if (cs) { 07581 #if 1 07582 bump_gains(p); 07583 #endif 07584 samples = 0; 07585 len = 0; 07586 distMatches = 0; 07587 /* Clear the current ring data array so we dont have old data in it. */ 07588 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 07589 curRingData[receivedRingT] = 0; 07590 receivedRingT = 0; 07591 counter = 0; 07592 counter1 = 0; 07593 /* Check to see if context is what it should be, if not set to be. */ 07594 if (strcmp(p->context,p->defcontext) != 0) { 07595 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 07596 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 07597 } 07598 07599 /* Take out of linear mode for Caller*ID processing */ 07600 dahdi_setlinear(p->subs[idx].dfd, 0); 07601 for (;;) { 07602 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07603 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 07604 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07605 callerid_free(cs); 07606 ast_hangup(chan); 07607 goto quit; 07608 } 07609 if (i & DAHDI_IOMUX_SIGEVENT) { 07610 res = dahdi_get_event(p->subs[idx].dfd); 07611 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07612 if (res == DAHDI_EVENT_NOALARM) { 07613 p->inalarm = 0; 07614 } 07615 /* If we get a PR event, they hung up while processing calerid */ 07616 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { 07617 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); 07618 p->polarity = POLARITY_IDLE; 07619 callerid_free(cs); 07620 ast_hangup(chan); 07621 goto quit; 07622 } 07623 res = 0; 07624 /* Let us detect callerid when the telco uses distinctive ring */ 07625 07626 curRingData[receivedRingT] = p->ringt; 07627 07628 if (p->ringt < p->ringt_base/2) 07629 break; 07630 /* Increment the ringT counter so we can match it against 07631 values in chan_dahdi.conf for distinctive ring */ 07632 if (++receivedRingT == ARRAY_LEN(curRingData)) 07633 break; 07634 } else if (i & DAHDI_IOMUX_READ) { 07635 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 07636 if (res < 0) { 07637 if (errno != ELAST) { 07638 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07639 callerid_free(cs); 07640 ast_hangup(chan); 07641 goto quit; 07642 } 07643 break; 07644 } 07645 if (p->ringt) 07646 p->ringt--; 07647 if (p->ringt == 1) { 07648 res = -1; 07649 break; 07650 } 07651 samples += res; 07652 res = callerid_feed(cs, buf, res, AST_LAW(p)); 07653 if (res < 0) { 07654 /* 07655 * The previous diagnostic message output likely 07656 * explains why it failed. 07657 */ 07658 ast_log(LOG_WARNING, 07659 "Failed to decode CallerID on channel '%s'\n", 07660 chan->name); 07661 break; 07662 } else if (res) 07663 break; 07664 else if (samples > (8000 * 10)) 07665 break; 07666 } 07667 } 07668 if (res == 1) { 07669 callerid_get(cs, &name, &number, &flags); 07670 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 07671 } 07672 if (distinctiveringaftercid == 1) { 07673 /* Clear the current ring data array so we dont have old data in it. */ 07674 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) { 07675 curRingData[receivedRingT] = 0; 07676 } 07677 receivedRingT = 0; 07678 ast_verb(3, "Detecting post-CID distinctive ring\n"); 07679 for (;;) { 07680 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07681 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 07682 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07683 callerid_free(cs); 07684 ast_hangup(chan); 07685 goto quit; 07686 } 07687 if (i & DAHDI_IOMUX_SIGEVENT) { 07688 res = dahdi_get_event(p->subs[idx].dfd); 07689 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07690 if (res == DAHDI_EVENT_NOALARM) { 07691 p->inalarm = 0; 07692 } 07693 res = 0; 07694 /* Let us detect callerid when the telco uses distinctive ring */ 07695 07696 curRingData[receivedRingT] = p->ringt; 07697 07698 if (p->ringt < p->ringt_base/2) 07699 break; 07700 /* Increment the ringT counter so we can match it against 07701 values in chan_dahdi.conf for distinctive ring */ 07702 if (++receivedRingT == ARRAY_LEN(curRingData)) 07703 break; 07704 } else if (i & DAHDI_IOMUX_READ) { 07705 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 07706 if (res < 0) { 07707 if (errno != ELAST) { 07708 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07709 callerid_free(cs); 07710 ast_hangup(chan); 07711 goto quit; 07712 } 07713 break; 07714 } 07715 if (p->ringt) 07716 p->ringt--; 07717 if (p->ringt == 1) { 07718 res = -1; 07719 break; 07720 } 07721 } 07722 } 07723 } 07724 if (p->usedistinctiveringdetection) { 07725 /* this only shows up if you have n of the dring patterns filled in */ 07726 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 07727 07728 for (counter = 0; counter < 3; counter++) { 07729 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 07730 channel */ 07731 /* this only shows up if you have n of the dring patterns filled in */ 07732 ast_verb(3, "Checking %d,%d,%d\n", 07733 p->drings.ringnum[counter].ring[0], 07734 p->drings.ringnum[counter].ring[1], 07735 p->drings.ringnum[counter].ring[2]); 07736 distMatches = 0; 07737 for (counter1 = 0; counter1 < 3; counter1++) { 07738 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 07739 if (p->drings.ringnum[counter].ring[counter1] == -1) { 07740 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 07741 curRingData[counter1]); 07742 distMatches++; 07743 } 07744 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 07745 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 07746 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 07747 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 07748 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 07749 distMatches++; 07750 } 07751 } 07752 if (distMatches == 3) { 07753 /* The ring matches, set the context to whatever is for distinctive ring.. */ 07754 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 07755 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 07756 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 07757 break; 07758 } 07759 } 07760 } 07761 /* Restore linear mode (if appropriate) for Caller*ID processing */ 07762 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 07763 #if 1 07764 restore_gains(p); 07765 #endif 07766 if (res < 0) { 07767 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); 07768 } 07769 } else 07770 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 07771 } 07772 } 07773 else 07774 cs = NULL; 07775 07776 if (number) 07777 ast_shrink_phone_number(number); 07778 ast_set_callerid(chan, number, name, number); 07779 07780 if (smdi_msg) 07781 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy); 07782 07783 if (cs) 07784 callerid_free(cs); 07785 /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */ 07786 if (flags & CID_MSGWAITING) { 07787 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel); 07788 notify_message(p->mailbox, 1); 07789 /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */ 07790 if (p->mwimonitor_rpas) { 07791 ast_hangup(chan); 07792 return NULL; 07793 } 07794 } else if (flags & CID_NOMSGWAITING) { 07795 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel); 07796 notify_message(p->mailbox, 0); 07797 /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */ 07798 if (p->mwimonitor_rpas) { 07799 ast_hangup(chan); 07800 return NULL; 07801 } 07802 } 07803 07804 ast_setstate(chan, AST_STATE_RING); 07805 chan->rings = 1; 07806 p->ringt = p->ringt_base; 07807 res = ast_pbx_run(chan); 07808 if (res) { 07809 ast_hangup(chan); 07810 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07811 } 07812 goto quit; 07813 default: 07814 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel); 07815 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07816 if (res < 0) 07817 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 07818 } 07819 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07820 if (res < 0) 07821 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 07822 ast_hangup(chan); 07823 quit: 07824 ast_mutex_lock(&ss_thread_lock); 07825 ss_thread_count--; 07826 ast_cond_signal(&ss_thread_complete); 07827 ast_mutex_unlock(&ss_thread_lock); 07828 return NULL; 07829 }
static int start_pri | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 12102 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().
12103 { 12104 int res, x; 12105 struct dahdi_params p; 12106 struct dahdi_bufferinfo bi; 12107 struct dahdi_spaninfo si; 12108 int i; 12109 12110 for (i = 0; i < NUM_DCHANS; i++) { 12111 if (!pri->dchannels[i]) 12112 break; 12113 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR); 12114 x = pri->dchannels[i]; 12115 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) { 12116 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno)); 12117 return -1; 12118 } 12119 memset(&p, 0, sizeof(p)); 12120 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p); 12121 if (res) { 12122 dahdi_close_pri_fd(pri, i); 12123 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno)); 12124 return -1; 12125 } 12126 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) { 12127 dahdi_close_pri_fd(pri, i); 12128 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x); 12129 return -1; 12130 } 12131 memset(&si, 0, sizeof(si)); 12132 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si); 12133 if (res) { 12134 dahdi_close_pri_fd(pri, i); 12135 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno)); 12136 } 12137 if (!si.alarms) 12138 pri->dchanavail[i] |= DCHAN_NOTINALARM; 12139 else 12140 pri->dchanavail[i] &= ~DCHAN_NOTINALARM; 12141 memset(&bi, 0, sizeof(bi)); 12142 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 12143 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 12144 bi.numbufs = 32; 12145 bi.bufsize = 1024; 12146 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) { 12147 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno)); 12148 dahdi_close_pri_fd(pri, i); 12149 return -1; 12150 } 12151 switch (pri->sig) { 12152 case SIG_BRI: 12153 pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype); 12154 break; 12155 case SIG_BRI_PTMP: 12156 pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype); 12157 break; 12158 default: 12159 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype); 12160 } 12161 /* Force overlap dial if we're doing GR-303! */ 12162 if (pri->switchtype == PRI_SWITCH_GR303_TMC) 12163 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH; 12164 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0); 12165 #ifdef HAVE_PRI_INBANDDISCONNECT 12166 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect); 12167 #endif 12168 /* Enslave to master if appropriate */ 12169 if (i) 12170 pri_enslave(pri->dchans[0], pri->dchans[i]); 12171 if (!pri->dchans[i]) { 12172 dahdi_close_pri_fd(pri, i); 12173 ast_log(LOG_ERROR, "Unable to create PRI structure\n"); 12174 return -1; 12175 } 12176 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG); 12177 pri_set_nsf(pri->dchans[i], pri->nsf); 12178 #ifdef PRI_GETSET_TIMERS 12179 for (x = 0; x < PRI_MAX_TIMERS; x++) { 12180 if (pritimers[x] != 0) 12181 pri_set_timer(pri->dchans[i], x, pritimers[x]); 12182 } 12183 #endif 12184 } 12185 /* Assume primary is the one we use */ 12186 pri->pri = pri->dchans[0]; 12187 pri->resetpos = -1; 12188 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) { 12189 for (i = 0; i < NUM_DCHANS; i++) { 12190 if (!pri->dchannels[i]) 12191 break; 12192 dahdi_close_pri_fd(pri, i); 12193 } 12194 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno)); 12195 return -1; 12196 } 12197 return 0; 12198 }
static void swap_subs | ( | struct dahdi_pvt * | p, | |
int | a, | |||
int | b | |||
) | [static] |
Definition at line 1425 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().
01426 { 01427 int tchan; 01428 int tinthreeway; 01429 struct ast_channel *towner; 01430 01431 ast_debug(1, "Swapping %d and %d\n", a, b); 01432 01433 tchan = p->subs[a].chan; 01434 towner = p->subs[a].owner; 01435 tinthreeway = p->subs[a].inthreeway; 01436 01437 p->subs[a].chan = p->subs[b].chan; 01438 p->subs[a].owner = p->subs[b].owner; 01439 p->subs[a].inthreeway = p->subs[b].inthreeway; 01440 01441 p->subs[b].chan = tchan; 01442 p->subs[b].owner = towner; 01443 p->subs[b].inthreeway = tinthreeway; 01444 01445 if (p->subs[a].owner) 01446 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd); 01447 if (p->subs[b].owner) 01448 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd); 01449 wakeup_sub(p, a, NULL); 01450 wakeup_sub(p, b, NULL); 01451 }
static int unalloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 1575 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().
01576 { 01577 if (!x) { 01578 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel); 01579 return -1; 01580 } 01581 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel); 01582 dahdi_close_sub(p, x); 01583 p->subs[x].linear = 0; 01584 p->subs[x].chan = 0; 01585 p->subs[x].owner = NULL; 01586 p->subs[x].inthreeway = 0; 01587 p->polarity = POLARITY_IDLE; 01588 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf)); 01589 return 0; 01590 }
static int unload_module | ( | void | ) | [static] |
Definition at line 14212 of file chan_dahdi.c.
References __unload_module(), ast_mutex_destroy(), lock, NUM_SPANS, and pris.
14213 { 14214 #if defined(HAVE_PRI) || defined(HAVE_SS7) 14215 int y; 14216 #endif 14217 #ifdef HAVE_PRI 14218 for (y = 0; y < NUM_SPANS; y++) 14219 ast_mutex_destroy(&pris[y].lock); 14220 #endif 14221 #ifdef HAVE_SS7 14222 for (y = 0; y < NUM_SPANS; y++) 14223 ast_mutex_destroy(&linksets[y].lock); 14224 #endif /* HAVE_SS7 */ 14225 return __unload_module(); 14226 }
static int update_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1965 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().
01966 { 01967 int needconf = 0; 01968 int x; 01969 int useslavenative; 01970 struct dahdi_pvt *slave = NULL; 01971 01972 useslavenative = isslavenative(p, &slave); 01973 /* Start with the obvious, general stuff */ 01974 for (x = 0; x < 3; x++) { 01975 /* Look for three way calls */ 01976 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) { 01977 conf_add(p, &p->subs[x], x, 0); 01978 needconf++; 01979 } else { 01980 conf_del(p, &p->subs[x], x); 01981 } 01982 } 01983 /* If we have a slave, add him to our conference now. or DAX 01984 if this is slave native */ 01985 for (x = 0; x < MAX_SLAVES; x++) { 01986 if (p->slaves[x]) { 01987 if (useslavenative) 01988 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 01989 else { 01990 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 01991 needconf++; 01992 } 01993 } 01994 } 01995 /* If we're supposed to be in there, do so now */ 01996 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 01997 if (useslavenative) 01998 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 01999 else { 02000 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 02001 needconf++; 02002 } 02003 } 02004 /* If we have a master, add ourselves to his conference */ 02005 if (p->master) { 02006 if (isslavenative(p->master, NULL)) { 02007 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 02008 } else { 02009 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 02010 } 02011 } 02012 if (!needconf) { 02013 /* Nobody is left (or should be left) in our conference. 02014 Kill it. */ 02015 p->confno = -1; 02016 } 02017 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf); 02018 return 0; 02019 }
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(), DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_pri::lock, dahdi_subchannel::owner, and dahdi_pvt::subs.
Referenced by swap_subs().
01336 { 01337 #ifdef HAVE_PRI 01338 if (pri) 01339 ast_mutex_unlock(&pri->lock); 01340 #endif 01341 for (;;) { 01342 if (p->subs[a].owner) { 01343 if (ast_channel_trylock(p->subs[a].owner)) { 01344 DEADLOCK_AVOIDANCE(&p->lock); 01345 } else { 01346 ast_queue_frame(p->subs[a].owner, &ast_null_frame); 01347 ast_channel_unlock(p->subs[a].owner); 01348 break; 01349 } 01350 } else 01351 break; 01352 } 01353 #ifdef HAVE_PRI 01354 if (pri) 01355 ast_mutex_lock(&pri->lock); 01356 #endif 01357 }
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 15635 of file chan_dahdi.c.
int alarm |
struct { ... } alarms[] [static] |
Referenced by alarm2str().
struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}} [static] |
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 15635 of file chan_dahdi.c.
struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static] |
Definition at line 1291 of file chan_dahdi.c.
Referenced by dahdi_call(), and handle_dahdi_show_cadences().
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 1302 of file chan_dahdi.c.
Referenced by dahdi_call(), and handle_dahdi_show_cadences().
const char config[] = "chan_dahdi.conf" [static] |
Definition at line 169 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 3269 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 3273 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static] |
Definition at line 3271 of file chan_dahdi.c.
struct ast_channel_tech dahdi_tech [static] |
Definition at line 1218 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 227 of file chan_dahdi.c.
char defaultozz[64] = "" [static] |
Definition at line 228 of file chan_dahdi.c.
int distinctiveringaftercid = 0 [static] |
Definition at line 239 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 255 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 258 of file chan_dahdi.c.
Referenced by mgcp_ss().
struct ast_jb_conf global_jbconf [static] |
Definition at line 126 of file chan_dahdi.c.
int ifcount = 0 [static] |
Definition at line 267 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 264 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 246 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 261 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 279 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 275 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 280 of file chan_dahdi.c.
int mwi_thread_count = 0 [static] |
Definition at line 285 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 243 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 233 of file chan_dahdi.c.
int mwisend_rpas = 0 [static] |
Definition at line 234 of file chan_dahdi.c.
char* name |
Definition at line 1731 of file chan_dahdi.c.
int num_cadence = 4 [static] |
Definition at line 1288 of file chan_dahdi.c.
Referenced by dahdi_call(), and handle_dahdi_show_cadences().
int num_restart_pending = 0 [static] |
Definition at line 287 of file chan_dahdi.c.
int numbufs = 4 [static] |
Definition at line 241 of file chan_dahdi.c.
char parkinglot[AST_MAX_EXTENSION] = "" [static] |
Default parking lot for this channel
Definition at line 230 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(), sip_new(), sip_park(), and store_config_core().
int pridebugfd = -1 [static] |
Definition at line 250 of file chan_dahdi.c.
ast_mutex_t pridebugfdlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 270 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 251 of file chan_dahdi.c.
Definition at line 448 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 236 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 342 of file chan_dahdi.c.
struct dahdi_pvt* round_robin[32] |
ast_cond_t ss_thread_complete [static] |
Definition at line 281 of file chan_dahdi.c.
int ss_thread_count = 0 [static] |
Definition at line 286 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 238 of file chan_dahdi.c.
int user_has_defined_cadences = 0 [static] |
Definition at line 1289 of file chan_dahdi.c.