DAHDI for Pseudo TDM. More...
#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 <libss7.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"#include "asterisk/paths.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_ss7 |
| struct | dahdi_subchannel |
| struct | distRingData |
| struct | mwi_thread_data |
| struct | mwisend_info |
| 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_CHAN_MAPPING_LOGICAL 1 |
| #define | DAHDI_CHAN_MAPPING_PHYSICAL 0 |
| #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 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" |
| #define | FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-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 | FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\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 | LINKSET_FLAG_EXPLICITACM (1 << 0) |
| #define | LINKSTATE_DOWN (1 << 3) |
| #define | LINKSTATE_INALARM (1 << 0) |
| #define | LINKSTATE_STARTING (1 << 1) |
| #define | LINKSTATE_UP (1 << 2) |
| #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_MFCR2 DAHDI_SIG_CAS |
| #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 | SS7_NAI_DYNAMIC -1 |
| #define | SUB_CALLWAIT 1 |
| #define | SUB_REAL 0 |
| #define | SUB_THREEWAY 2 |
| #define | TRAILER_MS 5 |
| #define | TRANSFER 0 |
Enumerations | |
| enum | mwisend_states { MWI_SEND_NULL = 0, 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 int | check_for_conference (struct dahdi_pvt *p) |
| static unsigned char | cid_pres2ss7pres (int cid_pres) |
| static unsigned char | cid_pres2ss7screen (int cid_pres) |
| static char * | complete_span_4 (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_ss7_fd (struct dahdi_ss7 *ss7, 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_func_write (struct ast_channel *chan, const char *function, char *data, const char *value) |
| 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 void | dahdi_loopback (struct dahdi_pvt *p, int enable) |
| 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_ss7_error (struct ss7 *ss7, char *s) |
| static void | dahdi_ss7_message (struct ss7 *ss7, char *s) |
| 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 struct dahdi_pvt * | duplicate_pseudo (struct dahdi_pvt *src) |
| 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_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_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_ss7_block_cic (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_ss7_block_linkset (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_ss7_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_ss7_show_linkset (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_ss7_unblock_cic (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_ss7_unblock_linkset (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_ss7_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 | linkset_addsigchan (int sigchan) |
| 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 int | mwi_send_init (struct dahdi_pvt *pvt) |
| static int | mwi_send_process_buffer (struct dahdi_pvt *pvt, int num_read) |
| static int | mwi_send_process_event (struct dahdi_pvt *pvt, int event) |
| 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 | parse_buffers_policy (const char *parse, int *num_buffers, int *policy) |
| static unsigned int | parse_pointcode (const char *pcstring) |
| 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 | ss7_apply_plan_to_number (char *buf, size_t size, const struct dahdi_ss7 *ss7, const char *number, const unsigned nai) |
| static void | ss7_block_cics (struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block) |
| static int | ss7_find_cic (struct dahdi_ss7 *linkset, int cic, unsigned int dpc) |
| static int | ss7_grab (struct dahdi_pvt *pvt, struct dahdi_ss7 *pri) |
| static void | ss7_handle_cqm (struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc) |
| static void | ss7_hangup_cics (struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc) |
| static void | ss7_inservice (struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc) |
| static void * | ss7_linkset (void *data) |
| static int | ss7_pres_scr2cid_pres (char presentation_ind, char screening_ind) |
| static void | ss7_rel (struct dahdi_ss7 *ss7) |
| static void | ss7_reset_linkset (struct dahdi_ss7 *linkset) |
| static struct dahdi_ss7 * | ss7_resolve_linkset (int linkset) |
| static void | ss7_start_call (struct dahdi_pvt *p, struct dahdi_ss7 *linkset) |
| 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 = tdesc , .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 = "0901e4e500243c855563a2d78b0c03e4" , .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 int | cur_adjpointcode = -1 |
| static int | cur_cicbeginswith = -1 |
| static int | cur_defaultdpc = -1 |
| static int | cur_linkset = -1 |
| static int | cur_networkindicator = -1 |
| static int | cur_pointcode = -1 |
| static int | cur_ss7type = -1 |
| static struct ast_cli_entry | dahdi_cli [] |
| static struct ast_cli_entry | dahdi_pri_cli [] |
| static char * | dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" |
| static struct ast_cli_entry | dahdi_ss7_cli [] |
| 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 struct dahdi_ss7 | linksets [NUM_SPANS] |
| static int | matchdigittimeout = 3000 |
| How long to wait for an extra digit, if there is an ambiguous match. | |
| static pthread_t | monitor_thread = AST_PTHREADT_NULL |
| This is the thread for the monitor which checks for input on the channels which are not currently in use. | |
| static ast_mutex_t | monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
| Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical. | |
| static int | mwilevel = 512 |
| static char | mwimonitornotify [PATH_MAX] = "" |
| static int | 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. | |
| struct 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 [] = " & SS7" |
| static int | usedistinctiveringdetection = 0 |
| static int | user_has_defined_cadences = 0 |
DAHDI for Pseudo TDM.
Connects to the DAHDI telephony library as well as libpri. Libpri is optional and needed only if you are going to use ISDN connections.
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 209 of file chan_dahdi.c.
Referenced by dahdi_call(), dahdi_callwait(), dahdi_sendtext(), do_monitor(), mwi_send_init(), mwi_thread(), send_cwcidspill(), and ss_thread().
| #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING) |
Definition at line 294 of file chan_dahdi.c.
Referenced by dahdi_handle_dtmfup().
| #define CALLPROGRESS_FAX_INCOMING 4 |
Definition at line 293 of file chan_dahdi.c.
Referenced by dahdi_new(), and process_dahdi().
| #define CALLPROGRESS_FAX_OUTGOING 2 |
Definition at line 292 of file chan_dahdi.c.
Referenced by dahdi_new().
| #define CALLPROGRESS_PROGRESS 1 |
Definition at line 291 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), and dahdi_new().
| #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) |
10,000 ms
Definition at line 403 of file chan_dahdi.c.
| #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) |
300 ms
Definition at line 402 of file chan_dahdi.c.
| #define CANBUSYDETECT | ( | p | ) | (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
Definition at line 1502 of file chan_dahdi.c.
Referenced by dahdi_new().
| #define CANPROGRESSDETECT | ( | p | ) | (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
Definition at line 1503 of file chan_dahdi.c.
Referenced by dahdi_call(), dahdi_handle_event(), and dahdi_new().
| #define CHAN_PSEUDO -2 |
Definition at line 277 of file chan_dahdi.c.
Referenced by dahdi_new(), dahdi_request(), enable_dtmf_detect(), mkintf(), and process_dahdi().
| #define CHANNEL_PSEUDO -12 |
Definition at line 207 of file chan_dahdi.c.
| #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) |
500 ms
Definition at line 404 of file chan_dahdi.c.
| #define CONF_USER_REAL (1 << 0) |
Definition at line 625 of file chan_dahdi.c.
| #define CONF_USER_THIRDCALL (1 << 1) |
Definition at line 626 of file chan_dahdi.c.
| #define DAHDI_CHAN_MAPPING_LOGICAL 1 |
Definition at line 339 of file chan_dahdi.c.
Referenced by start_pri().
| #define DAHDI_CHAN_MAPPING_PHYSICAL 0 |
Definition at line 338 of file chan_dahdi.c.
| #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING) |
Definition at line 289 of file chan_dahdi.c.
| #define DAHDI_OVERLAPDIAL_INCOMING 2 |
Definition at line 288 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_read(), handle_pri_show_span(), pri_dchannel(), and ss_thread().
| #define DAHDI_OVERLAPDIAL_NONE 0 |
Definition at line 286 of file chan_dahdi.c.
| #define DAHDI_OVERLAPDIAL_OUTGOING 1 |
Definition at line 287 of file chan_dahdi.c.
Referenced by dahdi_read(), and start_pri().
| #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP) |
Definition at line 283 of file chan_dahdi.c.
Referenced by pri_find_dchan(), and pri_is_up().
| #define DCHAN_NOTINALARM (1 << 1) |
Definition at line 280 of file chan_dahdi.c.
Referenced by build_status(), and pri_dchannel().
| #define DCHAN_PROVISIONED (1 << 0) |
Definition at line 279 of file chan_dahdi.c.
Referenced by build_status().
| #define DCHAN_UP (1 << 2) |
Definition at line 281 of file chan_dahdi.c.
Referenced by build_status(), and pri_dchannel().
| #define DEFAULT_CIDRINGS 1 |
Typically, how many rings before we should send Caller*ID.
Definition at line 205 of file chan_dahdi.c.
| #define DEFAULT_PRI_DEBUG 0 |
Definition at line 566 of file chan_dahdi.c.
Referenced by start_pri().
| #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) |
8,000 ms
Definition at line 406 of file chan_dahdi.c.
| #define END_SILENCE_LEN 400 |
Referenced by dahdi_sendtext().
| #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" |
Referenced by __iax2_show_peers(), _sip_show_peers(), alias_show(), dahdi_show_channels(), dahdi_show_status(), dundi_show_mappings(), dundi_show_peers(), dundi_show_precache(), dundi_show_requests(), dundi_show_trans(), gtalk_show_channels(), handle_cli_core_show_channeltypes(), handle_cli_core_show_file_formats(), handle_cli_iax2_show_channels(), handle_cli_iax2_show_registry(), handle_cli_iax2_show_users(), handle_cli_keys_show(), handle_core_show_image_formats(), handle_show_routes(), handle_show_version_files(), jingle_show_channels(), show_channels_cb(), show_chanstats_cb(), sip_show_domains(), sip_show_inuse(), sip_show_mwi(), sip_show_registry(), sip_show_tcp(), and sip_show_users().
| #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n" |
| #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" |
Referenced by __iax2_show_peers(), _sip_show_peers(), dahdi_show_channels(), dahdi_show_status(), dundi_show_mappings(), dundi_show_peers(), dundi_show_precache(), dundi_show_requests(), dundi_show_trans(), handle_cli_core_show_file_formats(), handle_cli_iax2_show_channels(), handle_cli_iax2_show_registry(), handle_cli_iax2_show_users(), handle_core_show_image_formats(), sip_show_channels(), sip_show_channelstats(), sip_show_inuse(), sip_show_registry(), and sip_show_tcp().
| #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n" |
| #define GET_CHANNEL | ( | p | ) | ((p)->bearer ? (p)->bearer->channel : p->channel) |
Definition at line 1425 of file chan_dahdi.c.
Referenced by update_conf().
| #define HANGUP 1 |
Definition at line 15309 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 |
| #define ISTRUNK | ( | p | ) |
Definition at line 1499 of file chan_dahdi.c.
Referenced by dahdi_indicate(), and ss_thread().
| #define LINKSET_FLAG_EXPLICITACM (1 << 0) |
Definition at line 425 of file chan_dahdi.c.
Referenced by ss7_start_call().
| #define LINKSTATE_DOWN (1 << 3) |
Definition at line 421 of file chan_dahdi.c.
Referenced by linkset_addsigchan(), and ss7_linkset().
| #define LINKSTATE_INALARM (1 << 0) |
Definition at line 418 of file chan_dahdi.c.
Referenced by ss7_linkset().
| #define LINKSTATE_STARTING (1 << 1) |
Definition at line 419 of file chan_dahdi.c.
| #define LINKSTATE_UP (1 << 2) |
Definition at line 420 of file chan_dahdi.c.
| #define MASK_AVAIL (1 << 0) |
Channel available for PRI use
Definition at line 399 of file chan_dahdi.c.
| #define MASK_INUSE (1 << 1) |
Channel currently in use
Definition at line 400 of file chan_dahdi.c.
| #define MAX_CHANLIST_LEN 80 |
The length of the parameters list of 'dahdichan'.
Definition at line 16164 of file chan_dahdi.c.
| #define MAX_CHANNELS 672 |
No more than a DS3 per trunk group
Definition at line 275 of file chan_dahdi.c.
Referenced by mkintf().
| #define MAX_SLAVES 4 |
Definition at line 628 of file chan_dahdi.c.
| #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 213 of file chan_dahdi.c.
Referenced by dahdi_new(), and ss_thread().
| #define NUM_CADENCE_MAX 25 |
Definition at line 1474 of file chan_dahdi.c.
Referenced by process_dahdi().
| #define NUM_DCHANS 4 |
No more than 4 d-channels
Definition at line 274 of file chan_dahdi.c.
Referenced by linkset_addsigchan(), and setup_dahdi().
| #define NUM_SPANS 32 |
Definition at line 272 of file chan_dahdi.c.
Referenced by handle_pri_debug(), handle_pri_show_span(), handle_ss7_block_cic(), handle_ss7_block_linkset(), handle_ss7_debug(), handle_ss7_show_linkset(), handle_ss7_unblock_cic(), handle_ss7_unblock_linkset(), linkset_addsigchan(), mkintf(), process_dahdi(), and ss7_resolve_linkset().
| #define POLARITY_IDLE 0 |
Definition at line 584 of file chan_dahdi.c.
| #define POLARITY_REV 1 |
Definition at line 585 of file chan_dahdi.c.
Referenced by ss_thread().
| #define PRI_CHANNEL | ( | p | ) | ((p) & 0xff) |
Definition at line 503 of file chan_dahdi.c.
Referenced by pri_dchannel(), and pri_find_principle().
| #define PRI_EXPLICIT | ( | p | ) | (((p) >> 16) & 0x01) |
Definition at line 505 of file chan_dahdi.c.
Referenced by pri_find_principle().
| #define PRI_SPAN | ( | p | ) | (((p) >> 8) & 0xff) |
Definition at line 504 of file chan_dahdi.c.
Referenced by pri_dchannel(), and pri_find_principle().
| #define PROC_DAHDI_OPT_NOCHAN (1 << 0) |
process_dahdi() - ignore keyword 'channel' and similar
Definition at line 16218 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 16220 of file chan_dahdi.c.
Referenced by process_dahdi(), and setup_dahdi().
| #define PVT_TO_CHANNEL | ( | p | ) | (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0)) |
Definition at line 502 of file chan_dahdi.c.
Referenced by dahdi_call(), dahdi_indicate(), dahdi_write(), pri_check_restart(), pri_dchannel(), and ss_thread().
| #define READ_SIZE 160 |
Chunk size to read -- we use 20ms chunks to make things happy.
Definition at line 397 of file chan_dahdi.c.
Referenced by dahdi_callwait(), dahdi_read(), dahdi_sendtext(), dahdi_setoption(), my_dahdi_write(), process_dahdi(), and send_cwcidspill().
| #define sig2str dahdi_sig2str |
Definition at line 2478 of file chan_dahdi.c.
Referenced by action_dahdishowchannels(), build_channels(), dahdi_handle_event(), dahdi_show_channel(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR) |
Definition at line 256 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 257 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(), pri_dchannel(), pri_find_dchan(), ss_thread(), and start_pri().
| #define SIG_E911 (0x1000000 | DAHDI_SIG_EM) |
Definition at line 245 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_EM DAHDI_SIG_EM |
Definition at line 240 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_EM_E1 DAHDI_SIG_EM_E1 |
Definition at line 265 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM) |
Definition at line 241 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM) |
Definition at line 244 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM) |
Definition at line 242 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM) |
Definition at line 243 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM) |
Definition at line 246 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM) |
Definition at line 247 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM) |
Definition at line 248 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_FXOGS DAHDI_SIG_FXOGS |
Definition at line 253 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_FXOKS DAHDI_SIG_FXOKS |
Definition at line 254 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 252 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_FXSGS DAHDI_SIG_FXSGS |
Definition at line 250 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 251 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(), pri_dchannel(), and ss_thread().
| #define SIG_FXSLS DAHDI_SIG_FXSLS |
Definition at line 249 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS) |
Definition at line 266 of file chan_dahdi.c.
Referenced by dahdi_sig2str(), handle_init_event(), and mkintf().
| #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS) |
Definition at line 267 of file chan_dahdi.c.
Referenced by dahdi_sig2str(), handle_init_event(), and mkintf().
| #define SIG_MFCR2 DAHDI_SIG_CAS |
Definition at line 259 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_sig2str(), do_monitor(), and mkintf().
| #define SIG_PRI DAHDI_SIG_CLEAR |
Definition at line 255 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 260 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF) |
Definition at line 264 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF) |
Definition at line 262 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF) |
Definition at line 263 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF) |
Definition at line 261 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR) |
Definition at line 258 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 |
Definition at line 159 of file chan_dahdi.c.
Referenced by ss_thread().
| #define SS7_NAI_DYNAMIC -1 |
Definition at line 423 of file chan_dahdi.c.
Referenced by dahdi_call().
| #define SUB_CALLWAIT 1 |
Call-Waiting call on hold
Definition at line 580 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 579 of file chan_dahdi.c.
Referenced by __dahdi_exception(), attempt_transfer(), available(), bump_gains(), check_for_conference(), dahdi_answer(), dahdi_bridge(), dahdi_call(), dahdi_confmute(), dahdi_destroy_channel_bynum(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_func_write(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_loopback(), dahdi_new(), dahdi_read(), dahdi_request(), dahdi_restart(), dahdi_ring_phone(), dahdi_set_hwgain(), dahdi_set_swgain(), dahdi_setoption(), dahdi_show_channel(), dahdi_train_ec(), dahdi_unlink(), destroy_dahdi_pvt(), disable_dtmf_detect(), do_monitor(), duplicate_pseudo(), enable_dtmf_detect(), get_alarms(), handle_init_event(), mkintf(), mwi_send_init(), mwi_send_process_buffer(), mwi_send_process_event(), mwi_thread(), pri_assign_bearer(), pri_dchannel(), pri_fixup_principle(), reset_conf(), restore_conference(), restore_gains(), save_conference(), send_callerid(), ss7_start_call(), ss_thread(), and update_conf().
| #define SUB_THREEWAY 2 |
Three-way call
Definition at line 581 of file chan_dahdi.c.
Referenced by attempt_transfer(), available(), dahdi_answer(), dahdi_bridge(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_show_channel(), and ss_thread().
| #define TRAILER_MS 5 |
| #define TRANSFER 0 |
Definition at line 15308 of file chan_dahdi.c.
Referenced by action_transfer(), and dahdi_fake_event().
| enum mwisend_states |
| MWI_SEND_NULL | |
| MWI_SEND_SA | |
| MWI_SEND_SA_WAIT | |
| MWI_SEND_PAUSE | |
| MWI_SEND_SPILL | |
| MWI_SEND_CLEANUP | |
| MWI_SEND_DONE |
Definition at line 633 of file chan_dahdi.c.
{
MWI_SEND_NULL = 0,
MWI_SEND_SA,
MWI_SEND_SA_WAIT,
MWI_SEND_PAUSE,
MWI_SEND_SPILL,
MWI_SEND_CLEANUP,
MWI_SEND_DONE,
} mwisend_states;
| static struct ast_frame* __dahdi_exception | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 6687 of file chan_dahdi.c.
References ast_channel::_state, ast_bridged_channel(), AST_CONTROL_UNHOLD, ast_debug, ast_log(), ast_queue_control(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_tv(), ast_tvnow(), ast_verb, dahdi_pvt::callwaitingrepeat, dahdi_pvt::channel, dahdi_pvt::cidcwexpire, 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, dahdi_subchannel::dfd, dahdi_pvt::dialing, event2str(), dahdi_subchannel::f, dahdi_pvt::fake_event, ast_channel::fds, dahdi_pvt::flashtime, ast_frame::frametype, LOG_WARNING, ast_frame::mallocd, ast_channel::name, dahdi_subchannel::needanswer, 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().
{
struct dahdi_pvt *p = ast->tech_pvt;
int res;
int usedindex=-1;
int idx;
struct ast_frame *f;
idx = dahdi_get_index(ast, p, 1);
p->subs[idx].f.frametype = AST_FRAME_NULL;
p->subs[idx].f.datalen = 0;
p->subs[idx].f.samples = 0;
p->subs[idx].f.mallocd = 0;
p->subs[idx].f.offset = 0;
p->subs[idx].f.subclass = 0;
p->subs[idx].f.delivery = ast_tv(0,0);
p->subs[idx].f.src = "dahdi_exception";
p->subs[idx].f.data.ptr = NULL;
if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
/* If nobody owns us, absorb the event appropriately, otherwise
we loop indefinitely. This occurs when, during call waiting, the
other end hangs up our channel so that it no longer exists, but we
have neither FLASH'd nor ONHOOK'd to signify our desire to
change to the other channel. */
if (p->fake_event) {
res = p->fake_event;
p->fake_event = 0;
} else
res = dahdi_get_event(p->subs[SUB_REAL].dfd);
/* Switch to real if there is one and this isn't something really silly... */
if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
(res != DAHDI_EVENT_HOOKCOMPLETE)) {
ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
p->owner = p->subs[SUB_REAL].owner;
if (p->owner && ast_bridged_channel(p->owner))
ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
p->subs[SUB_REAL].needunhold = 1;
}
switch (res) {
case DAHDI_EVENT_ONHOOK:
dahdi_disable_ec(p);
if (p->owner) {
ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
dahdi_ring_phone(p);
p->callwaitingrepeat = 0;
p->cidcwexpire = 0;
} else
ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
update_conf(p);
break;
case DAHDI_EVENT_RINGOFFHOOK:
dahdi_enable_ec(p);
dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
p->subs[SUB_REAL].needanswer = 1;
p->dialing = 0;
}
break;
case DAHDI_EVENT_HOOKCOMPLETE:
case DAHDI_EVENT_RINGERON:
case DAHDI_EVENT_RINGEROFF:
/* Do nothing */
break;
case DAHDI_EVENT_WINKFLASH:
p->flashtime = ast_tvnow();
if (p->owner) {
ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
if (p->owner->_state != AST_STATE_UP) {
/* Answer if necessary */
usedindex = dahdi_get_index(p->owner, p, 0);
if (usedindex > -1) {
p->subs[usedindex].needanswer = 1;
}
ast_setstate(p->owner, AST_STATE_UP);
}
p->callwaitingrepeat = 0;
p->cidcwexpire = 0;
if (ast_bridged_channel(p->owner))
ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
p->subs[SUB_REAL].needunhold = 1;
} else
ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
update_conf(p);
break;
default:
ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
}
f = &p->subs[idx].f;
return f;
}
if (!(p->radio || (p->oprmode < 0)))
ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
/* If it's not us, return NULL immediately */
if (ast != p->owner) {
ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
f = &p->subs[idx].f;
return f;
}
f = dahdi_handle_event(ast);
return f;
}
| static void __reg_module | ( | void | ) | [static] |
Definition at line 17601 of file chan_dahdi.c.
| static int __unload_module | ( | void | ) | [static] |
Definition at line 15975 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_close_pri_fd(), dahdi_close_ss7_fd(), destroy_all_channels(), iflist, iflock, linksets, master, monlock, dahdi_pvt::next, dahdi_pvt::owner, and pris.
Referenced by load_module(), and unload_module().
{
struct dahdi_pvt *p;
#if defined(HAVE_PRI) || defined(HAVE_SS7)
int i, j;
#endif
#ifdef HAVE_PRI
for (i = 0; i < NUM_SPANS; i++) {
if (pris[i].master != AST_PTHREADT_NULL)
pthread_cancel(pris[i].master);
}
ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
ast_unregister_application(dahdi_send_keypad_facility_app);
#ifdef HAVE_PRI_PROG_W_CAUSE
ast_unregister_application(dahdi_send_callrerouting_facility_app);
#endif
#endif
#if defined(HAVE_SS7)
for (i = 0; i < NUM_SPANS; i++) {
if (linksets[i].master != AST_PTHREADT_NULL)
pthread_cancel(linksets[i].master);
}
ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
#endif
#if defined(HAVE_OPENR2)
dahdi_r2_destroy_links();
ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
ast_unregister_application(dahdi_accept_r2_call_app);
#endif
ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
ast_manager_unregister( "DAHDIDialOffhook" );
ast_manager_unregister( "DAHDIHangup" );
ast_manager_unregister( "DAHDITransfer" );
ast_manager_unregister( "DAHDIDNDoff" );
ast_manager_unregister( "DAHDIDNDon" );
ast_manager_unregister("DAHDIShowChannels");
ast_manager_unregister("DAHDIRestart");
ast_channel_unregister(&dahdi_tech);
ast_mutex_lock(&iflock);
/* Hangup all interfaces if they have an owner */
p = iflist;
while (p) {
if (p->owner)
ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
p = p->next;
}
ast_mutex_unlock(&iflock);
ast_mutex_lock(&monlock);
if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
pthread_cancel(monitor_thread);
pthread_kill(monitor_thread, SIGURG);
pthread_join(monitor_thread, NULL);
}
monitor_thread = AST_PTHREADT_STOP;
ast_mutex_unlock(&monlock);
destroy_all_channels();
#if defined(HAVE_PRI)
for (i = 0; i < NUM_SPANS; i++) {
if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
pthread_join(pris[i].master, NULL);
for (j = 0; j < NUM_DCHANS; j++) {
dahdi_close_pri_fd(&(pris[i]), j);
}
}
#endif
#if defined(HAVE_SS7)
for (i = 0; i < NUM_SPANS; i++) {
if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
pthread_join(linksets[i].master, NULL);
for (j = 0; j < NUM_DCHANS; j++) {
dahdi_close_ss7_fd(&(linksets[i]), j);
}
}
#endif
ast_cond_destroy(&ss_thread_complete);
return 0;
}
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 17601 of file chan_dahdi.c.
| static int action_dahdidialoffhook | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 15415 of file chan_dahdi.c.
References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_queue_frame(), find_channel(), and dahdi_pvt::owner.
Referenced by load_module().
{
struct dahdi_pvt *p = NULL;
const char *channel = astman_get_header(m, "DAHDIChannel");
const char *number = astman_get_header(m, "Number");
int i;
if (ast_strlen_zero(channel)) {
astman_send_error(s, m, "No channel specified");
return 0;
}
if (ast_strlen_zero(number)) {
astman_send_error(s, m, "No number specified");
return 0;
}
p = find_channel(atoi(channel));
if (!p) {
astman_send_error(s, m, "No such channel");
return 0;
}
if (!p->owner) {
astman_send_error(s, m, "Channel does not have it's owner");
return 0;
}
for (i = 0; i < strlen(number); i++) {
struct ast_frame f = { AST_FRAME_DTMF, number[i] };
dahdi_queue_frame(p, &f, NULL);
}
astman_send_ack(s, m, "DAHDIDialOffhook");
return 0;
}
| static int action_dahdidndoff | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 15358 of file chan_dahdi.c.
References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_pvt::dnd, and find_channel().
Referenced by load_module().
{
struct dahdi_pvt *p = NULL;
const char *channel = astman_get_header(m, "DAHDIChannel");
if (ast_strlen_zero(channel)) {
astman_send_error(s, m, "No channel specified");
return 0;
}
p = find_channel(atoi(channel));
if (!p) {
astman_send_error(s, m, "No such channel");
return 0;
}
p->dnd = 0;
astman_send_ack(s, m, "DND Disabled");
return 0;
}
| static int action_dahdidndon | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 15339 of file chan_dahdi.c.
References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_pvt::dnd, and find_channel().
Referenced by load_module().
{
struct dahdi_pvt *p = NULL;
const char *channel = astman_get_header(m, "DAHDIChannel");
if (ast_strlen_zero(channel)) {
astman_send_error(s, m, "No channel specified");
return 0;
}
p = find_channel(atoi(channel));
if (!p) {
astman_send_error(s, m, "No such channel");
return 0;
}
p->dnd = 1;
astman_send_ack(s, m, "DND Enabled");
return 0;
}
| static int action_dahdirestart | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 14600 of file chan_dahdi.c.
References astman_send_ack(), astman_send_error(), and dahdi_restart().
Referenced by load_module().
{
if (dahdi_restart() != 0) {
astman_send_error(s, m, "Failed rereading DAHDI configuration");
return 1;
}
astman_send_ack(s, m, "DAHDIRestart: Success");
return 0;
}
| static int action_dahdishowchannels | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 15447 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, dahdi_pvt::sig, sig2str, and ast_channel::uniqueid.
Referenced by load_module().
{
struct dahdi_pvt *tmp = NULL;
const char *id = astman_get_header(m, "ActionID");
const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
char idText[256] = "";
int channels = 0;
int dahdichanquery = -1;
if (!ast_strlen_zero(dahdichannel)) {
dahdichanquery = atoi(dahdichannel);
}
astman_send_ack(s, m, "DAHDI channel status will follow");
if (!ast_strlen_zero(id))
snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
ast_mutex_lock(&iflock);
tmp = iflist;
while (tmp) {
if (tmp->channel > 0) {
int alm = get_alarms(tmp);
/* If a specific channel is queried for, only deliver status for that channel */
if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
continue;
channels++;
if (tmp->owner) {
/* Add data if we have a current call */
astman_append(s,
"Event: DAHDIShowChannels\r\n"
"DAHDIChannel: %d\r\n"
"Channel: %s\r\n"
"Uniqueid: %s\r\n"
"AccountCode: %s\r\n"
"Signalling: %s\r\n"
"SignallingCode: %d\r\n"
"Context: %s\r\n"
"DND: %s\r\n"
"Alarm: %s\r\n"
"%s"
"\r\n",
tmp->channel,
tmp->owner->name,
tmp->owner->uniqueid,
tmp->owner->accountcode,
sig2str(tmp->sig),
tmp->sig,
tmp->context,
tmp->dnd ? "Enabled" : "Disabled",
alarm2str(alm), idText);
} else {
astman_append(s,
"Event: DAHDIShowChannels\r\n"
"DAHDIChannel: %d\r\n"
"Signalling: %s\r\n"
"SignallingCode: %d\r\n"
"Context: %s\r\n"
"DND: %s\r\n"
"Alarm: %s\r\n"
"%s"
"\r\n",
tmp->channel, sig2str(tmp->sig), tmp->sig,
tmp->context,
tmp->dnd ? "Enabled" : "Disabled",
alarm2str(alm), idText);
}
}
tmp = tmp->next;
}
ast_mutex_unlock(&iflock);
astman_append(s,
"Event: DAHDIShowChannelsComplete\r\n"
"%s"
"Items: %d\r\n"
"\r\n",
idText,
channels);
return 0;
}
| static int action_transfer | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 15377 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(), and TRANSFER.
Referenced by load_module().
{
struct dahdi_pvt *p = NULL;
const char *channel = astman_get_header(m, "DAHDIChannel");
if (ast_strlen_zero(channel)) {
astman_send_error(s, m, "No channel specified");
return 0;
}
p = find_channel(atoi(channel));
if (!p) {
astman_send_error(s, m, "No such channel");
return 0;
}
dahdi_fake_event(p,TRANSFER);
astman_send_ack(s, m, "DAHDITransfer");
return 0;
}
| static int action_transferhangup | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 15396 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(), and HANGUP.
Referenced by load_module().
{
struct dahdi_pvt *p = NULL;
const char *channel = astman_get_header(m, "DAHDIChannel");
if (ast_strlen_zero(channel)) {
astman_send_error(s, m, "No channel specified");
return 0;
}
p = find_channel(atoi(channel));
if (!p) {
astman_send_error(s, m, "No such channel");
return 0;
}
dahdi_fake_event(p,HANGUP);
astman_send_ack(s, m, "DAHDIHangup");
return 0;
}
| static char* alarm2str | ( | int | alm | ) | [static] |
Definition at line 2381 of file chan_dahdi.c.
References alarms, and ARRAY_LEN.
Referenced by action_dahdishowchannels(), and handle_alarms().
| static int alloc_sub | ( | struct dahdi_pvt * | p, | |
| int | x | |||
| ) | [static] |
Definition at line 2177 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 dahdi_handle_event(), dahdi_request(), and ss_thread().
{
struct dahdi_bufferinfo bi;
int res;
if (p->subs[x].dfd >= 0) {
ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
return -1;
}
p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
if (p->subs[x].dfd <= -1) {
ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
return -1;
}
res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
if (!res) {
bi.txbufpolicy = p->buf_policy;
bi.rxbufpolicy = p->buf_policy;
bi.numbufs = p->buf_no;
res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
}
} else
ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
dahdi_close_sub(p, x);
p->subs[x].dfd = -1;
return -1;
}
ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
return 0;
}
| 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 12487 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.
Referenced by pri_dchannel().
{
if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */
snprintf(buf, size, "%s", number);
return;
}
if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
if (size) {
*buf = '\0';
}
return;
}
switch (plan) {
case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
snprintf(buf, size, "%s%s", pri->internationalprefix, number);
break;
case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
snprintf(buf, size, "%s%s", pri->nationalprefix, number);
break;
case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
snprintf(buf, size, "%s%s", pri->localprefix, number);
break;
case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
snprintf(buf, size, "%s%s", pri->privateprefix, number);
break;
case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
snprintf(buf, size, "%s%s", pri->unknownprefix, number);
break;
default: /* other Q.931 dialplan => don't twiddle with callingnum */
snprintf(buf, size, "%s", number);
break;
}
}
| static int attempt_transfer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5587 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_STATE_RING, AST_STATE_RINGING, dahdi_subchannel::dfd, LOG_WARNING, ast_channel::name, dahdi_subchannel::owner, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and unalloc_sub().
Referenced by dahdi_handle_event().
{
/* In order to transfer, we need at least one of the channels to
actually be in a call bridge. We can't conference two applications
together (but then, why would we want to?) */
if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
/* The three-way person we're about to transfer to could still be in MOH, so
stop if now if appropriate */
if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
}
if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
}
if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
return -1;
}
/* Orphan the channel after releasing the lock */
ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
unalloc_sub(p, SUB_THREEWAY);
} else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
}
if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
}
if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
return -1;
}
/* Three-way is now the REAL */
swap_subs(p, SUB_THREEWAY, SUB_REAL);
ast_channel_unlock(p->subs[SUB_REAL].owner);
unalloc_sub(p, SUB_THREEWAY);
/* Tell the caller not to hangup */
return 1;
} else {
ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
return -1;
}
return 0;
}
| static int available | ( | struct dahdi_pvt * | p, | |
| int | channelmatch, | |||
| ast_group_t | groupmatch, | |||
| int * | busy, | |||
| int * | channelmatched, | |||
| int * | groupmatched | |||
| ) | [inline, static] |
Definition at line 10763 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_subchannel::dfd, dahdi_pvt::dnd, errno, dahdi_pvt::group, dahdi_pvt::guardtime, dahdi_subchannel::inthreeway, dahdi_pvt::locallyblocked, LOG_WARNING, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_subchannel::owner, 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, dahdi_pvt::ss7, dahdi_pvt::ss7call, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, and dahdi_pvt::subs.
Referenced by dahdi_request().
{
int res;
struct dahdi_params par;
/* First, check group matching */
if (groupmatch) {
if ((p->group & groupmatch) != groupmatch)
return 0;
*groupmatched = 1;
}
/* Check to see if we have a channel match */
if (channelmatch != -1) {
if (p->channel != channelmatch)
return 0;
*channelmatched = 1;
}
/* We're at least busy at this point */
if (busy) {
if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
*busy = 1;
}
/* If do not disturb, definitely not */
if (p->dnd)
return 0;
/* If guard time, definitely not */
if (p->guardtime && (time(NULL) < p->guardtime))
return 0;
if (p->locallyblocked || p->remotelyblocked)
return 0;
/* If no owner definitely available */
if (!p->owner) {
#ifdef HAVE_PRI
/* Trust PRI */
if (p->pri) {
if (p->resetting || p->call)
return 0;
else
return 1;
}
#endif
#ifdef HAVE_SS7
/* Trust SS7 */
if (p->ss7) {
if (p->ss7call)
return 0;
else
return 1;
}
#endif
#ifdef HAVE_OPENR2
/* Trust MFC/R2 */
if (p->mfcr2) {
if (p->mfcr2call)
return 0;
else
return 1;
}
#endif
/* Trust hook state */
if (p->sig && !(p->radio || (p->oprmode < 0)))
{
/* Check hook state */
if (p->subs[SUB_REAL].dfd > -1) {
memset(&par, 0, sizeof(par));
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
} else {
/* Assume not off hook on CVRS */
res = 0;
par.rxisoffhook = 0;
}
if (res) {
ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
}
else if ((p->sig != SIG_FXSKS) && (p->sig != SIG_FXSGS) && (p->sig != SIG_FXSLS)) {
if (par.rxisoffhook) {
ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
/* Not available when the other end is off hook */
return 0;
}
}
#ifdef DAHDI_CHECK_HOOKSTATE
} else { /* FXO channel case (SIG_FXS--) */
/* Channel bank (using CAS), "onhook" does not necessarily means out of service, so return 1 */
if (par.rxbits > -1)
return 1;
/* TDM FXO card, "onhook" means out of service (no battery on the line) */
if (par.rxisoffhook)
return 1;
else
return 0;
#endif
}
return 1;
}
/* If it's not an FXO, forget about call wait */
if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
return 0;
if (!p->callwaiting) {
/* If they don't have call waiting enabled, then for sure they're unavailable at this point */
return 0;
}
if (p->subs[SUB_CALLWAIT].dfd > -1) {
/* If there is already a call waiting call, then we can't take a second one */
return 0;
}
if ((p->owner->_state != AST_STATE_UP) &&
((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
/* If the current call is not up, then don't allow the call */
return 0;
}
if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
/* Can't take a call wait when the three way calling hasn't been merged yet. */
return 0;
}
/* We're cool */
return 1;
}
| 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 16074 of file chan_dahdi.c.
References ast_log(), ast_strdupa, ast_verb, dahdi_chan_conf::chan, dahdi_chan_conf::is_sig_auto, LOG_ERROR, LOG_WARNING, mkintf(), dahdi_pri::pri, pris, dahdi_pvt::sig, sig2str, strsep(), and dahdi_pri::trunkgroup.
Referenced by process_dahdi().
{
char *c, *chan;
int x, start, finish;
struct dahdi_pvt *tmp;
#ifdef HAVE_PRI
struct dahdi_pri *pri;
int trunkgroup, y;
#endif
if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
return -1;
}
c = ast_strdupa(value);
#ifdef HAVE_PRI
pri = NULL;
if (iscrv) {
if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
return -1;
}
if (trunkgroup < 1) {
ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
return -1;
}
c += y;
for (y = 0; y < NUM_SPANS; y++) {
if (pris[y].trunkgroup == trunkgroup) {
pri = pris + y;
break;
}
}
if (!pri) {
ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
return -1;
}
}
#endif
while ((chan = strsep(&c, ","))) {
if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
/* Range */
} else if (sscanf(chan, "%30d", &start)) {
/* Just one */
finish = start;
} else if (!strcasecmp(chan, "pseudo")) {
finish = start = CHAN_PSEUDO;
if (found_pseudo)
*found_pseudo = 1;
} else {
ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
return -1;
}
if (finish < start) {
ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
x = finish;
finish = start;
start = x;
}
for (x = start; x <= finish; x++) {
#ifdef HAVE_PRI
tmp = mkintf(x, conf, pri, reload);
#else
tmp = mkintf(x, conf, NULL, reload);
#endif
if (tmp) {
#ifdef HAVE_PRI
if (pri)
ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
else
#endif
ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
} else {
ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
(reload == 1) ? "reconfigure" : "register", value);
return -1;
}
}
}
return 0;
}
| static void build_status | ( | char * | s, | |
| size_t | len, | |||
| int | status, | |||
| int | active | |||
| ) | [static] |
Definition at line 13895 of file chan_dahdi.c.
References DCHAN_NOTINALARM, DCHAN_PROVISIONED, and DCHAN_UP.
Referenced by handle_pri_show_span(), and handle_pri_show_spans().
{
if (!s || len < 1) {
return;
}
s[0] = '\0';
if (status & DCHAN_PROVISIONED)
strncat(s, "Provisioned, ", len - strlen(s) - 1);
if (!(status & DCHAN_NOTINALARM))
strncat(s, "In Alarm, ", len - strlen(s) - 1);
if (status & DCHAN_UP)
strncat(s, "Up", len - strlen(s) - 1);
else
strncat(s, "Down", len - strlen(s) - 1);
if (active)
strncat(s, ", Active", len - strlen(s) - 1);
else
strncat(s, ", Standby", len - strlen(s) - 1);
s[len - 1] = '\0';
}
| static int bump_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2838 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::cid_rxgain, dahdi_subchannel::dfd, 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().
{
int res;
/* Bump receive gain by value stored in cid_rxgain */
res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
if (res) {
ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
return -1;
}
return 0;
}
| static int calc_energy | ( | const unsigned char * | buf, | |
| int | len, | |||
| int | law | |||
| ) | [static] |
Definition at line 9020 of file chan_dahdi.c.
References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.
Referenced by do_monitor(), and mwi_thread().
| static int check_for_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5639 of file chan_dahdi.c.
References ast_log(), ast_verb, dahdi_pvt::channel, dahdi_pvt::confno, dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, LOG_WARNING, dahdi_pvt::master, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_handle_event().
{
struct dahdi_confinfo ci;
/* Fine if we already have a master, etc */
if (p->master || (p->confno > -1))
return 0;
memset(&ci, 0, sizeof(ci));
if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
return 0;
}
/* If we have no master and don't have a confno, then
if we're in a conference, it's probably a MeetMe room or
some such, so don't let us 3-way out! */
if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
ast_verb(3, "Avoiding 3-way call when in an external conference\n");
return 1;
}
return 0;
}
| static unsigned char cid_pres2ss7pres | ( | int | cid_pres | ) | [static] |
Definition at line 3090 of file chan_dahdi.c.
Referenced by dahdi_call().
{
return (cid_pres >> 5) & 0x03;
}
| static unsigned char cid_pres2ss7screen | ( | int | cid_pres | ) | [static] |
Definition at line 3097 of file chan_dahdi.c.
Referenced by dahdi_call().
{
return cid_pres & 0x03;
}
| static char* complete_span_4 | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Definition at line 13787 of file chan_dahdi.c.
References complete_span_helper().
Referenced by handle_pri_debug(), and handle_pri_show_span().
{
return complete_span_helper(line,word,pos,state,3);
}
| static char* complete_span_helper | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state, | |||
| int | rpos | |||
| ) | [static] |
Definition at line 13766 of file chan_dahdi.c.
References asprintf(), ast_log(), errno, LOG_WARNING, and pris.
Referenced by complete_span_4().
{
int which, span;
char *ret = NULL;
if (pos != rpos)
return ret;
for (which = span = 0; span < NUM_SPANS; span++) {
if (pris[span].pri && ++which > state) {
if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
}
break;
}
}
return ret;
}
| static int conf_add | ( | struct dahdi_pvt * | p, | |
| struct dahdi_subchannel * | c, | |||
| int | idx, | |||
| int | slavechannel | |||
| ) | [static] |
Definition at line 2480 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().
{
/* If the conference already exists, and we're already in it
don't bother doing anything */
struct dahdi_confinfo zi;
memset(&zi, 0, sizeof(zi));
zi.chan = 0;
if (slavechannel > 0) {
/* If we have only one slave, do a digital mon */
zi.confmode = DAHDI_CONF_DIGITALMON;
zi.confno = slavechannel;
} else {
if (!idx) {
/* Real-side and pseudo-side both participate in conference */
zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
} else
zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
zi.confno = p->confno;
}
if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
return 0;
if (c->dfd < 0)
return 0;
if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
return -1;
}
if (slavechannel < 1) {
p->confno = zi.confno;
}
memcpy(&c->curconf, &zi, sizeof(c->curconf));
ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
return 0;
}
| static int conf_del | ( | struct dahdi_pvt * | p, | |
| struct dahdi_subchannel * | c, | |||
| int | idx | |||
| ) | [static] |
Definition at line 2529 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().
{
struct dahdi_confinfo zi;
if (/* Can't delete if there's no dfd */
(c->dfd < 0) ||
/* Don't delete from the conference if it's not our conference */
!isourconf(p, c)
/* Don't delete if we don't think it's conferenced at all (implied) */
) return 0;
memset(&zi, 0, sizeof(zi));
if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
return -1;
}
ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
memcpy(&c->curconf, &zi, sizeof(c->curconf));
return 0;
}
| static int dahdi_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 4736 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_subchannel::inthreeway, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, ast_channel::name, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::polaritydelaytv, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, dahdi_pvt::radio, dahdi_pvt::ringt, dahdi_pvt::sig, SIG_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_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, dahdi_pvt::span, dahdi_ss7::ss7, dahdi_pvt::ss7, ss7_grab(), ss7_rel(), dahdi_pvt::ss7call, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and ast_channel::tech_pvt.
{
struct dahdi_pvt *p = ast->tech_pvt;
int res = 0;
int idx;
int oldstate = ast->_state;
ast_setstate(ast, AST_STATE_UP);
ast_mutex_lock(&p->lock);
idx = dahdi_get_index(ast, p, 0);
if (idx < 0)
idx = SUB_REAL;
/* nothing to do if a radio channel */
if ((p->radio || (p->oprmode < 0))) {
ast_mutex_unlock(&p->lock);
return 0;
}
switch (p->sig) {
case SIG_FXSLS:
case SIG_FXSGS:
case SIG_FXSKS:
p->ringt = 0;
/* Fall through */
case SIG_EM:
case SIG_EM_E1:
case SIG_EMWINK:
case SIG_FEATD:
case SIG_FEATDMF:
case SIG_FEATDMF_TA:
case SIG_E911:
case SIG_FGC_CAMA:
case SIG_FGC_CAMAMF:
case SIG_FEATB:
case SIG_SF:
case SIG_SFWINK:
case SIG_SF_FEATD:
case SIG_SF_FEATDMF:
case SIG_SF_FEATB:
case SIG_FXOLS:
case SIG_FXOGS:
case SIG_FXOKS:
/* Pick up the line */
ast_debug(1, "Took %s off hook\n", ast->name);
if (p->hanguponpolarityswitch) {
p->polaritydelaytv = ast_tvnow();
}
res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
tone_zone_play_tone(p->subs[idx].dfd, -1);
p->dialing = 0;
if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
if (oldstate == AST_STATE_RINGING) {
ast_debug(1, "Finally swapping real and threeway\n");
tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
swap_subs(p, SUB_THREEWAY, SUB_REAL);
p->owner = p->subs[SUB_REAL].owner;
}
}
if (p->sig & __DAHDI_SIG_FXS) {
dahdi_enable_ec(p);
dahdi_train_ec(p);
}
break;
#ifdef HAVE_PRI
case SIG_BRI:
case SIG_BRI_PTMP:
case SIG_PRI:
/* Send a pri acknowledge */
if (!pri_grab(p, p->pri)) {
p->proceeding = 1;
p->dialing = 0;
res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
pri_rel(p->pri);
} else {
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
res = -1;
}
break;
#endif
#ifdef HAVE_SS7
case SIG_SS7:
if (!ss7_grab(p, p->ss7)) {
p->proceeding = 1;
res = isup_anm(p->ss7->ss7, p->ss7call);
ss7_rel(p->ss7);
} else {
ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
res = -1;
}
break;
#endif
#ifdef HAVE_OPENR2
case SIG_MFCR2:
if (!p->mfcr2_call_accepted) {
/* The call was not accepted on offer nor the user, so it must be accepted now before answering,
openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
p->mfcr2_answer_pending = 1;
if (p->mfcr2_charge_calls) {
ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
} else {
ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
}
} else {
ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
dahdi_r2_answer(p);
}
break;
#endif
case 0:
ast_mutex_unlock(&p->lock);
return 0;
default:
ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
res = -1;
}
ast_mutex_unlock(&p->lock);
return res;
}
| 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 5239 of file chan_dahdi.c.
References ast_channel::_state, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, 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(), ast_channel::fds, ast_frame::frametype, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, dahdi_pri::lock, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, 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().
{
struct ast_channel *who;
struct dahdi_pvt *p0, *p1, *op0, *op1;
struct dahdi_pvt *master = NULL, *slave = NULL;
struct ast_frame *f;
int inconf = 0;
int nothingok = 1;
int ofd0, ofd1;
int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
int os0 = -1, os1 = -1;
int priority = 0;
struct ast_channel *oc0, *oc1;
enum ast_bridge_result res;
#ifdef PRI_2BCT
int triedtopribridge = 0;
#endif
/* For now, don't attempt to native bridge if either channel needs DTMF detection.
There is code below to handle it properly until DTMF is actually seen,
but due to currently unresolved issues it's ignored...
*/
if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
return AST_BRIDGE_FAILED_NOWARN;
ast_channel_lock(c0);
while (ast_channel_trylock(c1)) {
CHANNEL_DEADLOCK_AVOIDANCE(c0);
}
p0 = c0->tech_pvt;
p1 = c1->tech_pvt;
/* cant do pseudo-channels here */
if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
ast_channel_unlock(c0);
ast_channel_unlock(c1);
return AST_BRIDGE_FAILED_NOWARN;
}
oi0 = dahdi_get_index(c0, p0, 0);
oi1 = dahdi_get_index(c1, p1, 0);
if ((oi0 < 0) || (oi1 < 0)) {
ast_channel_unlock(c0);
ast_channel_unlock(c1);
return AST_BRIDGE_FAILED;
}
op0 = p0 = c0->tech_pvt;
op1 = p1 = c1->tech_pvt;
ofd0 = c0->fds[0];
ofd1 = c1->fds[0];
oc0 = p0->owner;
oc1 = p1->owner;
if (ast_mutex_trylock(&p0->lock)) {
/* Don't block, due to potential for deadlock */
ast_channel_unlock(c0);
ast_channel_unlock(c1);
ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
return AST_BRIDGE_RETRY;
}
if (ast_mutex_trylock(&p1->lock)) {
/* Don't block, due to potential for deadlock */
ast_mutex_unlock(&p0->lock);
ast_channel_unlock(c0);
ast_channel_unlock(c1);
ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
return AST_BRIDGE_RETRY;
}
if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
if (p0->owner && p1->owner) {
/* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
master = p0;
slave = p1;
inconf = 1;
} else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
master = p1;
slave = p0;
inconf = 1;
} else {
ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
p0->channel,
oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
p0->subs[SUB_REAL].inthreeway, p0->channel,
oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
p1->subs[SUB_REAL].inthreeway);
}
nothingok = 0;
}
} else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
if (p1->subs[SUB_THREEWAY].inthreeway) {
master = p1;
slave = p0;
nothingok = 0;
}
} else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
if (p0->subs[SUB_THREEWAY].inthreeway) {
master = p0;
slave = p1;
nothingok = 0;
}
} else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
/* We have a real and a call wait. If we're in a three way call, put us in it, otherwise,
don't put us in anything */
if (p1->subs[SUB_CALLWAIT].inthreeway) {
master = p1;
slave = p0;
nothingok = 0;
}
} else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
/* Same as previous */
if (p0->subs[SUB_CALLWAIT].inthreeway) {
master = p0;
slave = p1;
nothingok = 0;
}
}
ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
if (master && slave) {
/* Stop any tones, or play ringtone as appropriate. If they're bridged
in an active threeway call with a channel that is ringing, we should
indicate ringing. */
if ((oi1 == SUB_THREEWAY) &&
p1->subs[SUB_THREEWAY].inthreeway &&
p1->subs[SUB_REAL].owner &&
p1->subs[SUB_REAL].inthreeway &&
(p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
os1 = p1->subs[SUB_REAL].owner->_state;
} else {
ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
tone_zone_play_tone(p0->subs[oi0].dfd, -1);
}
if ((oi0 == SUB_THREEWAY) &&
p0->subs[SUB_THREEWAY].inthreeway &&
p0->subs[SUB_REAL].owner &&
p0->subs[SUB_REAL].inthreeway &&
(p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
os0 = p0->subs[SUB_REAL].owner->_state;
} else {
ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
tone_zone_play_tone(p1->subs[oi0].dfd, -1);
}
if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
if (!p0->echocanbridged || !p1->echocanbridged) {
/* Disable echo cancellation if appropriate */
dahdi_disable_ec(p0);
dahdi_disable_ec(p1);
}
}
dahdi_link(slave, master);
master->inconference = inconf;
} else if (!nothingok)
ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
update_conf(p0);
update_conf(p1);
t0 = p0->subs[SUB_REAL].inthreeway;
t1 = p1->subs[SUB_REAL].inthreeway;
ast_mutex_unlock(&p0->lock);
ast_mutex_unlock(&p1->lock);
ast_channel_unlock(c0);
ast_channel_unlock(c1);
/* Native bridge failed */
if ((!master || !slave) && !nothingok) {
dahdi_enable_ec(p0);
dahdi_enable_ec(p1);
return AST_BRIDGE_FAILED;
}
ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
disable_dtmf_detect(op0);
if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
disable_dtmf_detect(op1);
for (;;) {
struct ast_channel *c0_priority[2] = {c0, c1};
struct ast_channel *c1_priority[2] = {c1, c0};
/* Here's our main loop... Start by locking things, looking for private parts,
and then balking if anything is wrong */
ast_channel_lock(c0);
while (ast_channel_trylock(c1)) {
CHANNEL_DEADLOCK_AVOIDANCE(c0);
}
p0 = c0->tech_pvt;
p1 = c1->tech_pvt;
if (op0 == p0)
i0 = dahdi_get_index(c0, p0, 1);
if (op1 == p1)
i1 = dahdi_get_index(c1, p1, 1);
ast_channel_unlock(c0);
ast_channel_unlock(c1);
if (!timeoutms ||
(op0 != p0) ||
(op1 != p1) ||
(ofd0 != c0->fds[0]) ||
(ofd1 != c1->fds[0]) ||
(p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
(p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
(oc0 != p0->owner) ||
(oc1 != p1->owner) ||
(t0 != p0->subs[SUB_REAL].inthreeway) ||
(t1 != p1->subs[SUB_REAL].inthreeway) ||
(oi0 != i0) ||
(oi1 != i1)) {
ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
op0->channel, oi0, op1->channel, oi1);
res = AST_BRIDGE_RETRY;
goto return_from_bridge;
}
#ifdef PRI_2BCT
if (!triedtopribridge) {
triedtopribridge = 1;
if (p0->pri && p0->pri == p1->pri && p0->transfer && p1->transfer) {
ast_mutex_lock(&p0->pri->lock);
if (p0->call && p1->call) {
pri_channel_bridge(p0->call, p1->call);
}
ast_mutex_unlock(&p0->pri->lock);
}
}
#endif
who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
if (!who) {
ast_debug(1, "Ooh, empty read...\n");
continue;
}
f = ast_read(who);
if (!f || (f->frametype == AST_FRAME_CONTROL)) {
*fo = f;
*rc = who;
res = AST_BRIDGE_COMPLETE;
goto return_from_bridge;
}
if (f->frametype == AST_FRAME_DTMF) {
if ((who == c0) && p0->pulsedial) {
ast_write(c1, f);
} else if ((who == c1) && p1->pulsedial) {
ast_write(c0, f);
} else {
*fo = f;
*rc = who;
res = AST_BRIDGE_COMPLETE;
goto return_from_bridge;
}
}
ast_frfree(f);
/* Swap who gets priority */
priority = !priority;
}
return_from_bridge:
if (op0 == p0)
dahdi_enable_ec(p0);
if (op1 == p1)
dahdi_enable_ec(p1);
if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
enable_dtmf_detect(op0);
if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
enable_dtmf_detect(op1);
dahdi_unlink(slave, master, 1);
return res;
}
| static int dahdi_call | ( | struct ast_channel * | ast, | |
| char * | rdest, | |||
| int | timeout | |||
| ) | [static] |
Definition at line 3103 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_OFFHOOK, AST_STATE_RESERVED, AST_STATE_RINGING, AST_STATE_UP, ast_strlen_zero(), ast_transfercapability2str(), ast_tvnow(), ast_verb, dahdi_pvt::bearer, dahdi_pvt::call, dahdi_pvt::call_ref_pc, dahdi_ss7::called_nai, dahdi_ss7::calling_nai, dahdi_pvt::callwait_name, dahdi_pvt::callwait_num, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitrings, CANPROGRESSDETECT, dahdi_pvt::channel, dahdi_pvt::cic, ast_channel::cid, ast_callerid::cid_ani2, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, cid_pres2ss7pres(), cid_pres2ss7screen(), ast_callerid::cid_rdnis, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_callwait(), dahdi_get_index(), dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialednone, dahdi_pvt::dialing, dahdi_pri::dialplan, dialplan2str(), dahdi_pvt::digital, dahdi_pvt::distinctivering, dahdi_pvt::dop, dahdi_pvt::dpc, dahdi_pvt::dsp, dahdi_pvt::echobreak, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, dahdi_pri::facilityenable, dahdi_pvt::finaldial, dahdi_pvt::gen_add_nai, dahdi_pvt::gen_add_num_plan, dahdi_pvt::gen_add_pres_ind, dahdi_pvt::gen_add_type, dahdi_pvt::gen_dig_scheme, dahdi_pvt::gen_dig_type, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pri::internationalprefix, dahdi_ss7::internationalprefix, IS_DIGITAL, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_pvt::law, dahdi_pri::localdialplan, dahdi_pvt::lock, LOG_DEBUG, LOG_ERROR, LOG_WARNING, dahdi_pvt::logicalspan, dahdi_pvt::lspi_ident, MAX_CALLERID_SIZE, ast_channel::name, dahdi_pri::nationalprefix, dahdi_ss7::nationalprefix, dahdi_subchannel::needbusy, dahdi_subchannel::needringing, dahdi_pri::nodetype, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pvt::owner, pbx_builtin_getvar_helper(), dahdi_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_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, dahdi_ss7::ss7, dahdi_pvt::ss7, ss7_grab(), SS7_NAI_DYNAMIC, ss7_rel(), dahdi_pvt::ss7call, 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, dahdi_pvt::waitfordialtone, dahdi_pvt::waitingfordt, and dahdi_pvt::whichwink.
{
struct dahdi_pvt *p = ast->tech_pvt;
int x, res, idx,mysig;
char *c, *n, *l;
#ifdef HAVE_PRI
char *s = NULL;
#endif
char dest[256]; /* must be same length as p->dialdest */
ast_mutex_lock(&p->lock);
ast_copy_string(dest, rdest, sizeof(dest));
ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
if ((ast->_state == AST_STATE_BUSY)) {
p->subs[SUB_REAL].needbusy = 1;
ast_mutex_unlock(&p->lock);
return 0;
}
if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
ast_mutex_unlock(&p->lock);
return -1;
}
p->waitingfordt.tv_sec = 0;
p->dialednone = 0;
if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */
{
/* Special pseudo -- automatically up */
ast_setstate(ast, AST_STATE_UP);
ast_mutex_unlock(&p->lock);
return 0;
}
x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
if (res)
ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
p->outgoing = 1;
if (IS_DIGITAL(ast->transfercapability)){
set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law);
} else {
set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
}
mysig = p->sig;
if (p->outsigmod > -1)
mysig = p->outsigmod;
switch (mysig) {
case SIG_FXOLS:
case SIG_FXOGS:
case SIG_FXOKS:
if (p->owner == ast) {
/* Normal ring, on hook */
/* Don't send audio while on hook, until the call is answered */
p->dialing = 1;
if (p->use_callerid) {
/* Generate the Caller-ID spill if desired */
if (p->cidspill) {
ast_log(LOG_WARNING, "cidspill already exists??\n");
ast_free(p->cidspill);
}
p->callwaitcas = 0;
if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
p->cidpos = 0;
send_callerid(p);
}
}
/* Choose proper cadence */
if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
p->cidrings = cidrings[p->distinctivering - 1];
} else {
if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
p->cidrings = p->sendcalleridafter;
}
/* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
c = strchr(dest, '/');
if (c)
c++;
if (c && (strlen(c) < p->stripmsd)) {
ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
c = NULL;
}
if (c) {
p->dop.op = DAHDI_DIAL_OP_REPLACE;
snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
} else {
p->dop.dialstr[0] = '\0';
}
x = DAHDI_RING;
if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
ast_mutex_unlock(&p->lock);
return -1;
}
p->dialing = 1;
} else {
/* Call waiting call */
p->callwaitrings = 0;
if (ast->cid.cid_num)
ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
else
p->callwait_num[0] = '\0';
if (ast->cid.cid_name)
ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
else
p->callwait_name[0] = '\0';
/* Call waiting tone instead */
if (dahdi_callwait(ast)) {
ast_mutex_unlock(&p->lock);
return -1;
}
/* Make ring-back */
if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
}
n = ast->cid.cid_name;
l = ast->cid.cid_num;
if (l)
ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
else
p->lastcid_num[0] = '\0';
if (n)
ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
else
p->lastcid_name[0] = '\0';
ast_setstate(ast, AST_STATE_RINGING);
idx = dahdi_get_index(ast, p, 0);
if (idx > -1) {
p->subs[idx].needringing = 1;
}
break;
case SIG_FXSLS:
case SIG_FXSGS:
case SIG_FXSKS:
if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
ast_debug(1, "Ignore possible polarity reversal on line seizure\n");
p->polaritydelaytv = ast_tvnow();
}
/* fall through */
case SIG_EMWINK:
case SIG_EM:
case SIG_EM_E1:
case SIG_FEATD:
case SIG_FEATDMF:
case SIG_E911:
case SIG_FGC_CAMA:
case SIG_FGC_CAMAMF:
case SIG_FEATB:
case SIG_SFWINK:
case SIG_SF:
case SIG_SF_FEATD:
case SIG_SF_FEATDMF:
case SIG_FEATDMF_TA:
case SIG_SF_FEATB:
c = strchr(dest, '/');
if (c)
c++;
else
c = "";
if (strlen(c) < p->stripmsd) {
ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
ast_mutex_unlock(&p->lock);
return -1;
}
#ifdef HAVE_PRI
/* Start the trunk, if not GR-303 */
if (!p->pri) {
#endif
x = DAHDI_START;
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
if (res < 0) {
if (errno != EINPROGRESS) {
ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
ast_mutex_unlock(&p->lock);
return -1;
}
}
#ifdef HAVE_PRI
}
#endif
ast_debug(1, "Dialing '%s'\n", c);
p->dop.op = DAHDI_DIAL_OP_REPLACE;
c += p->stripmsd;
switch (mysig) {
case SIG_FEATD:
l = ast->cid.cid_num;
if (l)
snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
else
snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
break;
case SIG_FEATDMF:
l = ast->cid.cid_num;
if (l)
snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
else
snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
break;
case SIG_FEATDMF_TA:
{
const char *cic, *ozz;
/* If you have to go through a Tandem Access point you need to use this */
ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
if (!ozz)
ozz = defaultozz;
cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
if (!cic)
cic = defaultcic;
if (!ozz || !cic) {
ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
ast_mutex_unlock(&p->lock);
return -1;
}
snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
p->whichwink = 0;
}
break;
case SIG_E911:
ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
break;
case SIG_FGC_CAMA:
snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
break;
case SIG_FGC_CAMAMF:
case SIG_FEATB:
snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
break;
default:
if (p->pulse)
snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
else
snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
break;
}
if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
memset(p->echorest, 'w', sizeof(p->echorest) - 1);
strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
p->echorest[sizeof(p->echorest) - 1] = '\0';
p->echobreak = 1;
p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
} else
p->echobreak = 0;
/* waitfordialtone ? */
#ifdef HAVE_PRI
if (!p->pri) {
#endif
if( p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp ) {
ast_log(LOG_DEBUG, "Defer dialling for %dms or dialtone\n", p->waitfordialtone);
gettimeofday(&p->waitingfordt,NULL);
ast_setstate(ast, AST_STATE_OFFHOOK);
break;
}
#ifdef HAVE_PRI
}
#endif
if (!res) {
if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
int saveerr = errno;
x = DAHDI_ONHOOK;
ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
ast_mutex_unlock(&p->lock);
return -1;
}
} else
ast_debug(1, "Deferring dialing...\n");
p->dialing = 1;
if (ast_strlen_zero(c))
p->dialednone = 1;
ast_setstate(ast, AST_STATE_DIALING);
break;
case 0:
/* Special pseudo -- automatically up*/
ast_setstate(ast, AST_STATE_UP);
break;
case SIG_PRI:
case SIG_BRI:
case SIG_BRI_PTMP:
case SIG_SS7:
case SIG_MFCR2:
/* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
p->dialdest[0] = '\0';
p->dialing = 1;
break;
default:
ast_debug(1, "not yet implemented\n");
ast_mutex_unlock(&p->lock);
return -1;
}
#ifdef HAVE_SS7
if (p->ss7) {
char ss7_called_nai;
int called_nai_strip;
char ss7_calling_nai;
int calling_nai_strip;
const char *charge_str = NULL;
const char *gen_address = NULL;
const char *gen_digits = NULL;
const char *gen_dig_type = NULL;
const char *gen_dig_scheme = NULL;
const char *gen_name = NULL;
const char *jip_digits = NULL;
const char *lspi_ident = NULL;
const char *rlt_flag = NULL;
const char *call_ref_id = NULL;
const char *call_ref_pc = NULL;
const char *send_far = NULL;
c = strchr(dest, '/');
if (c) {
c++;
} else {
c = "";
}
if (strlen(c) < p->stripmsd) {
ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
ast_mutex_unlock(&p->lock);
return -1;
}
if (!p->hidecallerid) {
l = ast->cid.cid_num;
} else {
l = NULL;
}
if (ss7_grab(p, p->ss7)) {
ast_log(LOG_WARNING, "Failed to grab SS7!\n");
ast_mutex_unlock(&p->lock);
return -1;
}
p->digital = IS_DIGITAL(ast->transfercapability);
p->ss7call = isup_new_call(p->ss7->ss7);
if (!p->ss7call) {
ss7_rel(p->ss7);
ast_mutex_unlock(&p->lock);
ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
return -1;
}
called_nai_strip = 0;
ss7_called_nai = p->ss7->called_nai;
if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */
if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
called_nai_strip = strlen(p->ss7->internationalprefix);
ss7_called_nai = SS7_NAI_INTERNATIONAL;
} else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
called_nai_strip = strlen(p->ss7->nationalprefix);
ss7_called_nai = SS7_NAI_NATIONAL;
} else {
ss7_called_nai = SS7_NAI_SUBSCRIBER;
}
}
isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
calling_nai_strip = 0;
ss7_calling_nai = p->ss7->calling_nai;
if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */
if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
calling_nai_strip = strlen(p->ss7->internationalprefix);
ss7_calling_nai = SS7_NAI_INTERNATIONAL;
} else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
calling_nai_strip = strlen(p->ss7->nationalprefix);
ss7_calling_nai = SS7_NAI_NATIONAL;
} else {
ss7_calling_nai = SS7_NAI_SUBSCRIBER;
}
}
isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
isup_set_oli(p->ss7call, ast->cid.cid_ani2);
isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
ast_channel_lock(ast);
/* Set the charge number if it is set */
charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
if (charge_str)
isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
if (gen_address)
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 */
gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
if (gen_digits)
isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
if (gen_name)
isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
if (jip_digits)
isup_set_jip_digits(p->ss7call, jip_digits);
lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
if (lspi_ident)
isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */
}
call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
if (call_ref_id && call_ref_pc) {
isup_set_callref(p->ss7call, atoi(call_ref_id),
call_ref_pc ? atoi(call_ref_pc) : 0);
}
send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
(isup_far(p->ss7->ss7, p->ss7call));
ast_channel_unlock(ast);
isup_iam(p->ss7->ss7, p->ss7call);
ast_setstate(ast, AST_STATE_DIALING);
ss7_rel(p->ss7);
}
#endif /* HAVE_SS7 */
#ifdef HAVE_OPENR2
if (p->mfcr2) {
openr2_calling_party_category_t chancat;
int callres = 0;
char *c, *l;
c = strchr(dest, '/');
if (c) {
c++;
} else {
c = "";
}
if (!p->hidecallerid) {
l = ast->cid.cid_num;
} else {
l = NULL;
}
if (strlen(c) < p->stripmsd) {
ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
ast_mutex_unlock(&p->lock);
return -1;
}
p->dialing = 1;
ast_channel_lock(ast);
chancat = dahdi_r2_get_channel_category(ast);
ast_channel_unlock(ast);
callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
if (-1 == callres) {
ast_mutex_unlock(&p->lock);
ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
return -1;
}
ast_setstate(ast, AST_STATE_DIALING);
}
#endif /* HAVE_OPENR2 */
#ifdef HAVE_PRI
if (p->pri) {
struct pri_sr *sr;
#ifdef SUPPORT_USERUSER
const char *useruser;
#endif
int pridialplan;
int dp_strip;
int prilocaldialplan;
int ldp_strip;
int exclusive;
const char *rr_str;
int redirect_reason;
c = strchr(dest, '/');
if (c) {
c++;
} else {
c = "";
}
l = NULL;
n = NULL;
if (!p->hidecallerid) {
/* If we get to the end of this loop without breaking, there's no
* numeric calleridnum. This is done instead of testing for
* "unknown" or the thousands of other ways that the calleridnum
* could be invalid. */
for (l = ast->cid.cid_num; l && *l; l++) {
if (strchr("0123456789", *l)) {
l = ast->cid.cid_num;
break;
}
}
if (!p->hidecalleridname) {
n = ast->cid.cid_name;
}
}
if (strlen(c) < p->stripmsd) {
ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
ast_mutex_unlock(&p->lock);
return -1;
}
if (mysig != SIG_FXSKS) {
p->dop.op = DAHDI_DIAL_OP_REPLACE;
s = strchr(c + p->stripmsd, 'w');
if (s) {
if (strlen(s) > 1)
snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
else
p->dop.dialstr[0] = '\0';
*s = '\0';
} else {
p->dop.dialstr[0] = '\0';
}
}
if (pri_grab(p, p->pri)) {
ast_log(LOG_WARNING, "Failed to grab PRI!\n");
ast_mutex_unlock(&p->lock);
return -1;
}
if (!(p->call = pri_new_call(p->pri->pri))) {
ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
pri_rel(p->pri);
ast_mutex_unlock(&p->lock);
return -1;
}
if (!(sr = pri_sr_new())) {
ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
pri_rel(p->pri);
ast_mutex_unlock(&p->lock);
}
if (p->bearer || (mysig == SIG_FXSKS)) {
if (p->bearer) {
ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
p->bearer->call = p->call;
} else
ast_debug(1, "I'm being setup with no bearer right now...\n");
pri_set_crv(p->pri->pri, p->call, p->channel, 0);
}
p->digital = IS_DIGITAL(ast->transfercapability);
/* Should the picked channel be used exclusively? */
if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
exclusive = 1;
} else {
exclusive = 0;
}
pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
(p->digital ? -1 :
((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
if (p->pri->facilityenable)
pri_facility_enable(p->pri->pri);
ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
dp_strip = 0;
pridialplan = p->pri->dialplan - 1;
if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */
if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
if (pridialplan == -2) {
dp_strip = strlen(p->pri->internationalprefix);
}
pridialplan = PRI_INTERNATIONAL_ISDN;
} else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
if (pridialplan == -2) {
dp_strip = strlen(p->pri->nationalprefix);
}
pridialplan = PRI_NATIONAL_ISDN;
} else {
pridialplan = PRI_LOCAL_ISDN;
}
}
while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
switch (c[p->stripmsd]) {
case 'U':
pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
break;
case 'I':
pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
break;
case 'N':
pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
break;
case 'L':
pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
break;
case 'S':
pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
break;
case 'V':
pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
break;
case 'R':
pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
break;
case 'u':
pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
break;
case 'e':
pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
break;
case 'x':
pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
break;
case 'f':
pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
break;
case 'n':
pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
break;
case 'p':
pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
break;
case 'r':
pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
break;
default:
if (isalpha(c[p->stripmsd])) {
ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
}
break;
}
c++;
}
pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
ldp_strip = 0;
prilocaldialplan = p->pri->localdialplan - 1;
if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */
if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
if (prilocaldialplan == -2) {
ldp_strip = strlen(p->pri->internationalprefix);
}
prilocaldialplan = PRI_INTERNATIONAL_ISDN;
} else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
if (prilocaldialplan == -2) {
ldp_strip = strlen(p->pri->nationalprefix);
}
prilocaldialplan = PRI_NATIONAL_ISDN;
} else {
prilocaldialplan = PRI_LOCAL_ISDN;
}
}
if (l != NULL) {
while (*l > '9' && *l != '*' && *l != '#') {
switch (*l) {
case 'U':
prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
break;
case 'I':
prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
break;
case 'N':
prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
break;
case 'L':
prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
break;
case 'S':
prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
break;
case 'V':
prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
break;
case 'R':
prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
break;
case 'u':
prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
break;
case 'e':
prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
break;
case 'x':
prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
break;
case 'f':
prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
break;
case 'n':
prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
break;
case 'p':
prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
break;
case 'r':
prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
break;
default:
if (isalpha(*l)) {
ast_log(LOG_WARNING,
"Unrecognized prilocaldialplan %s modifier: %c\n",
*l > 'Z' ? "NPI" : "TON", *l);
}
break;
}
l++;
}
}
pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
if (!strcasecmp(rr_str, "UNKNOWN"))
redirect_reason = 0;
else if (!strcasecmp(rr_str, "BUSY"))
redirect_reason = 1;
else if (!strcasecmp(rr_str, "NO_REPLY") || !strcasecmp(rr_str, "NOANSWER"))
/* the NOANSWER is to match diversion-reason from chan_sip, (which never reads PRIREDIRECTREASON) */
redirect_reason = 2;
else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
redirect_reason = 15;
else
redirect_reason = PRI_REDIR_UNCONDITIONAL;
} else
redirect_reason = PRI_REDIR_UNCONDITIONAL;
pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
#ifdef SUPPORT_USERUSER
/* User-user info */
useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
if (useruser)
pri_sr_set_useruser(sr, useruser);
#endif
if (pri_setup(p->pri->pri, p->call, sr)) {
ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
pri_rel(p->pri);
ast_mutex_unlock(&p->lock);
pri_sr_free(sr);
return -1;
}
pri_sr_free(sr);
ast_setstate(ast, AST_STATE_DIALING);
pri_rel(p->pri);
}
#endif
ast_mutex_unlock(&p->lock);
return 0;
}
| static int dahdi_callwait | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3061 of file chan_dahdi.c.
References ast_free, ast_gen_cas(), AST_LAW, ast_log(), ast_malloc, dahdi_pvt::callwaitcas, 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().
{
struct dahdi_pvt *p = ast->tech_pvt;
p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
if (p->cidspill) {
ast_log(LOG_WARNING, "Spill already exists?!?\n");
ast_free(p->cidspill);
}
if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
return -1;
save_conference(p);
/* Silence */
memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
if (!p->callwaitrings && p->callwaitingcallerid) {
ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
p->callwaitcas = 1;
p->cidlen = 2400 + 680 + READ_SIZE * 4;
} else {
ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
p->callwaitcas = 0;
p->cidlen = 2400 + READ_SIZE * 4;
}
p->cidpos = 0;
send_callerid(p);
return 0;
}
| static struct dahdi_chan_conf dahdi_chan_conf_default | ( | void | ) | [static, read] |
returns a new dahdi_chan_conf with default values (by-value)
Definition at line 1266 of file chan_dahdi.c.
References dahdi_pri::nsf, and dahdi_chan_conf::pri.
Referenced by process_dahdi(), and setup_dahdi().
{
/* recall that if a field is not included here it is initialized
* to 0 or equivalent
*/
struct dahdi_chan_conf conf = {
#ifdef HAVE_PRI
.pri = {
.nsf = PRI_NSF_NONE,
.switchtype = PRI_SWITCH_NI2,
.dialplan = PRI_UNKNOWN + 1,
.localdialplan = PRI_NATIONAL_ISDN + 1,
.nodetype = PRI_CPE,
.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
.minunused = 2,
.idleext = "",
.idledial = "",
.internationalprefix = "",
.nationalprefix = "",
.localprefix = "",
.privateprefix = "",
.unknownprefix = "",
.resetinterval = -1,
},
#endif
#ifdef HAVE_SS7
.ss7 = {
.called_nai = SS7_NAI_NATIONAL,
.calling_nai = SS7_NAI_NATIONAL,
.internationalprefix = "",
.nationalprefix = "",
.subscriberprefix = "",
.unknownprefix = ""
},
#endif
#ifdef HAVE_OPENR2
.mfcr2 = {
.variant = OR2_VAR_ITU,
.mfback_timeout = -1,
.metering_pulse_timeout = -1,
.max_ani = 10,
.max_dnis = 4,
.get_ani_first = -1,
#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
.skip_category_request = -1,
#endif
.call_files = 0,
.allow_collect_calls = 0,
.charge_calls = 1,
.accept_on_offer = 1,
.forced_release = 0,
.double_answer = 0,
.immediate_accept = -1,
.logdir = "",
.r2proto_file = "",
.loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
},
#endif
.chan = {
.context = "default",
.cid_num = "",
.cid_name = "",
.mohinterpret = "default",
.mohsuggest = "",
.parkinglot = "",
.transfertobusy = 1,
.cid_signalling = CID_SIG_BELL,
.cid_start = CID_START_RING,
.dahditrcallerid = 0,
.use_callerid = 1,
.sig = -1,
.outsigmod = -1,
.cid_rxgain = +5.0,
.tonezone = -1,
.echocancel.head.tap_length = 1,
.busycount = 3,
.accountcode = "",
.mailbox = "",
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
.mwisend_fsk = 1,
#endif
.polarityonanswerdelay = 600,
.sendcalleridafter = DEFAULT_CIDRINGS,
.buf_policy = DAHDI_POLICY_IMMEDIATE,
.buf_no = numbufs,
.usefaxbuffers = 0,
.faxbuf_policy = DAHDI_POLICY_IMMEDIATE,
.faxbuf_no = numbufs,
},
.timing = {
.prewinktime = -1,
.preflashtime = -1,
.winktime = -1,
.flashtime = -1,
.starttime = -1,
.rxwinktime = -1,
.rxflashtime = -1,
.debouncetime = -1
},
.is_sig_auto = 1,
.smdi_port = "/dev/ttyS0",
};
return conf;
}
| static void dahdi_close | ( | int | fd | ) | [static] |
Definition at line 2139 of file chan_dahdi.c.
Referenced by dahdi_close_pri_fd(), dahdi_close_ss7_fd(), and dahdi_close_sub().
{
if (fd > 0)
close(fd);
}
| static void dahdi_close_pri_fd | ( | struct dahdi_pri * | pri, | |
| int | fd_num | |||
| ) | [static] |
Definition at line 2152 of file chan_dahdi.c.
References dahdi_close(), and dahdi_pri::fds.
Referenced by __unload_module(), dahdi_restart(), and start_pri().
{
dahdi_close(pri->fds[fd_num]);
pri->fds[fd_num] = -1;
}
| static void dahdi_close_ss7_fd | ( | struct dahdi_ss7 * | ss7, | |
| int | fd_num | |||
| ) | [static] |
Definition at line 2160 of file chan_dahdi.c.
References dahdi_close(), and dahdi_ss7::fds.
Referenced by __unload_module(), dahdi_restart(), and linkset_addsigchan().
{
dahdi_close(ss7->fds[fd_num]);
ss7->fds[fd_num] = -1;
}
| static void dahdi_close_sub | ( | struct dahdi_pvt * | chan_pvt, | |
| int | sub_num | |||
| ) | [static] |
Definition at line 2145 of file chan_dahdi.c.
References dahdi_close(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by alloc_sub(), destroy_dahdi_pvt(), pri_fixup_principle(), and unalloc_sub().
{
dahdi_close(chan_pvt->subs[sub_num].dfd);
chan_pvt->subs[sub_num].dfd = -1;
}
| static int dahdi_confmute | ( | struct dahdi_pvt * | p, | |
| int | muted | |||
| ) | [inline, static] |
Definition at line 2882 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, 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().
{
int x, y, res;
x = muted;
if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
y = 1;
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
if (res)
ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
}
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
if (res < 0)
ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
return res;
}
| static char* dahdi_destroy_channel | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 14412 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, dahdi_destroy_channel_bynum(), RESULT_SUCCESS, and ast_cli_entry::usage.
{
int channel;
int ret;
switch (cmd) {
case CLI_INIT:
e->command = "dahdi destroy channel";
e->usage =
"Usage: dahdi destroy channel <chan num>\n"
" DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 4)
return CLI_SHOWUSAGE;
channel = atoi(a->argv[3]);
ret = dahdi_destroy_channel_bynum(channel);
return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
}
| static int dahdi_destroy_channel_bynum | ( | int | channel | ) | [static] |
Definition at line 9362 of file chan_dahdi.c.
References ast_module_unref(), dahdi_pvt::channel, destroy_channel(), dahdi_subchannel::dfd, iflist, dahdi_pvt::next, dahdi_pvt::prev, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_destroy_channel(), and do_monitor().
{
struct dahdi_pvt *tmp = NULL;
struct dahdi_pvt *prev = NULL;
tmp = iflist;
while (tmp) {
if (tmp->channel == channel) {
int x = DAHDI_FLASH;
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 */
destroy_channel(prev, tmp, 1);
ast_module_unref(ast_module_info->self);
return RESULT_SUCCESS;
}
prev = tmp;
tmp = tmp->next;
}
return RESULT_FAILURE;
}
| static int dahdi_digit_begin | ( | struct ast_channel * | ast, | |
| char | digit | |||
| ) | [static] |
Definition at line 2247 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, dahdi_get_index(), dahdi_subchannel::dfd, 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.
{
struct dahdi_pvt *pvt;
int idx;
int dtmf = -1;
pvt = chan->tech_pvt;
ast_mutex_lock(&pvt->lock);
idx = dahdi_get_index(chan, pvt, 0);
if ((idx != SUB_REAL) || !pvt->owner)
goto out;
#ifdef HAVE_PRI
if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
&& (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
if (pvt->setup_ack) {
if (!pri_grab(pvt, pvt->pri)) {
pri_information(pvt->pri->pri, pvt->call, digit);
pri_rel(pvt->pri);
} else
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
} else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
int res;
ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit);
res = strlen(pvt->dialdest);
pvt->dialdest[res++] = digit;
pvt->dialdest[res] = '\0';
}
goto out;
}
#endif
if ((dtmf = digit_to_dtmfindex(digit)) == -1)
goto out;
if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
int res;
struct dahdi_dialoperation zo = {
.op = DAHDI_DIAL_OP_APPEND,
};
zo.dialstr[0] = 'T';
zo.dialstr[1] = digit;
zo.dialstr[2] = '\0';
if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
else
pvt->dialing = 1;
} else {
ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
pvt->dialing = 1;
pvt->begindigit = digit;
}
out:
ast_mutex_unlock(&pvt->lock);
return 0;
}
| static int dahdi_digit_end | ( | struct ast_channel * | ast, | |
| char | digit, | |||
| unsigned int | duration | |||
| ) | [static] |
Definition at line 2309 of file chan_dahdi.c.
References ast_debug, ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::begindigit, dahdi_get_index(), dahdi_subchannel::dfd, 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.
{
struct dahdi_pvt *pvt;
int res = 0;
int idx;
int x;
pvt = chan->tech_pvt;
ast_mutex_lock(&pvt->lock);
idx = dahdi_get_index(chan, pvt, 0);
if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
goto out;
#ifdef HAVE_PRI
/* This means that the digit was already sent via PRI signalling */
if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
&& !pvt->begindigit)
goto out;
#endif
if (pvt->begindigit) {
x = -1;
ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
pvt->dialing = 0;
pvt->begindigit = 0;
}
out:
ast_mutex_unlock(&pvt->lock);
return res;
}
| static void dahdi_disable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2711 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, 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().
{
int res;
if (p->echocanon) {
struct dahdi_echocanparams ecp = { .tap_length = 0 };
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
if (res)
ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
else
ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
}
p->echocanon = 0;
}
| 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 |
chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical DAHDI channel). Use this to enable or disable it.
Definition at line 7748 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().
{
/* Do not disturb */
dahdichan->dnd = on;
ast_verb(3, "%s DND on channel %d\n",
on? "Enabled" : "Disabled",
dahdichan->channel);
manager_event(EVENT_FLAG_SYSTEM, "DNDState",
"Channel: DAHDI/%d\r\n"
"Status: %s\r\n", dahdichan->channel,
on? "enabled" : "disabled");
}
| static void dahdi_enable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2662 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, 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(), pri_dchannel(), ss7_linkset(), ss7_start_call(), and ss_thread().
{
int x;
int res;
if (!p)
return;
if (p->echocanon) {
ast_debug(1, "Echo cancellation already on\n");
return;
}
if (p->digital) {
ast_debug(1, "Echo cancellation isn't required on digital connection\n");
return;
}
if (p->echocancel.head.tap_length) {
if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) {
x = 1;
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
if (res)
ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
}
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
if (res) {
ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
} else {
p->echocanon = 1;
ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
}
} else
ast_debug(1, "No echo cancellation requested\n");
}
| static struct ast_frame * dahdi_exception | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 6793 of file chan_dahdi.c.
References __dahdi_exception(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::lock, and ast_channel::tech_pvt.
{
struct dahdi_pvt *p = ast->tech_pvt;
struct ast_frame *f;
ast_mutex_lock(&p->lock);
f = __dahdi_exception(ast);
ast_mutex_unlock(&p->lock);
return f;
}
| static int dahdi_fake_event | ( | struct dahdi_pvt * | p, | |
| int | mode | |||
| ) | [static] |
Definition at line 15311 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::fake_event, HANGUP, LOG_WARNING, ast_channel::name, dahdi_pvt::owner, and TRANSFER.
Referenced by action_transfer(), and action_transferhangup().
{
if (p) {
switch (mode) {
case TRANSFER:
p->fake_event = DAHDI_EVENT_WINKFLASH;
break;
case HANGUP:
p->fake_event = DAHDI_EVENT_ONHOOK;
break;
default:
ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
}
}
return 0;
}
| static int dahdi_fixup | ( | struct ast_channel * | oldchan, | |
| struct ast_channel * | newchan | |||
| ) | [static] |
Definition at line 5532 of file chan_dahdi.c.
References ast_channel::_state, AST_CONTROL_RINGING, ast_debug, ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RINGING, dahdi_pvt::channel, dahdi_indicate(), dahdi_unlink(), dahdi_pvt::lock, ast_channel::name, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::subs, ast_channel::tech_pvt, and update_conf().
{
struct dahdi_pvt *p = newchan->tech_pvt;
int x;
ast_mutex_lock(&p->lock);
ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
if (p->owner == oldchan) {
p->owner = newchan;
}
for (x = 0; x < 3; x++)
if (p->subs[x].owner == oldchan) {
if (!x)
dahdi_unlink(NULL, p, 0);
p->subs[x].owner = newchan;
}
update_conf(p);
ast_mutex_unlock(&p->lock);
if (newchan->_state == AST_STATE_RINGING) {
dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
}
return 0;
}
| static int dahdi_func_read | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 5043 of file chan_dahdi.c.
References ast_copy_string(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::lock, dahdi_pvt::rxgain, ast_channel::tech_pvt, and dahdi_pvt::txgain.
{
struct dahdi_pvt *p = chan->tech_pvt;
int res = 0;
if (!strcasecmp(data, "rxgain")) {
ast_mutex_lock(&p->lock);
snprintf(buf, len, "%f", p->rxgain);
ast_mutex_unlock(&p->lock);
} else if (!strcasecmp(data, "txgain")) {
ast_mutex_lock(&p->lock);
snprintf(buf, len, "%f", p->txgain);
ast_mutex_unlock(&p->lock);
} else {
ast_copy_string(buf, "", len);
res = -1;
}
return res;
}
| static int dahdi_func_write | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| char * | data, | |||
| const char * | value | |||
| ) | [static] |
Definition at line 5095 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, dahdi_pvt::channel, dahdi_subchannel::dfd, errno, LOG_WARNING, parse_buffers_policy(), SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
{
struct dahdi_pvt *p = chan->tech_pvt;
int res = 0;
if (!strcasecmp(data, "buffers")) {
int num_bufs, policy;
if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
struct dahdi_bufferinfo bi = {
.txbufpolicy = policy,
.rxbufpolicy = policy,
.bufsize = p->bufsize,
.numbufs = num_bufs,
};
int bpres;
if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
} else {
p->bufferoverrideinuse = 1;
}
} else {
res = -1;
}
} else {
res = -1;
}
return res;
}
| static int dahdi_get_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition at line 376 of file chan_dahdi.c.
Referenced by __dahdi_exception(), dahdi_handle_event(), do_monitor(), mwi_thread(), and ss_thread().
{
int j;
if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
return -1;
return j;
}
| static int dahdi_get_index | ( | struct ast_channel * | ast, | |
| struct dahdi_pvt * | p, | |||
| int | nullok | |||
| ) | [static] |
Definition at line 1505 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, dahdi_subchannel::owner, 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().
{
int res;
if (p->subs[SUB_REAL].owner == ast)
res = 0;
else if (p->subs[SUB_CALLWAIT].owner == ast)
res = 1;
else if (p->subs[SUB_THREEWAY].owner == ast)
res = 2;
else {
res = -1;
if (!nullok)
ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
}
return res;
}
| static void dahdi_handle_dtmfup | ( | struct ast_channel * | ast, | |
| int | idx, | |||
| struct ast_frame ** | dest | |||
| ) | [static] |
Definition at line 5692 of file chan_dahdi.c.
References ast_async_goto(), ast_channel_lock, ast_channel_unlock, ast_debug, ast_exists_extension(), ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verb, dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, 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(), dahdi_subchannel::dfd, errno, ast_channel::exten, dahdi_subchannel::f, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, dahdi_pvt::faxhandled, ast_frame::frametype, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, ast_channel::name, pbx_builtin_setvar_helper(), S_OR, send_cwcidspill(), ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, and dahdi_pvt::usefaxbuffers.
Referenced by dahdi_handle_event(), and dahdi_read().
{
struct dahdi_pvt *p = ast->tech_pvt;
struct ast_frame *f = *dest;
ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name);
if (p->confirmanswer) {
ast_debug(1, "Confirm answer on %s!\n", ast->name);
/* Upon receiving a DTMF digit, consider this an answer confirmation instead
of a DTMF digit */
p->subs[idx].f.frametype = AST_FRAME_CONTROL;
p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
*dest = &p->subs[idx].f;
/* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
p->confirmanswer = 0;
} else if (p->callwaitcas) {
if ((f->subclass == 'A') || (f->subclass == 'D')) {
ast_debug(1, "Got some DTMF, but it's for the CAS\n");
if (p->cidspill)
ast_free(p->cidspill);
send_cwcidspill(p);
}
p->callwaitcas = 0;
p->subs[idx].f.frametype = AST_FRAME_NULL;
p->subs[idx].f.subclass = 0;
*dest = &p->subs[idx].f;
} else if (f->subclass == 'f') {
/* Fax tone -- Handle and return NULL */
if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
/* If faxbuffers are configured, use them for the fax transmission */
if (p->usefaxbuffers && !p->bufferoverrideinuse) {
struct dahdi_bufferinfo bi = {
.txbufpolicy = p->faxbuf_policy,
.bufsize = p->bufsize,
.numbufs = p->faxbuf_no
};
int res;
if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
ast_log(LOG_WARNING, "Channel '%s' unable to set faxbuffer policy, reason: %s\n", ast->name, strerror(errno));
} else {
p->bufferoverrideinuse = 1;
}
}
p->faxhandled = 1;
if (strcmp(ast->exten, "fax")) {
const char *target_context = S_OR(ast->macrocontext, ast->context);
/* We need to unlock 'ast' here because ast_exists_extension has the
* potential to start autoservice on the channel. Such action is prone
* to deadlock.
*/
ast_mutex_unlock(&p->lock);
ast_channel_unlock(ast);
if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
ast_channel_lock(ast);
ast_mutex_lock(&p->lock);
ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
/* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
if (ast_async_goto(ast, target_context, "fax", 1))
ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
} else {
ast_channel_lock(ast);
ast_mutex_lock(&p->lock);
ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
}
} else {
ast_debug(1, "Already in a fax extension, not redirecting\n");
}
} else {
ast_debug(1, "Fax already handled\n");
}
dahdi_confmute(p, 0);
p->subs[idx].f.frametype = AST_FRAME_NULL;
p->subs[idx].f.subclass = 0;
*dest = &p->subs[idx].f;
}
}
| static struct ast_frame* dahdi_handle_event | ( | struct ast_channel * | ast | ) | [static, read] |
< Digits (or equivalent) have been dialed
< Remote end is ringing
< Line is up
< Line is ringing
< Channel is down and available
< Channel is down, but reserved
< Channel is off hook
< Line is busy
< Digits (or equivalent) have been dialed while offhook
< Channel has detected an incoming call and is waiting for ring
< Digits (or equivalent) have been dialed
< Remote end is ringing
< Line is up
< Line is ringing
Definition at line 5784 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_HOLD, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, 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_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, dahdi_pvt::callprogress, CALLPROGRESS_PROGRESS, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitingrepeat, CANPROGRESSDETECT, ast_channel::cdr, 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::cidcwexpire, 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::dialednone, dahdi_pvt::dialing, DLA_LOCK, DLA_UNLOCK, dahdi_pvt::dop, dahdi_pvt::dsp, dahdi_pvt::echobreak, dahdi_pvt::echocanon, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, event2str(), EVENT_FLAG_SYSTEM, dahdi_subchannel::f, dahdi_pvt::fake_event, dahdi_pvt::finaldial, dahdi_pvt::flashtime, ast_frame::frametype, dahdi_pvt::fxsoffhookstate, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::inalarm, dahdi_subchannel::inthreeway, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, manager_event, MIN_MS_SINCE_FLASH, dahdi_pvt::mohsuggest, dahdi_pvt::msgstate, ast_channel::name, dahdi_subchannel::needanswer, 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, 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_MFCR2, 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(), dahdi_pvt::waitingfordt, and dahdi_pvt::whichwink.
Referenced by __dahdi_exception().
{
int res, x;
int idx, mysig;
char *c;
struct dahdi_pvt *p = ast->tech_pvt;
pthread_t threadid;
struct ast_channel *chan;
struct ast_frame *f;
idx = dahdi_get_index(ast, p, 0);
mysig = p->sig;
if (p->outsigmod > -1)
mysig = p->outsigmod;
p->subs[idx].f.frametype = AST_FRAME_NULL;
p->subs[idx].f.subclass = 0;
p->subs[idx].f.datalen = 0;
p->subs[idx].f.samples = 0;
p->subs[idx].f.mallocd = 0;
p->subs[idx].f.offset = 0;
p->subs[idx].f.src = "dahdi_handle_event";
p->subs[idx].f.data.ptr = NULL;
f = &p->subs[idx].f;
if (idx < 0)
return &p->subs[idx].f;
if (p->fake_event) {
res = p->fake_event;
p->fake_event = 0;
} else
res = dahdi_get_event(p->subs[idx].dfd);
ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
#ifdef HAVE_PRI
if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
/* absorb event */
} else {
#endif
dahdi_confmute(p, 0);
p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
p->subs[idx].f.subclass = res & 0xff;
#ifdef HAVE_PRI
}
#endif
dahdi_handle_dtmfup(ast, idx, &f);
return f;
}
if (res & DAHDI_EVENT_DTMFDOWN) {
ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
/* Mute conference */
dahdi_confmute(p, 1);
p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
p->subs[idx].f.subclass = res & 0xff;
return &p->subs[idx].f;
}
switch (res) {
case DAHDI_EVENT_EC_DISABLED:
ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
p->echocanon = 0;
break;
case DAHDI_EVENT_BITSCHANGED:
#ifdef HAVE_OPENR2
if (p->sig != SIG_MFCR2) {
ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
} else {
ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
openr2_chan_handle_cas(p->r2chan);
}
#else
ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
#endif
case DAHDI_EVENT_PULSE_START:
/* Stop tone if there's a pulse start and the PBX isn't started */
if (!ast->pbx)
tone_zone_play_tone(p->subs[idx].dfd, -1);
break;
case DAHDI_EVENT_DIALCOMPLETE:
#ifdef HAVE_OPENR2
if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
/* we don't need to do anything for this event for R2 signaling
if the call is being setup */
break;
}
#endif
if (p->inalarm) break;
if ((p->radio || (p->oprmode < 0))) break;
if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
return NULL;
}
if (!x) { /* if not still dialing in driver */
dahdi_enable_ec(p);
if (p->echobreak) {
dahdi_train_ec(p);
ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
p->dop.op = DAHDI_DIAL_OP_REPLACE;
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
p->echobreak = 0;
} else {
p->dialing = 0;
if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
/* if thru with dialing after offhook */
if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
ast_setstate(ast, AST_STATE_UP);
p->subs[idx].f.frametype = AST_FRAME_CONTROL;
p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
break;
} else { /* if to state wait for offhook to dial rest */
/* we now wait for off hook */
ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
}
}
if (ast->_state == AST_STATE_DIALING) {
if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
} 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)))) {
ast_setstate(ast, AST_STATE_RINGING);
} else if (!p->answeronpolarityswitch) {
ast_setstate(ast, AST_STATE_UP);
p->subs[idx].f.frametype = AST_FRAME_CONTROL;
p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
/* If aops=0 and hops=1, this is necessary */
p->polarity = POLARITY_REV;
} else {
/* Start clean, so we can catch the change to REV polarity when party answers */
p->polarity = POLARITY_IDLE;
}
}
}
}
break;
case DAHDI_EVENT_ALARM:
#ifdef HAVE_PRI
if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
/* T309 is not enabled : hangup calls when alarm occurs */
if (p->call) {
if (p->pri && p->pri->pri) {
if (!pri_grab(p, p->pri)) {
pri_hangup(p->pri->pri, p->call, -1);
pri_destroycall(p->pri->pri, p->call);
p->call = NULL;
pri_rel(p->pri);
} else
ast_log(LOG_WARNING, "Failed to grab PRI!\n");
} else
ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
}
if (p->owner)
p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
}
}
if (p->bearer)
p->bearer->inalarm = 1;
else
#endif
p->inalarm = 1;
res = get_alarms(p);
handle_alarms(p, res);
#ifdef HAVE_PRI
if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
/* fall through intentionally */
} else {
break;
}
#endif
#ifdef HAVE_SS7
if (p->sig == SIG_SS7)
break;
#endif
#ifdef HAVE_OPENR2
if (p->sig == SIG_MFCR2)
break;
#endif
case DAHDI_EVENT_ONHOOK:
if (p->radio) {
p->subs[idx].f.frametype = AST_FRAME_CONTROL;
p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
break;
}
if (p->oprmode < 0)
{
if (p->oprmode != -1) break;
if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
{
/* Make sure it starts ringing */
dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
save_conference(p->oprpeer);
tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
}
break;
}
switch (p->sig) {
case SIG_FXOLS:
case SIG_FXOGS:
case SIG_FXOKS:
p->onhooktime = time(NULL);
p->fxsoffhookstate = 0;
p->msgstate = -1;
/* Check for some special conditions regarding call waiting */
if (idx == SUB_REAL) {
/* The normal line was hung up */
if (p->subs[SUB_CALLWAIT].owner) {
/* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
swap_subs(p, SUB_CALLWAIT, SUB_REAL);
ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
unalloc_sub(p, SUB_CALLWAIT);
#if 0
p->subs[idx].needanswer = 0;
p->subs[idx].needringing = 0;
#endif
p->callwaitingrepeat = 0;
p->cidcwexpire = 0;
p->owner = NULL;
/* Don't start streaming audio yet if the incoming call isn't up yet */
if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
p->dialing = 1;
dahdi_ring_phone(p);
} else if (p->subs[SUB_THREEWAY].owner) {
unsigned int mssinceflash;
/* Here we have to retain the lock on both the main channel, the 3-way channel, and
the private structure -- not especially easy or clean */
while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
/* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
DLA_UNLOCK(&p->lock);
CHANNEL_DEADLOCK_AVOIDANCE(ast);
/* We can grab ast and p in that order, without worry. We should make sure
nothing seriously bad has happened though like some sort of bizarre double
masquerade! */
DLA_LOCK(&p->lock);
if (p->owner != ast) {
ast_log(LOG_WARNING, "This isn't good...\n");
return NULL;
}
}
if (!p->subs[SUB_THREEWAY].owner) {
ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
return NULL;
}
mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
if (mssinceflash < MIN_MS_SINCE_FLASH) {
/* It hasn't been long enough since the last flashook. This is probably a bounce on
hanging up. Hangup both channels now */
if (p->subs[SUB_THREEWAY].owner)
ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
} else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
if (p->transfer) {
/* In any case this isn't a threeway call anymore */
p->subs[SUB_REAL].inthreeway = 0;
p->subs[SUB_THREEWAY].inthreeway = 0;
/* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
/* Swap subs and dis-own channel */
swap_subs(p, SUB_THREEWAY, SUB_REAL);
p->owner = NULL;
/* Ring the phone */
dahdi_ring_phone(p);
} else {
if ((res = attempt_transfer(p)) < 0) {
p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
if (p->subs[SUB_THREEWAY].owner)
ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
} else if (res) {
/* Don't actually hang up at this point */
if (p->subs[SUB_THREEWAY].owner)
ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
break;
}
}
} else {
p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
if (p->subs[SUB_THREEWAY].owner)
ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
}
} else {
ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
/* Swap subs and dis-own channel */
swap_subs(p, SUB_THREEWAY, SUB_REAL);
p->owner = NULL;
/* Ring the phone */
dahdi_ring_phone(p);
}
}
} else {
ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
}
/* Fall through */
default:
dahdi_disable_ec(p);
return NULL;
}
break;
case DAHDI_EVENT_RINGOFFHOOK:
if (p->inalarm) break;
if (p->oprmode < 0)
{
if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
{
/* Make sure it stops ringing */
dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
restore_conference(p->oprpeer);
}
break;
}
if (p->radio)
{
p->subs[idx].f.frametype = AST_FRAME_CONTROL;
p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
break;
}
/* for E911, its supposed to wait for offhook then dial
the second half of the dial string */
if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
c = strchr(p->dialdest, '/');
if (c)
c++;
else
c = p->dialdest;
if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
if (strlen(p->dop.dialstr) > 4) {
memset(p->echorest, 'w', sizeof(p->echorest) - 1);
strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
p->echorest[sizeof(p->echorest) - 1] = '\0';
p->echobreak = 1;
p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
} else
p->echobreak = 0;
if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
int saveerr = errno;
x = DAHDI_ONHOOK;
ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
return NULL;
}
p->dialing = 1;
return &p->subs[idx].f;
}
switch (p->sig) {
case SIG_FXOLS:
case SIG_FXOGS:
case SIG_FXOKS:
p->fxsoffhookstate = 1;
switch (ast->_state) {
case AST_STATE_RINGING:
dahdi_enable_ec(p);
dahdi_train_ec(p);
p->subs[idx].f.frametype = AST_FRAME_CONTROL;
p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
/* Make sure it stops ringing */
p->subs[SUB_REAL].needringing = 0;
dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
ast_debug(1, "channel %d answered\n", p->channel);
if (p->cidspill) {
/* Cancel any running CallerID spill */
ast_free(p->cidspill);
p->cidspill = NULL;
}
p->dialing = 0;
p->callwaitcas = 0;
if (p->confirmanswer) {
/* Ignore answer if "confirm answer" is enabled */
p->subs[idx].f.frametype = AST_FRAME_NULL;
p->subs[idx].f.subclass = 0;
} else if (!ast_strlen_zero(p->dop.dialstr)) {
/* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
p->dop.dialstr[0] = '\0';
return NULL;
} else {
ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
p->subs[idx].f.frametype = AST_FRAME_NULL;
p->subs[idx].f.subclass = 0;
p->dialing = 1;
}
p->dop.dialstr[0] = '\0';
ast_setstate(ast, AST_STATE_DIALING);
} else
ast_setstate(ast, AST_STATE_UP);
return &p->subs[idx].f;
case AST_STATE_DOWN:
ast_setstate(ast, AST_STATE_RING);
ast->rings = 1;
p->subs[idx].f.frametype = AST_FRAME_CONTROL;
p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
ast_debug(1, "channel %d picked up\n", p->channel);
return &p->subs[idx].f;
case AST_STATE_UP:
/* Make sure it stops ringing */
dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
/* Okay -- probably call waiting*/
if (ast_bridged_channel(p->owner))
ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
p->subs[idx].needunhold = 1;
break;
case AST_STATE_RESERVED:
/* Start up dialtone */
if (has_voicemail(p))
res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
else
res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
break;
default:
ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
}
break;
case SIG_FXSLS:
case SIG_FXSGS:
case SIG_FXSKS:
if (ast->_state == AST_STATE_RING) {
p->ringt = p->ringt_base;
}
/* If we get a ring then we cannot be in
* reversed polarity. So we reset to idle */
ast_debug(1, "Setting IDLE polarity due "
"to ring. Old polarity was %d\n",
p->polarity);
p->polarity = POLARITY_IDLE;
/* Fall through */
case SIG_EM:
case SIG_EM_E1:
case SIG_EMWINK:
case SIG_FEATD:
case SIG_FEATDMF:
case SIG_FEATDMF_TA:
case SIG_E911:
case SIG_FGC_CAMA:
case SIG_FGC_CAMAMF:
case SIG_FEATB:
case SIG_SF:
case SIG_SFWINK:
case SIG_SF_FEATD:
case SIG_SF_FEATDMF:
case SIG_SF_FEATB:
if (ast->_state == AST_STATE_PRERING)
ast_setstate(ast, AST_STATE_RING);
if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
ast_debug(1, "Ring detected\n");
p->subs[idx].f.frametype = AST_FRAME_CONTROL;
p->subs[idx].f.subclass = AST_CONTROL_RING;
} else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
ast_debug(1, "Line answered\n");
if (p->confirmanswer) {
p->subs[idx].f.frametype = AST_FRAME_NULL;
p->subs[idx].f.subclass = 0;
} else {
p->subs[idx].f.frametype = AST_FRAME_CONTROL;
p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
ast_setstate(ast, AST_STATE_UP);
}
} else if (ast->_state != AST_STATE_RING)
ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
break;
default:
ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
}
break;
case DAHDI_EVENT_RINGBEGIN:
switch (p->sig) {
case SIG_FXSLS:
case SIG_FXSGS:
case SIG_FXSKS:
if (ast->_state == AST_STATE_RING) {
p->ringt = p->ringt_base;
}
break;
}
break;
case DAHDI_EVENT_RINGEROFF:
if (p->inalarm) break;
if ((p->radio || (p->oprmode < 0))) break;
ast->rings++;
if ((ast->rings > p->cidrings) && (p->cidspill)) {
ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
ast_free(p->cidspill);
p->cidspill = NULL;
p->callwaitcas = 0;
}
p->subs[idx].f.frametype = AST_FRAME_CONTROL;
p->subs[idx].f.subclass = AST_CONTROL_RINGING;
break;
case DAHDI_EVENT_RINGERON:
break;
case DAHDI_EVENT_NOALARM:
p->inalarm = 0;
#ifdef HAVE_PRI
/* Extremely unlikely but just in case */
if (p->bearer)
p->bearer->inalarm = 0;
#endif
ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
"Channel: %d\r\n", p->channel);
break;
case DAHDI_EVENT_WINKFLASH:
if (p->inalarm) break;
if (p->radio) break;
if (p->oprmode < 0) break;
if (p->oprmode > 1)
{
struct dahdi_params par;
memset(&par, 0, sizeof(par));
if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
{
if (!par.rxisoffhook)
{
/* Make sure it stops ringing */
dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
save_conference(p);
tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
}
}
break;
}
/* Remember last time we got a flash-hook */
p->flashtime = ast_tvnow();
switch (mysig) {
case SIG_FXOLS:
case SIG_FXOGS:
case SIG_FXOKS:
ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
p->callwaitcas = 0;
if (idx != SUB_REAL) {
ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
goto winkflashdone;
}
if (p->subs[SUB_CALLWAIT].owner) {
/* Swap to call-wait */
swap_subs(p, SUB_REAL, SUB_CALLWAIT);
tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
p->owner = p->subs[SUB_REAL].owner;
ast_debug(1, "Making %s the new owner\n", p->owner->name);
if (p->owner->_state == AST_STATE_RINGING) {
ast_setstate(p->owner, AST_STATE_UP);
p->subs[SUB_REAL].needanswer = 1;
}
p->callwaitingrepeat = 0;
p->cidcwexpire = 0;
/* Start music on hold if appropriate */
if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
S_OR(p->mohsuggest, NULL),
!ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
}
p->subs[SUB_CALLWAIT].needhold = 1;
if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
S_OR(p->mohsuggest, NULL),
!ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
}
p->subs[SUB_REAL].needunhold = 1;
} else if (!p->subs[SUB_THREEWAY].owner) {
if (!p->threewaycalling) {
/* Just send a flash if no 3-way calling */
p->subs[SUB_REAL].needflash = 1;
goto winkflashdone;
} else if (!check_for_conference(p)) {
char cid_num[256];
char cid_name[256];
cid_num[0] = 0;
cid_name[0] = 0;
if (p->dahditrcallerid && p->owner) {
if (p->owner->cid.cid_num)
ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
if (p->owner->cid.cid_name)
ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
}
/* XXX This section needs much more error checking!!! XXX */
/* Start a 3-way call if feasible */
if (!((ast->pbx) ||
(ast->_state == AST_STATE_UP) ||
(ast->_state == AST_STATE_RING))) {
ast_debug(1, "Flash when call not up or ringing\n");
goto winkflashdone;
}
if (alloc_sub(p, SUB_THREEWAY)) {
ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
goto winkflashdone;
}
/* Make new channel */
chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
if (p->dahditrcallerid) {
if (!p->origcid_num)
p->origcid_num = ast_strdup(p->cid_num);
if (!p->origcid_name)
p->origcid_name = ast_strdup(p->cid_name);
ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
}
/* Swap things around between the three-way and real call */
swap_subs(p, SUB_THREEWAY, SUB_REAL);
/* Disable echo canceller for better dialing */
dahdi_disable_ec(p);
res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
if (res)
ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
p->owner = chan;
if (!chan) {
ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
} else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
dahdi_enable_ec(p);
ast_hangup(chan);
} else {
struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
int way3bridge = 0, cdr3way = 0;
if (!other) {
other = ast_bridged_channel(p->subs[SUB_REAL].owner);
} else
way3bridge = 1;
if (p->subs[SUB_THREEWAY].owner->cdr)
cdr3way = 1;
ast_verb(3, "Started three way call on channel %d\n", p->channel);
/* Start music on hold if appropriate */
if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
S_OR(p->mohsuggest, NULL),
!ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
}
p->subs[SUB_THREEWAY].needhold = 1;
}
}
} else {
/* Already have a 3 way call */
if (p->subs[SUB_THREEWAY].inthreeway) {
/* Call is already up, drop the last person */
ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
/* If the primary call isn't answered yet, use it */
if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
/* Swap back -- we're dropping the real 3-way that isn't finished yet*/
swap_subs(p, SUB_THREEWAY, SUB_REAL);
p->owner = p->subs[SUB_REAL].owner;
}
/* Drop the last call and stop the conference */
ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
p->subs[SUB_REAL].inthreeway = 0;
p->subs[SUB_THREEWAY].inthreeway = 0;
} else {
/* Lets see what we're up to */
if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
(p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
int otherindex = SUB_THREEWAY;
struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
int way3bridge = 0, cdr3way = 0;
if (!other) {
other = ast_bridged_channel(p->subs[SUB_REAL].owner);
} else
way3bridge = 1;
if (p->subs[SUB_THREEWAY].owner->cdr)
cdr3way = 1;
ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
/* Put them in the threeway, and flip */
p->subs[SUB_THREEWAY].inthreeway = 1;
p->subs[SUB_REAL].inthreeway = 1;
if (ast->_state == AST_STATE_UP) {
swap_subs(p, SUB_THREEWAY, SUB_REAL);
otherindex = SUB_REAL;
}
if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
p->subs[otherindex].needunhold = 1;
p->owner = p->subs[SUB_REAL].owner;
if (ast->_state == AST_STATE_RINGING) {
ast_debug(1, "Enabling ringtone on real and threeway\n");
res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
}
} else {
ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
swap_subs(p, SUB_THREEWAY, SUB_REAL);
p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
p->owner = p->subs[SUB_REAL].owner;
if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
p->subs[SUB_REAL].needunhold = 1;
dahdi_enable_ec(p);
}
}
}
winkflashdone:
update_conf(p);
break;
case SIG_EM:
case SIG_EM_E1:
case SIG_FEATD:
case SIG_SF:
case SIG_SFWINK:
case SIG_SF_FEATD:
case SIG_FXSLS:
case SIG_FXSGS:
if (option_debug) {
if (p->dialing)
ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
else
ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
}
break;
case SIG_FEATDMF_TA:
switch (p->whichwink) {
case 0:
ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
break;
case 1:
ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
break;
case 2:
ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
return NULL;
}
p->whichwink++;
/* Fall through */
case SIG_FEATDMF:
case SIG_E911:
case SIG_FGC_CAMAMF:
case SIG_FGC_CAMA:
case SIG_FEATB:
case SIG_SF_FEATDMF:
case SIG_SF_FEATB:
case SIG_EMWINK:
/* FGD MF and EMWINK *Must* wait for wink */
if (!ast_strlen_zero(p->dop.dialstr)) {
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
p->dop.dialstr[0] = '\0';
return NULL;
} else
ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
}
p->dop.dialstr[0] = '\0';
break;
default:
ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
}
break;
case DAHDI_EVENT_HOOKCOMPLETE:
if (p->inalarm) break;
if ((p->radio || (p->oprmode < 0))) break;
if (p->waitingfordt.tv_sec) break;
switch (mysig) {
case SIG_FXSLS: /* only interesting for FXS */
case SIG_FXSGS:
case SIG_FXSKS:
case SIG_EM:
case SIG_EM_E1:
case SIG_EMWINK:
case SIG_FEATD:
case SIG_SF:
case SIG_SFWINK:
case SIG_SF_FEATD:
if (!ast_strlen_zero(p->dop.dialstr)) {
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
p->dop.dialstr[0] = '\0';
return NULL;
} else
ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
}
p->dop.dialstr[0] = '\0';
p->dop.op = DAHDI_DIAL_OP_REPLACE;
break;
case SIG_FEATDMF:
case SIG_FEATDMF_TA:
case SIG_E911:
case SIG_FGC_CAMA:
case SIG_FGC_CAMAMF:
case SIG_FEATB:
case SIG_SF_FEATDMF:
case SIG_SF_FEATB:
ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
break;
default:
break;
}
break;
case DAHDI_EVENT_POLARITY:
/*
* If we get a Polarity Switch event, this could be
* due to line seizure, remote end connect or remote end disconnect.
*
* Check to see if we should change the polarity state and
* mark the channel as UP or if this is an indication
* of remote end disconnect.
*/
if (p->polarityonanswerdelay > 0) {
/* check if event is not too soon after OffHook or Answer */
if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
switch (ast->_state) {
case AST_STATE_DIALING: /*!< Digits (or equivalent) have been dialed */
case AST_STATE_RINGING: /*!< Remote end is ringing */
if (p->answeronpolarityswitch) {
ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel);
ast_setstate(p->owner, AST_STATE_UP);
p->polarity = POLARITY_REV;
if (p->hanguponpolarityswitch) {
p->polaritydelaytv = ast_tvnow();
}
} else {
ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel);
}
break;
case AST_STATE_UP: /*!< Line is up */
case AST_STATE_RING: /*!< Line is ringing */
if (p->hanguponpolarityswitch) {
ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel);
ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
p->polarity = POLARITY_IDLE;
} else {
ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel);
}
break;
case AST_STATE_DOWN: /*!< Channel is down and available */
case AST_STATE_RESERVED: /*!< Channel is down, but reserved */
case AST_STATE_OFFHOOK: /*!< Channel is off hook */
case AST_STATE_BUSY: /*!< Line is busy */
case AST_STATE_DIALING_OFFHOOK: /*!< Digits (or equivalent) have been dialed while offhook */
case AST_STATE_PRERING: /*!< Channel has detected an incoming call and is waiting for ring */
default:
if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state);
}
}
} else {
/* event is too soon after OffHook or Answer */
switch (ast->_state) {
case AST_STATE_DIALING: /*!< Digits (or equivalent) have been dialed */
case AST_STATE_RINGING: /*!< Remote end is ringing */
if (p->answeronpolarityswitch) {
ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state);
}
break;
case AST_STATE_UP: /*!< Line is up */
case AST_STATE_RING: /*!< Line is ringing */
if (p->hanguponpolarityswitch) {
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);
}
break;
default:
if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state);
}
}
}
}
/* Added more log_debug information below to provide a better indication of what is going on */
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) );
break;
default:
ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
}
return &p->subs[idx].f;
}
| static int dahdi_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 4324 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::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, dahdi_pvt::call, dahdi_pvt::callwaitcas, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingrepeat, dahdi_pvt::channel, dahdi_pvt::cic, 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::fxsoffhookstate, dahdi_pvt::guardtime, ast_channel::hangupcause, dahdi_pvt::hidecallerid, iflist, iflock, dahdi_pvt::ignoredtmf, dahdi_subchannel::inthreeway, dahdi_pvt::law, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, 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, 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_MFCR2, SIG_PRI, SIG_SS7, dahdi_pvt::span, dahdi_ss7::ss7, dahdi_pvt::ss7, ss7_grab(), ss7_rel(), dahdi_pvt::ss7call, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, unalloc_sub(), update_conf(), and dahdi_pvt::waitingfordt.
Referenced by pri_dchannel().
{
int res;
int idx,x, law;
/*static int restore_gains(struct dahdi_pvt *p);*/
struct dahdi_pvt *p = ast->tech_pvt;
struct dahdi_pvt *tmp = NULL;
struct dahdi_pvt *prev = NULL;
struct dahdi_params par;
ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
if (!ast->tech_pvt) {
ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
return 0;
}
ast_mutex_lock(&p->lock);
idx = dahdi_get_index(ast, p, 1);
switch (p->sig) {
case SIG_PRI:
case SIG_BRI:
case SIG_BRI_PTMP:
case SIG_SS7:
x = 1;
ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
/* Fall through */
case SIG_MFCR2:
p->cid_num[0] = '\0';
p->cid_name[0] = '\0';
break;
default:
break;
}
x = 0;
dahdi_confmute(p, 0);
p->muting = 0;
restore_gains(p);
if (p->origcid_num) {
ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
ast_free(p->origcid_num);
p->origcid_num = NULL;
}
if (p->origcid_name) {
ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
ast_free(p->origcid_name);
p->origcid_name = NULL;
}
if (p->dsp)
ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
p->exten[0] = '\0';
ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
p->ignoredtmf = 0;
if (idx > -1) {
/* Real channel, do some fixup */
p->subs[idx].owner = NULL;
p->subs[idx].needanswer = 0;
p->subs[idx].needflash = 0;
p->subs[idx].needringing = 0;
p->subs[idx].needbusy = 0;
p->subs[idx].needcongestion = 0;
p->subs[idx].linear = 0;
p->subs[idx].needcallerid = 0;
p->polarity = POLARITY_IDLE;
dahdi_setlinear(p->subs[idx].dfd, 0);
if (idx == SUB_REAL) {
if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
if (p->subs[SUB_CALLWAIT].inthreeway) {
/* We had flipped over to answer a callwait and now it's gone */
ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
/* Move to the call-wait, but un-own us until they flip back. */
swap_subs(p, SUB_CALLWAIT, SUB_REAL);
unalloc_sub(p, SUB_CALLWAIT);
p->owner = NULL;
} else {
/* The three way hung up, but we still have a call wait */
ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
swap_subs(p, SUB_THREEWAY, SUB_REAL);
unalloc_sub(p, SUB_THREEWAY);
if (p->subs[SUB_REAL].inthreeway) {
/* This was part of a three way call. Immediately make way for
another call */
ast_debug(1, "Call was complete, setting owner to former third call\n");
p->owner = p->subs[SUB_REAL].owner;
} else {
/* This call hasn't been completed yet... Set owner to NULL */
ast_debug(1, "Call was incomplete, setting owner to NULL\n");
p->owner = NULL;
}
p->subs[SUB_REAL].inthreeway = 0;
}
} else if (p->subs[SUB_CALLWAIT].dfd > -1) {
/* Move to the call-wait and switch back to them. */
swap_subs(p, SUB_CALLWAIT, SUB_REAL);
unalloc_sub(p, SUB_CALLWAIT);
p->owner = p->subs[SUB_REAL].owner;
if (p->owner->_state != AST_STATE_UP)
p->subs[SUB_REAL].needanswer = 1;
if (ast_bridged_channel(p->subs[SUB_REAL].owner))
ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
} else if (p->subs[SUB_THREEWAY].dfd > -1) {
swap_subs(p, SUB_THREEWAY, SUB_REAL);
unalloc_sub(p, SUB_THREEWAY);
if (p->subs[SUB_REAL].inthreeway) {
/* This was part of a three way call. Immediately make way for
another call */
ast_debug(1, "Call was complete, setting owner to former third call\n");
p->owner = p->subs[SUB_REAL].owner;
} else {
/* This call hasn't been completed yet... Set owner to NULL */
ast_debug(1, "Call was incomplete, setting owner to NULL\n");
p->owner = NULL;
}
p->subs[SUB_REAL].inthreeway = 0;
}
} else if (idx == SUB_CALLWAIT) {
/* Ditch the holding callwait call, and immediately make it availabe */
if (p->subs[SUB_CALLWAIT].inthreeway) {
/* This is actually part of a three way, placed on hold. Place the third part
on music on hold now */
if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
S_OR(p->mohsuggest, NULL),
!ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
}
p->subs[SUB_THREEWAY].inthreeway = 0;
/* Make it the call wait now */
swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
unalloc_sub(p, SUB_THREEWAY);
} else
unalloc_sub(p, SUB_CALLWAIT);
} else if (idx == SUB_THREEWAY) {
if (p->subs[SUB_CALLWAIT].inthreeway) {
/* The other party of the three way call is currently in a call-wait state.
Start music on hold for them, and take the main guy out of the third call */
if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
S_OR(p->mohsuggest, NULL),
!ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
}
p->subs[SUB_CALLWAIT].inthreeway = 0;
}
p->subs[SUB_REAL].inthreeway = 0;
/* If this was part of a three way call index, let us make
another three way call */
unalloc_sub(p, SUB_THREEWAY);
} else {
/* This wasn't any sort of call, but how are we an index? */
ast_log(LOG_WARNING, "Index found but not any type of call?\n");
}
}
if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
p->owner = NULL;
p->ringt = 0;
p->distinctivering = 0;
p->confirmanswer = 0;
p->cidrings = 1;
p->outgoing = 0;
p->digital = 0;
p->faxhandled = 0;
p->pulsedial = 0;
p->onhooktime = time(NULL);
#if defined(HAVE_PRI) || defined(HAVE_SS7)
p->proceeding = 0;
p->dialing = 0;
p->progress = 0;
p->alerting = 0;
p->setup_ack = 0;
p->rlt = 0;
#endif
if (p->dsp) {
ast_dsp_free(p->dsp);
p->dsp = NULL;
}
if (p->bufferoverrideinuse) {
/* faxbuffers are in use, revert them */
struct dahdi_bufferinfo bi = {
.txbufpolicy = p->buf_policy,
.rxbufpolicy = p->buf_policy,
.bufsize = p->bufsize,
.numbufs = p->buf_no
};
int bpres;
if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
ast_log(LOG_WARNING, "Channel '%s' unable to revert faxbuffer policy: %s\n", ast->name, strerror(errno));
}
p->bufferoverrideinuse = 0;
}
law = DAHDI_LAW_DEFAULT;
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
if (res < 0)
ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
/* Perform low level hangup if no owner left */
#ifdef HAVE_SS7
if (p->ss7) {
if (p->ss7call) {
if (!ss7_grab(p, p->ss7)) {
if (!p->alreadyhungup) {
const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
int icause = ast->hangupcause ? ast->hangupcause : -1;
if (cause) {
if (atoi(cause))
icause = atoi(cause);
}
isup_rel(p->ss7->ss7, p->ss7call, icause);
ss7_rel(p->ss7);
p->alreadyhungup = 1;
} else
ast_log(LOG_WARNING, "Trying to hangup twice!\n");
} else {
ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
res = -1;
}
}
}
#endif
#ifdef HAVE_OPENR2
if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
/* If it's an incoming call, check the mfcr2_forced_release setting */
if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
} else {
const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
: dahdi_ast_cause_to_r2_cause(ast->hangupcause);
dahdi_r2_disconnect_call(p, r2cause);
}
} else if (p->mfcr2call) {
ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
/* since ast_request() was called but not ast_call() we have not yet dialed
and the openr2 stack will not call on_call_end callback, we need to unset
the mfcr2call flag and bump the monitor count so the monitor thread can take
care of this channel events from now on */
p->mfcr2call = 0;
}
#endif
#ifdef HAVE_PRI
if (p->pri) {
#ifdef SUPPORT_USERUSER
const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
#endif
/* Make sure we have a call (or REALLY have a call in the case of a PRI) */
if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
if (!pri_grab(p, p->pri)) {
if (p->alreadyhungup) {
ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n");
#ifdef SUPPORT_USERUSER
pri_call_set_useruser(p->call, useruser);
#endif
pri_hangup(p->pri->pri, p->call, -1);
p->call = NULL;
if (p->bearer)
p->bearer->call = NULL;
} else {
const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
int icause = ast->hangupcause ? ast->hangupcause : -1;
ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
#ifdef SUPPORT_USERUSER
pri_call_set_useruser(p->call, useruser);
#endif
p->alreadyhungup = 1;
if (p->bearer)
p->bearer->alreadyhungup = 1;
if (cause) {
if (atoi(cause))
icause = atoi(cause);
}
pri_hangup(p->pri->pri, p->call, icause);
}
if (res < 0)
ast_log(LOG_WARNING, "pri_disconnect failed\n");
pri_rel(p->pri);
} else {
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
res = -1;
}
} else {
if (p->bearer)
ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
p->call = NULL;
res = 0;
}
}
#endif
if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7)
&& (p->sig != SIG_BRI)
&& (p->sig != SIG_BRI_PTMP))
&& (p->sig != SIG_MFCR2))
res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
}
switch (p->sig) {
case SIG_FXOGS:
case SIG_FXOLS:
case SIG_FXOKS:
memset(&par, 0, sizeof(par));
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
if (!res) {
#if 0
ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
#endif
/* If they're off hook, try playing congestion */
if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
else
tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
p->fxsoffhookstate = par.rxisoffhook;
}
break;
case SIG_FXSGS:
case SIG_FXSLS:
case SIG_FXSKS:
/* Make sure we're not made available for at least two seconds assuming
we were actually used for an inbound or outbound call. */
if (ast->_state != AST_STATE_RESERVED) {
time(&p->guardtime);
p->guardtime += 2;
}
break;
default:
tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
}
if (p->cidspill)
ast_free(p->cidspill);
if (p->sig)
dahdi_disable_ec(p);
x = 0;
ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
p->didtdd = 0;
p->cidspill = NULL;
p->callwaitcas = 0;
p->callwaiting = p->permcallwaiting;
p->hidecallerid = p->permhidecallerid;
p->waitingfordt.tv_sec = 0;
p->dialing = 0;
p->rdnis[0] = '\0';
update_conf(p);
reset_conf(p);
/* Restore data mode */
if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
x = 0;
ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
}
#ifdef HAVE_PRI
if (p->bearer) {
ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
/* Free up the bearer channel as well, and
don't use its file descriptor anymore */
update_conf(p->bearer);
reset_conf(p->bearer);
p->bearer->owner = NULL;
p->bearer->realcall = NULL;
p->bearer = NULL;
p->subs[SUB_REAL].dfd = -1;
p->pri = NULL;
}
#endif
if (num_restart_pending == 0)
restart_monitor();
}
p->callwaitingrepeat = 0;
p->cidcwexpire = 0;
p->oprmode = 0;
ast->tech_pvt = NULL;
ast_mutex_unlock(&p->lock);
ast_module_unref(ast_module_info->self);
ast_verb(3, "Hungup '%s'\n", ast->name);
ast_mutex_lock(&iflock);
if (p->restartpending) {
num_restart_pending--;
}
tmp = iflist;
prev = NULL;
if (p->destroy) {
while (tmp) {
if (tmp == p) {
destroy_channel(prev, tmp, 0);
break;
} else {
prev = tmp;
tmp = tmp->next;
}
}
}
ast_mutex_unlock(&iflock);
return 0;
}
| static int dahdi_indicate | ( | struct ast_channel * | chan, | |
| int | condition, | |||
| const void * | data, | |||
| size_t | datalen | |||
| ) | [static] |
Definition at line 7256 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, dahdi_pvt::alerting, 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_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, dahdi_pvt::call, 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, LOG_WARNING, 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, dahdi_ss7::ss7, dahdi_pvt::ss7, ss7_grab(), ss7_rel(), dahdi_pvt::ss7call, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
Referenced by dahdi_fixup().
{
struct dahdi_pvt *p = chan->tech_pvt;
int res=-1;
int idx;
int func = DAHDI_FLASH;
ast_mutex_lock(&p->lock);
idx = dahdi_get_index(chan, p, 0);
ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
#ifdef HAVE_OPENR2
if (p->mfcr2 && !p->mfcr2_call_accepted) {
ast_mutex_unlock(&p->lock);
/* if this is an R2 call and the call is not yet accepted, we don't want the
tone indications to mess up with the MF tones */
return 0;
}
#endif
if (idx == SUB_REAL) {
switch (condition) {
case AST_CONTROL_BUSY:
#ifdef HAVE_PRI
if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
chan->hangupcause = AST_CAUSE_USER_BUSY;
chan->_softhangup |= AST_SOFTHANGUP_DEV;
res = 0;
} else if (!p->progress &&
((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
&& p->pri && !p->outgoing) {
if (p->pri->pri) {
if (!pri_grab(p, p->pri)) {
#ifdef HAVE_PRI_PROG_W_CAUSE
pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_USER_BUSY); /* cause = 17 */
#else
pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
#endif
pri_rel(p->pri);
}
else
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
}
p->progress = 1;
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
} else
#endif
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
break;
case AST_CONTROL_RINGING:
#ifdef HAVE_PRI
if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
&& p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
if (p->pri->pri) {
if (!pri_grab(p, p->pri)) {
pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
pri_rel(p->pri);
}
else
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
}
p->alerting = 1;
}
#endif
#ifdef HAVE_SS7
if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) {
if (p->ss7->ss7) {
ss7_grab(p, p->ss7);
if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
p->rlt = 1;
if (p->rlt != 1) /* No need to send CPG if call will be RELEASE */
isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
p->alerting = 1;
ss7_rel(p->ss7);
}
}
#endif
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
if (chan->_state != AST_STATE_UP) {
if ((chan->_state != AST_STATE_RING) ||
((p->sig != SIG_FXSKS) &&
(p->sig != SIG_FXSLS) &&
(p->sig != SIG_FXSGS)))
ast_setstate(chan, AST_STATE_RINGING);
}
break;
case AST_CONTROL_PROCEEDING:
ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
#ifdef HAVE_PRI
if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
&& p->pri && !p->outgoing) {
if (p->pri->pri) {
if (!pri_grab(p, p->pri)) {
pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
pri_rel(p->pri);
}
else
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
}
p->proceeding = 1;
p->dialing = 0;
}
#endif
#ifdef HAVE_SS7
/* This IF sends the FAR for an answered ALEG call */
if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){
if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
p->rlt = 1;
}
if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) {
if (p->ss7->ss7) {
ss7_grab(p, p->ss7);
isup_acm(p->ss7->ss7, p->ss7call);
p->proceeding = 1;
ss7_rel(p->ss7);
}
}
#endif
/* don't continue in ast_indicate */
res = 0;
break;
case AST_CONTROL_PROGRESS:
ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
#ifdef HAVE_PRI
p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */
if (!p->progress && !p->alerting && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
&& p->pri && !p->outgoing) {
if (p->pri->pri) {
if (!pri_grab(p, p->pri)) {
#ifdef HAVE_PRI_PROG_W_CAUSE
pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, -1); /* no cause at all */
#else
pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
#endif
pri_rel(p->pri);
}
else
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
}
p->progress = 1;
}
#endif
#ifdef HAVE_SS7
if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) {
if (p->ss7->ss7) {
ss7_grab(p, p->ss7);
isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
p->progress = 1;
ss7_rel(p->ss7);
/* enable echo canceler here on SS7 calls */
dahdi_enable_ec(p);
}
}
#endif
/* don't continue in ast_indicate */
res = 0;
break;
case AST_CONTROL_CONGESTION:
chan->hangupcause = AST_CAUSE_CONGESTION;
#ifdef HAVE_PRI
if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
chan->_softhangup |= AST_SOFTHANGUP_DEV;
res = 0;
} else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
&& p->pri && !p->outgoing) {
if (p->pri) {
if (!pri_grab(p, p->pri)) {
#ifdef HAVE_PRI_PROG_W_CAUSE
pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_SWITCH_CONGESTION); /* cause = 42 */
#else
pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
#endif
pri_rel(p->pri);
} else
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
}
p->progress = 1;
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
} else
#endif
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
break;
case AST_CONTROL_HOLD:
#ifdef HAVE_PRI
if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
if (!pri_grab(p, p->pri)) {
res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
pri_rel(p->pri);
} else
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
} else
#endif
ast_moh_start(chan, data, p->mohinterpret);
break;
case AST_CONTROL_UNHOLD:
#ifdef HAVE_PRI
if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
if (!pri_grab(p, p->pri)) {
res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
pri_rel(p->pri);
} else
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
} else
#endif
ast_moh_stop(chan);
break;
case AST_CONTROL_RADIO_KEY:
if (p->radio)
res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
res = 0;
break;
case AST_CONTROL_RADIO_UNKEY:
if (p->radio)
res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
res = 0;
break;
case AST_CONTROL_FLASH:
/* flash hookswitch */
if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
/* Clear out the dial buffer */
p->dop.dialstr[0] = '\0';
if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
chan->name, strerror(errno));
} else
res = 0;
} else
res = 0;
break;
case AST_CONTROL_SRCUPDATE:
res = 0;
break;
case -1:
res = tone_zone_play_tone(p->subs[idx].dfd, -1);
break;
}
} else
res = 0;
ast_mutex_unlock(&p->lock);
return res;
}
Definition at line 5183 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::channel, LOG_WARNING, dahdi_pvt::master, and dahdi_pvt::slaves.
Referenced by dahdi_bridge().
{
int x;
if (!slave || !master) {
ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
return;
}
for (x = 0; x < MAX_SLAVES; x++) {
if (!master->slaves[x]) {
master->slaves[x] = slave;
break;
}
}
if (x >= MAX_SLAVES) {
ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
master->slaves[MAX_SLAVES - 1] = slave;
}
if (slave->master)
ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
slave->master = master;
ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
}
| static void dahdi_loopback | ( | struct dahdi_pvt * | p, | |
| int | enable | |||
| ) | [static] |
Definition at line 11346 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, errno, LOG_WARNING, dahdi_pvt::loopedback, SUB_REAL, and dahdi_pvt::subs.
Referenced by ss7_linkset().
{
if (p->loopedback != enable) {
if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
return;
}
p->loopedback = enable;
}
}
| static struct ast_channel * dahdi_new | ( | struct dahdi_pvt * | i, | |
| int | state, | |||
| int | startpbx, | |||
| int | idx, | |||
| int | law, | |||
| int | transfercapability | |||
| ) | [static, read] |
Definition at line 7503 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_channel_alloc(), ast_channel_set_fd(), ast_copy_string(), ast_debug, ast_devstate_changed_literal(), ast_dsp_new(), 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_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_buffer(), ast_str_set(), ast_strdup, ast_string_field_set, ast_strlen_zero(), AST_TRANS_CAP_DIGITAL, ast_transfercapability2str(), dahdi_pvt::bearer, dahdi_pvt::busy_quietlength, dahdi_pvt::busy_tonelength, dahdi_pvt::busycount, dahdi_pvt::busydetect, 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_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_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::dnid, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, dahdi_pvt::dsp_features, 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, LOG_WARNING, 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, SUB_REAL, dahdi_pvt::subs, ast_channel::tech, ast_channel::tech_pvt, ast_channel::transfercapability, dahdi_pri::trunkgroup, ast_variable::value, dahdi_pvt::vars, dahdi_pvt::waitfordialtone, and ast_channel::writeformat.
Referenced by dahdi_handle_event(), dahdi_request(), handle_init_event(), mwi_thread(), pri_dchannel(), and ss7_start_call().
{
struct ast_channel *tmp;
int deflaw;
int res;
int x,y;
int features;
struct ast_str *chan_name;
struct ast_variable *v;
struct dahdi_params ps;
if (i->subs[idx].owner) {
ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
return NULL;
}
y = 1;
chan_name = ast_str_alloca(32);
do {
#ifdef HAVE_PRI
if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
else
#endif
if (i->channel == CHAN_PSEUDO)
ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
else
ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
for (x = 0; x < 3; x++) {
if ((idx != x) && i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name), i->subs[x].owner->name + 6))
break;
}
y++;
} while (x < 3);
tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "DAHDI/%s", ast_str_buffer(chan_name));
if (!tmp)
return NULL;
tmp->tech = &dahdi_tech;
memset(&ps, 0, sizeof(ps));
ps.channo = i->channel;
res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
if (res) {
ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
ps.curlaw = DAHDI_LAW_MULAW;
}
if (ps.curlaw == DAHDI_LAW_ALAW)
deflaw = AST_FORMAT_ALAW;
else
deflaw = AST_FORMAT_ULAW;
if (law) {
if (law == DAHDI_LAW_ALAW)
deflaw = AST_FORMAT_ALAW;
else
deflaw = AST_FORMAT_ULAW;
}
ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
tmp->nativeformats = deflaw;
/* Start out assuming ulaw since it's smaller :) */
tmp->rawreadformat = deflaw;
tmp->readformat = deflaw;
tmp->rawwriteformat = deflaw;
tmp->writeformat = deflaw;
i->subs[idx].linear = 0;
dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
features = 0;
if (idx == SUB_REAL) {
if (i->busydetect && CANBUSYDETECT(i))
features |= DSP_FEATURE_BUSY_DETECT;
if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
features |= DSP_FEATURE_CALL_PROGRESS;
if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
features |= DSP_FEATURE_WAITDIALTONE;
if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
(i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
features |= DSP_FEATURE_FAX_DETECT;
}
x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
i->hardwaredtmf = 0;
features |= DSP_FEATURE_DIGIT_DETECT;
} else if (NEED_MFDETECT(i)) {
i->hardwaredtmf = 1;
features |= DSP_FEATURE_DIGIT_DETECT;
}
}
if (features) {
if (i->dsp) {
ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
} else {
if (i->channel != CHAN_PSEUDO)
i->dsp = ast_dsp_new();
else
i->dsp = NULL;
if (i->dsp) {
i->dsp_features = features;
#if defined(HAVE_PRI) || defined(HAVE_SS7)
/* We cannot do progress detection until receives PROGRESS message */
if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
/* Remember requested DSP features, don't treat
talking as ANSWER */
i->dsp_features = features & ~DSP_PROGRESS_TALK;
features = 0;
}
#endif
ast_dsp_set_features(i->dsp, features);
ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
if (!ast_strlen_zero(progzone))
ast_dsp_set_call_progress_zone(i->dsp, progzone);
if (i->busydetect && CANBUSYDETECT(i)) {
ast_dsp_set_busy_count(i->dsp, i->busycount);
ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
}
}
}
}
if (state == AST_STATE_RING)
tmp->rings = 1;
tmp->tech_pvt = i;
if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
/* Only FXO signalled stuff can be picked up */
tmp->callgroup = i->callgroup;
tmp->pickupgroup = i->pickupgroup;
}
if (!ast_strlen_zero(i->parkinglot))
ast_string_field_set(tmp, parkinglot, i->parkinglot);
if (!ast_strlen_zero(i->language))
ast_string_field_set(tmp, language, i->language);
if (!i->owner)
i->owner = tmp;
if (!ast_strlen_zero(i->accountcode))
ast_string_field_set(tmp, accountcode, i->accountcode);
if (i->amaflags)
tmp->amaflags = i->amaflags;
i->subs[idx].owner = tmp;
ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
ast_string_field_set(tmp, call_forward, i->call_forward);
/* If we've been told "no ADSI" then enforce it */
if (!i->adsi)
tmp->adsicpe = AST_ADSI_UNAVAILABLE;
if (!ast_strlen_zero(i->exten))
ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
if (!ast_strlen_zero(i->rdnis))
tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
if (!ast_strlen_zero(i->dnid))
tmp->cid.cid_dnid = ast_strdup(i->dnid);
/* Don't use ast_set_callerid() here because it will
* generate a needless NewCallerID event */
#ifdef PRI_ANI
if (!ast_strlen_zero(i->cid_ani))
tmp->cid.cid_ani = ast_strdup(i->cid_ani);
else
tmp->cid.cid_ani = ast_strdup(i->cid_num);
#else
tmp->cid.cid_ani = ast_strdup(i->cid_num);
#endif
tmp->cid.cid_pres = i->callingpres;
tmp->cid.cid_ton = i->cid_ton;
tmp->cid.cid_ani2 = i->cid_ani2;
#if defined(HAVE_PRI) || defined(HAVE_SS7)
tmp->transfercapability = transfercapability;
pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
if (transfercapability & AST_TRANS_CAP_DIGITAL)
i->digital = 1;
/* Assume calls are not idle calls unless we're told differently */
i->isidlecall = 0;
i->alreadyhungup = 0;
#endif
/* clear the fake event in case we posted one before we had ast_channel */
i->fake_event = 0;
/* Assure there is no confmute on this channel */
dahdi_confmute(i, 0);
i->muting = 0;
/* Configure the new channel jb */
ast_jb_configure(tmp, &global_jbconf);
ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
for (v = i->vars ; v ; v = v->next)
pbx_builtin_setvar_helper(tmp, v->name, v->value);
if (startpbx) {
#ifdef HAVE_OPENR2
if (i->mfcr2call) {
pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
}
#endif
if (ast_pbx_start(tmp)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
ast_hangup(tmp);
i->owner = NULL;
return NULL;
}
}
ast_module_ref(ast_module_info->self);
return tmp;
}
| static int dahdi_open | ( | char * | fn | ) | [static] |
Definition at line 2092 of file chan_dahdi.c.
References ast_log(), chan, errno, and LOG_WARNING.
Referenced by alloc_sub(), duplicate_pseudo(), and mkintf().
{
int fd;
int isnum;
int chan = 0;
int bs;
int x;
isnum = 1;
for (x = 0; x < strlen(fn); x++) {
if (!isdigit(fn[x])) {
isnum = 0;
break;
}
}
if (isnum) {
chan = atoi(fn);
if (chan < 1) {
ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
return -1;
}
fn = "/dev/dahdi/channel";
}
fd = open(fn, O_RDWR | O_NONBLOCK);
if (fd < 0) {
ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
return -1;
}
if (chan) {
if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
x = errno;
close(fd);
errno = x;
ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
return -1;
}
}
bs = READ_SIZE;
if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
x = errno;
close(fd);
errno = x;
return -1;
}
return fd;
}
| static void dahdi_pri_error | ( | struct pri * | pri, | |
| char * | s | |||
| ) | [static] |
Definition at line 12381 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), errno, LOG_ERROR, LOG_WARNING, pridebugfdlock, and pris.
Referenced by dahdi_restart(), and load_module().
{
int x, y;
int dchan = -1, span = -1;
int dchancount = 0;
if (pri) {
for (x = 0; x < NUM_SPANS; x++) {
for (y = 0; y < NUM_DCHANS; y++) {
if (pris[x].dchans[y])
dchancount++;
if (pris[x].dchans[y] == pri)
dchan = y;
}
if (dchan >= 0) {
span = x;
break;
}
dchancount = 0;
}
if ((dchancount > 1) && (span > -1))
ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
else
ast_log(LOG_ERROR, "%s", s);
} else
ast_log(LOG_ERROR, "%s", s);
ast_mutex_lock(&pridebugfdlock);
if (pridebugfd >= 0) {
if (write(pridebugfd, s, strlen(s)) < 0) {
ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
}
}
ast_mutex_unlock(&pridebugfdlock);
}
| static void dahdi_pri_message | ( | struct pri * | pri, | |
| char * | s | |||
| ) | [static] |
Definition at line 12340 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), errno, LOG_WARNING, pridebugfdlock, and pris.
Referenced by dahdi_restart(), and load_module().
{
int x, y;
int dchan = -1, span = -1;
int dchancount = 0;
if (pri) {
for (x = 0; x < NUM_SPANS; x++) {
for (y = 0; y < NUM_DCHANS; y++) {
if (pris[x].dchans[y])
dchancount++;
if (pris[x].dchans[y] == pri)
dchan = y;
}
if (dchan >= 0) {
span = x;
break;
}
dchancount = 0;
}
if (dchancount > 1 && (span > -1))
ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
else
ast_verbose("%s", s);
} else
ast_verbose("%s", s);
ast_mutex_lock(&pridebugfdlock);
if (pridebugfd >= 0) {
if (write(pridebugfd, s, strlen(s)) < 0) {
ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
}
}
ast_mutex_unlock(&pridebugfdlock);
}
Definition at line 1546 of file chan_dahdi.c.
References ast_channel_trylock, ast_channel_unlock, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_ss7::lock, dahdi_pri::lock, dahdi_pvt::owner, dahdi_pri::pri, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_PRI, SIG_SS7, and dahdi_ss7::ss7.
Referenced by action_dahdidialoffhook(), pri_dchannel(), and ss7_linkset().
{
#ifdef HAVE_PRI
struct dahdi_pri *pri = (struct dahdi_pri*) data;
#endif
#ifdef HAVE_SS7
struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
#endif
/* We must unlock the PRI to avoid the possibility of a deadlock */
#if defined(HAVE_PRI) || defined(HAVE_SS7)
if (data) {
switch (p->sig) {
#ifdef HAVE_PRI
case SIG_BRI:
case SIG_BRI_PTMP:
case SIG_PRI:
ast_mutex_unlock(&pri->lock);
break;
#endif
#ifdef HAVE_SS7
case SIG_SS7:
ast_mutex_unlock(&ss7->lock);
break;
#endif
default:
break;
}
}
#endif
for (;;) {
if (p->owner) {
if (ast_channel_trylock(p->owner)) {
DEADLOCK_AVOIDANCE(&p->lock);
} else {
ast_queue_frame(p->owner, f);
ast_channel_unlock(p->owner);
break;
}
} else
break;
}
#if defined(HAVE_PRI) || defined(HAVE_SS7)
if (data) {
switch (p->sig) {
#ifdef HAVE_PRI
case SIG_BRI:
case SIG_BRI_PTMP:
case SIG_PRI:
ast_mutex_lock(&pri->lock);
break;
#endif
#ifdef HAVE_SS7
case SIG_SS7:
ast_mutex_lock(&ss7->lock);
break;
#endif
default:
break;
}
}
#endif
}
| static struct ast_frame * dahdi_read | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 6803 of file chan_dahdi.c.
References __dahdi_exception(), ast_channel::_state, ast_clear_flag, AST_CONTROL_BUSY, ast_debug, ast_dsp_get_tcount(), ast_dsp_get_tstate(), ast_dsp_process(), ast_dsp_set_features(), 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_VOICE, AST_FRIENDLY_OFFSET, ast_getformatname(), ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_null_frame, ast_set_callerid(), ast_set_flag, ast_setstate(), AST_STATE_DIALING, AST_STATE_RINGING, AST_STATE_UP, ast_strlen_zero(), ast_tv(), ast_tvdiff_ms(), ast_tvnow(), 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, ast_channel::cid, ast_callerid::cid_tns, 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::dop, dahdi_pvt::dsp, dahdi_pvt::dsp_features, DSP_TONE_STATE_DIALTONE, DSP_TONE_STATE_RINGING, errno, dahdi_subchannel::f, dahdi_pvt::fake_event, dahdi_pvt::firstradio, ast_frame::frametype, dahdi_pvt::ignoredtmf, dahdi_pvt::inalarm, dahdi_subchannel::inthreeway, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, 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(), ast_channel::tech_pvt, dahdi_pvt::waitfordialtone, and dahdi_pvt::waitingfordt.
{
struct dahdi_pvt *p = ast->tech_pvt;
int res;
int idx;
void *readbuf;
struct ast_frame *f;
while (ast_mutex_trylock(&p->lock)) {
CHANNEL_DEADLOCK_AVOIDANCE(ast);
}
idx = dahdi_get_index(ast, p, 0);
/* Hang up if we don't really exist */
if (idx < 0) {
ast_log(LOG_WARNING, "We don't exist?\n");
ast_mutex_unlock(&p->lock);
return NULL;
}
if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
ast_mutex_unlock(&p->lock);
return NULL;
}
p->subs[idx].f.frametype = AST_FRAME_NULL;
p->subs[idx].f.datalen = 0;
p->subs[idx].f.samples = 0;
p->subs[idx].f.mallocd = 0;
p->subs[idx].f.offset = 0;
p->subs[idx].f.subclass = 0;
p->subs[idx].f.delivery = ast_tv(0,0);
p->subs[idx].f.src = "dahdi_read";
p->subs[idx].f.data.ptr = NULL;
/* make sure it sends initial key state as first frame */
if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
{
struct dahdi_params ps;
memset(&ps, 0, sizeof(ps));
ps.channo = p->channel;
if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
ast_mutex_unlock(&p->lock);
return NULL;
}
p->firstradio = 1;
p->subs[idx].f.frametype = AST_FRAME_CONTROL;
if (ps.rxisoffhook)
{
p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
}
else
{
p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
}
ast_mutex_unlock(&p->lock);
return &p->subs[idx].f;
}
if (p->ringt == 1) {
ast_mutex_unlock(&p->lock);
return NULL;
}
else if (p->ringt > 0)
p->ringt--;
#ifdef HAVE_OPENR2
if (p->mfcr2) {
openr2_chan_process_event(p->r2chan);
}
#endif
if (p->subs[idx].needringing) {
/* Send ringing frame if requested */
p->subs[idx].needringing = 0;
p->subs[idx].f.frametype = AST_FRAME_CONTROL;
p->subs[idx].f.subclass = AST_CONTROL_RINGING;
ast_setstate(ast, AST_STATE_RINGING);
ast_mutex_unlock(&p->lock);
return &p->subs[idx].f;
}
if (p->subs[idx].needbusy) {
/* Send busy frame if requested */
p->subs[idx].needbusy = 0;
p->subs[idx].f.frametype = AST_FRAME_CONTROL;
p->subs[idx].f.subclass = AST_CONTROL_BUSY;
ast_mutex_unlock(&p->lock);
return &p->subs[idx].f;
}
if (p->subs[idx].needcongestion) {
/* Send congestion frame if requested */
p->subs[idx].needcongestion = 0;
p->subs[idx].f.frametype = AST_FRAME_CONTROL;
p->subs[idx].f.subclass = AST_CONTROL_CONGESTION;
ast_mutex_unlock(&p->lock);
return &p->subs[idx].f;
}
if (p->subs[idx].needcallerid && !ast->cid.cid_tns) {
ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
S_OR(p->lastcid_name, NULL),
S_OR(p->lastcid_num, NULL)
);
p->subs[idx].needcallerid = 0;
}
if (p->subs[idx].needanswer) {
/* Send answer frame if requested */
p->subs[idx].needanswer = 0;
p->subs[idx].f.frametype = AST_FRAME_CONTROL;
p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
ast_mutex_unlock(&p->lock);
return &p->subs[idx].f;
}
#ifdef HAVE_OPENR2
if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
/* openr2 took care of reading and handling any event
(needanswer, needbusy etc), if we continue we will read()
twice, lets just return a null frame. This should only
happen when openr2 is dialing out */
ast_mutex_unlock(&p->lock);
return &ast_null_frame;
}
#endif
if (p->subs[idx].needflash) {
/* Send answer frame if requested */
p->subs[idx].needflash = 0;
p->subs[idx].f.frametype = AST_FRAME_CONTROL;
p->subs[idx].f.subclass = AST_CONTROL_FLASH;
ast_mutex_unlock(&p->lock);
return &p->subs[idx].f;
}
if (p->subs[idx].needhold) {
/* Send answer frame if requested */
p->subs[idx].needhold = 0;
p->subs[idx].f.frametype = AST_FRAME_CONTROL;
p->subs[idx].f.subclass = AST_CONTROL_HOLD;
ast_mutex_unlock(&p->lock);
ast_debug(1, "Sending hold on '%s'\n", ast->name);
return &p->subs[idx].f;
}
if (p->subs[idx].needunhold) {
/* Send answer frame if requested */
p->subs[idx].needunhold = 0;
p->subs[idx].f.frametype = AST_FRAME_CONTROL;
p->subs[idx].f.subclass = AST_CONTROL_UNHOLD;
ast_mutex_unlock(&p->lock);
ast_debug(1, "Sending unhold on '%s'\n", ast->name);
return &p->subs[idx].f;
}
if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
if (!p->subs[idx].linear) {
p->subs[idx].linear = 1;
res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
if (res)
ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
}
} else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
(ast->rawreadformat == AST_FORMAT_ALAW)) {
if (p->subs[idx].linear) {
p->subs[idx].linear = 0;
res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
if (res)
ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
}
} else {
ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
ast_mutex_unlock(&p->lock);
return NULL;
}
readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
CHECK_BLOCKING(ast);
res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
ast_clear_flag(ast, AST_FLAG_BLOCKING);
/* Check for hangup */
if (res < 0) {
f = NULL;
if (res == -1) {
if (errno == EAGAIN) {
/* Return "NULL" frame if there is nobody there */
ast_mutex_unlock(&p->lock);
return &p->subs[idx].f;
} else if (errno == ELAST) {
f = __dahdi_exception(ast);
} else
ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
}
ast_mutex_unlock(&p->lock);
return f;
}
if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
f = __dahdi_exception(ast);
ast_mutex_unlock(&p->lock);
return f;
}
if (p->tdd) { /* if in TDD mode, see if we receive that */
int c;
c = tdd_feed(p->tdd,readbuf,READ_SIZE);
if (c < 0) {
ast_debug(1,"tdd_feed failed\n");
ast_mutex_unlock(&p->lock);
return NULL;
}
if (c) { /* if a char to return */
p->subs[idx].f.subclass = 0;
p->subs[idx].f.frametype = AST_FRAME_TEXT;
p->subs[idx].f.mallocd = 0;
p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
p->subs[idx].f.datalen = 1;
*((char *) p->subs[idx].f.data.ptr) = c;
ast_mutex_unlock(&p->lock);
return &p->subs[idx].f;
}
}
/* Ensure the CW timer decrements only on a single subchannel */
if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
p->callwaitingrepeat--;
}
if (p->cidcwexpire)
p->cidcwexpire--;
/* Repeat callwaiting */
if (p->callwaitingrepeat == 1) {
p->callwaitrings++;
dahdi_callwait(ast);
}
/* Expire CID/CW */
if (p->cidcwexpire == 1) {
ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
restore_conference(p);
}
if (p->subs[idx].linear) {
p->subs[idx].f.datalen = READ_SIZE * 2;
} else
p->subs[idx].f.datalen = READ_SIZE;
/* Handle CallerID Transmission */
if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
send_callerid(p);
}
p->subs[idx].f.frametype = AST_FRAME_VOICE;
p->subs[idx].f.subclass = ast->rawreadformat;
p->subs[idx].f.samples = READ_SIZE;
p->subs[idx].f.mallocd = 0;
p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
#if 0
ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
#endif
if (p->dialing || /* Transmitting something */
(idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
) {
/* Whoops, we're still dialing, or in a state where we shouldn't transmit....
don't send anything */
p->subs[idx].f.frametype = AST_FRAME_NULL;
p->subs[idx].f.subclass = 0;
p->subs[idx].f.samples = 0;
p->subs[idx].f.mallocd = 0;
p->subs[idx].f.offset = 0;
p->subs[idx].f.data.ptr = NULL;
p->subs[idx].f.datalen= 0;
}
if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
/* Perform busy detection etc on the dahdi line */
int mute;
f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
/* Check if DSP code thinks we should be muting this frame and mute the conference if so */
mute = ast_dsp_was_muted(p->dsp);
if (p->muting != mute) {
p->muting = mute;
dahdi_confmute(p, mute);
}
if (f) {
if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
/* Treat this as a "hangup" instead of a "busy" on the assumption that
a busy */
f = NULL;
}
} else if (f->frametype == AST_FRAME_DTMF) {
#ifdef HAVE_PRI
if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri &&
((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
(p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
/* Don't accept in-band DTMF when in overlap dial mode */
f->frametype = AST_FRAME_NULL;
f->subclass = 0;
}
#endif
/* DSP clears us of being pulse */
p->pulsedial = 0;
} else if (p->waitingfordt.tv_sec) {
if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
p->waitingfordt.tv_sec = 0;
ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
f=NULL;
} else if (f->frametype == AST_FRAME_VOICE) {
f->frametype = AST_FRAME_NULL;
f->subclass = 0;
if ((ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_DIALTONE || ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_RINGING) && ast_dsp_get_tcount(p->dsp) > 9) {
p->waitingfordt.tv_sec = 0;
p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
ast_dsp_set_features(p->dsp, p->dsp_features);
ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
p->dop.dialstr[0] = '\0';
ast_mutex_unlock(&p->lock);
return NULL;
} else {
ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
p->dialing = 1;
p->dop.dialstr[0] = '\0';
p->dop.op = DAHDI_DIAL_OP_REPLACE;
ast_setstate(ast, AST_STATE_DIALING);
}
}
}
}
}
}
} else
f = &p->subs[idx].f;
if (f && (f->frametype == AST_FRAME_DTMF))
dahdi_handle_dtmfup(ast, idx, &f);
/* If we have a fake_event, trigger exception to handle it */
if (p->fake_event)
ast_set_flag(ast, AST_FLAG_EXCEPTION);
ast_mutex_unlock(&p->lock);
return f;
}
| static struct ast_channel * dahdi_request | ( | const char * | type, | |
| int | format, | |||
| void * | data, | |||
| int * | cause | |||
| ) | [static, read] |
Definition at line 10959 of file chan_dahdi.c.
References alloc_sub(), ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RESERVED, ast_strdupa, ast_verbose(), available(), dahdi_pvt::bearer, ast_channel::cdrflags, CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::confirmanswer, dahdi_pri::crvend, dahdi_pri::crvs, dahdi_new(), dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::distinctivering, duplicate_pseudo(), iflist, iflock, dahdi_pvt::inalarm, dahdi_pvt::lock, dahdi_pri::lock, lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_channel::name, dahdi_pvt::next, 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(), dahdi_pvt::sig, SIG_FXSKS, dahdi_pri::span, strsep(), SUB_CALLWAIT, SUB_REAL, dahdi_pvt::subs, and ast_channel::transfercapability.
Referenced by pri_dchannel().
{
ast_group_t groupmatch = 0;
int channelmatch = -1;
int roundrobin = 0;
int callwait = 0;
int busy = 0;
struct dahdi_pvt *p;
struct ast_channel *tmp = NULL;
char *dest=NULL;
int x;
char *s;
char opt=0;
int res=0, y=0;
int backwards = 0;
#ifdef HAVE_PRI
int crv;
int bearer = -1;
int trunkgroup;
struct dahdi_pri *pri=NULL;
#endif
struct dahdi_pvt *exitpvt, *start, *end;
ast_mutex_t *lock;
int channelmatched = 0;
int groupmatched = 0;
/*
* data is ---v
* Dial(DAHDI/pseudo[/extension])
* Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension])
* Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension])
* Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension])
*
* g - channel group allocation search forward
* G - channel group allocation search backward
* r - channel group allocation round robin search forward
* R - channel group allocation round robin search backward
*
* c - Wait for DTMF digit to confirm answer
* r<cadance#> - Set distintive ring cadance number
* d - Force bearer capability for ISDN/SS7 call to digital.
*/
/* Assume we're locking the iflock */
lock = &iflock;
start = iflist;
end = ifend;
if (data) {
dest = ast_strdupa((char *)data);
} else {
ast_log(LOG_WARNING, "Channel requested with no data\n");
return NULL;
}
if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
/* Retrieve the group number */
char *stringp;
stringp = dest + 1;
s = strsep(&stringp, "/");
if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
return NULL;
}
groupmatch = ((ast_group_t) 1 << x);
if (toupper(dest[0]) == 'G') {
if (dest[0] == 'G') {
backwards = 1;
p = ifend;
} else
p = iflist;
} else {
if (dest[0] == 'R') {
backwards = 1;
p = round_robin[x]?round_robin[x]->prev:ifend;
if (!p)
p = ifend;
} else {
p = round_robin[x]?round_robin[x]->next:iflist;
if (!p)
p = iflist;
}
roundrobin = 1;
}
} else {
char *stringp;
stringp = dest;
s = strsep(&stringp, "/");
p = iflist;
if (!strcasecmp(s, "pseudo")) {
/* Special case for pseudo */
x = CHAN_PSEUDO;
channelmatch = x;
}
#ifdef HAVE_PRI
else if ((res = sscanf(s, "%30d:%30d%1c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
if ((trunkgroup < 1) || (crv < 1)) {
ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
return NULL;
}
res--;
for (x = 0; x < NUM_SPANS; x++) {
if (pris[x].trunkgroup == trunkgroup) {
pri = pris + x;
lock = &pri->lock;
start = pri->crvs;
end = pri->crvend;
break;
}
}
if (!pri) {
ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
return NULL;
}
channelmatch = crv;
p = pris[x].crvs;
}
#endif
else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
return NULL;
} else {
channelmatch = x;
}
}
/* Search for an unowned channel */
ast_mutex_lock(lock);
exitpvt = p;
while (p && !tmp) {
if (roundrobin)
round_robin[x] = p;
#if 0
ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
#endif
if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
ast_debug(1, "Using channel %d\n", p->channel);
if (p->inalarm)
goto next;
callwait = (p->owner != NULL);
#ifdef HAVE_PRI
if (pri && (p->subs[SUB_REAL].dfd < 0)) {
if (p->sig != SIG_FXSKS) {
/* Gotta find an actual channel to use for this
CRV if this isn't a callwait */
bearer = pri_find_empty_chan(pri, 0);
if (bearer < 0) {
ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
p = NULL;
break;
}
pri_assign_bearer(p, pri, pri->pvts[bearer]);
} else {
if (alloc_sub(p, 0)) {
ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
p = NULL;
break;
} else
ast_debug(1, "Allocated placeholder pseudo channel\n");
p->pri = pri;
}
}
#endif
#ifdef HAVE_OPENR2
if (p->mfcr2) {
ast_mutex_lock(&p->lock);
if (p->mfcr2call) {
ast_mutex_unlock(&p->lock);
ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
goto next;
}
p->mfcr2call = 1;
ast_mutex_unlock(&p->lock);
}
#endif
if (p->channel == CHAN_PSEUDO) {
p = duplicate_pseudo(p);
if (!p) {
break;
}
}
if (p->owner) {
if (alloc_sub(p, SUB_CALLWAIT)) {
p = NULL;
break;
}
}
p->outgoing = 1;
tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
if (!tmp) {
p->outgoing = 0;
}
#ifdef HAVE_PRI
if (p->bearer) {
/* Log owner to bearer channel, too */
p->bearer->owner = tmp;
}
#endif
/* Make special notes */
if (res > 1) {
if (opt == 'c') {
/* Confirm answer */
p->confirmanswer = 1;
} else if (opt == 'r') {
/* Distinctive ring */
if (res < 3)
ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
else
p->distinctivering = y;
} else if (opt == 'd') {
/* If this is an ISDN call, make it digital */
p->digital = 1;
if (tmp)
tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
} else {
ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
}
}
/* Note if the call is a call waiting call */
if (tmp && callwait)
tmp->cdrflags |= AST_CDR_CALLWAIT;
break;
}
next:
if (backwards) {
p = p->prev;
if (!p)
p = end;
} else {
p = p->next;
if (!p)
p = start;
}
/* stop when you roll to the one that we started from */
if (p == exitpvt)
break;
}
ast_mutex_unlock(lock);
restart_monitor();
if (callwait)
*cause = AST_CAUSE_BUSY;
else if (!tmp) {
if (channelmatched) {
if (busy)
*cause = AST_CAUSE_BUSY;
} else if (groupmatched) {
*cause = AST_CAUSE_CONGESTION;
}
}
return tmp;
}
| static int dahdi_restart | ( | void | ) | [static] |
Definition at line 14463 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_close_ss7_fd(), dahdi_pri_error(), dahdi_pri_message(), dahdi_softhangup_all(), dahdi_ss7_error(), dahdi_ss7_message(), destroy_all_channels(), dahdi_subchannel::dfd, iflist, linksets, lock, LOG_WARNING, dahdi_ss7::master, dahdi_pri::master, master, monlock, dahdi_pvt::next, dahdi_pri::offset, dahdi_pvt::owner, pris, restart_lock, setup_dahdi(), ss_thread_lock, SUB_REAL, and dahdi_pvt::subs.
Referenced by action_dahdirestart(), and dahdi_restart_cmd().
{
#if defined(HAVE_PRI) || defined(HAVE_SS7)
int i, j;
#endif
int cancel_code;
struct dahdi_pvt *p;
ast_mutex_lock(&restart_lock);
ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
dahdi_softhangup_all();
ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
#ifdef HAVE_OPENR2
dahdi_r2_destroy_links();
#endif
#if defined(HAVE_PRI)
for (i = 0; i < NUM_SPANS; i++) {
if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
cancel_code = pthread_cancel(pris[i].master);
pthread_kill(pris[i].master, SIGURG);
ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
pthread_join(pris[i].master, NULL);
ast_debug(4, "Joined thread of span %d\n", i);
}
}
#endif
#if defined(HAVE_SS7)
for (i = 0; i < NUM_SPANS; i++) {
if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
cancel_code = pthread_cancel(linksets[i].master);
pthread_kill(linksets[i].master, SIGURG);
ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
pthread_join(linksets[i].master, NULL);
ast_debug(4, "Joined thread of span %d\n", i);
}
}
#endif
ast_mutex_lock(&monlock);
if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
cancel_code = pthread_cancel(monitor_thread);
pthread_kill(monitor_thread, SIGURG);
ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
pthread_join(monitor_thread, NULL);
ast_debug(4, "Joined monitor thread\n");
}
monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
ast_mutex_lock(&ss_thread_lock);
while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
int x = DAHDI_FLASH;
ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
for (p = iflist; p; p = p->next) {
if (p->owner)
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 */
}
ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
}
/* ensure any created channels before monitor threads were stopped are hungup */
dahdi_softhangup_all();
ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
destroy_all_channels();
ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
ast_mutex_unlock(&monlock);
#ifdef HAVE_PRI
for (i = 0; i < NUM_SPANS; i++) {
for (j = 0; j < NUM_DCHANS; j++)
dahdi_close_pri_fd(&(pris[i]), j);
}
memset(pris, 0, sizeof(pris));
for (i = 0; i < NUM_SPANS; i++) {
ast_mutex_init(&pris[i].lock);
pris[i].offset = -1;
pris[i].master = AST_PTHREADT_NULL;
for (j = 0; j < NUM_DCHANS; j++)
pris[i].fds[j] = -1;
}
pri_set_error(dahdi_pri_error);
pri_set_message(dahdi_pri_message);
#endif
#ifdef HAVE_SS7
for (i = 0; i < NUM_SPANS; i++) {
for (j = 0; j < NUM_DCHANS; j++)
dahdi_close_ss7_fd(&(linksets[i]), j);
}
memset(linksets, 0, sizeof(linksets));
for (i = 0; i < NUM_SPANS; i++) {
ast_mutex_init(&linksets[i].lock);
linksets[i].master = AST_PTHREADT_NULL;
for (j = 0; j < NUM_DCHANS; j++)
linksets[i].fds[j] = -1;
}
ss7_set_error(dahdi_ss7_error);
ss7_set_message(dahdi_ss7_message);
#endif
if (setup_dahdi(2) != 0) {
ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
ast_mutex_unlock(&ss_thread_lock);
return 1;
}
ast_mutex_unlock(&ss_thread_lock);
ast_mutex_unlock(&restart_lock);
return 0;
}
| static char* dahdi_restart_cmd | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 14577 of file chan_dahdi.c.
References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, dahdi_restart(), and ast_cli_entry::usage.
{
switch (cmd) {
case CLI_INIT:
e->command = "dahdi restart";
e->usage =
"Usage: dahdi restart\n"
" Restarts the DAHDI channels: destroys them all and then\n"
" re-reads them from chan_dahdi.conf.\n"
" Note that this will STOP any running CALL on DAHDI channels.\n"
"";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 2)
return CLI_SHOWUSAGE;
if (dahdi_restart() != 0)
return CLI_FAILURE;
return CLI_SUCCESS;
}
| static int dahdi_ring_phone | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5555 of file chan_dahdi.c.
References ast_log(), dahdi_subchannel::dfd, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), and dahdi_handle_event().
{
int x;
int res;
/* Make sure our transmit state is on hook */
x = 0;
x = DAHDI_ONHOOK;
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
do {
x = DAHDI_RING;
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
if (res) {
switch (errno) {
case EBUSY:
case EINTR:
/* Wait just in case */
usleep(10000);
continue;
case EINPROGRESS:
res = 0;
break;
default:
ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
res = 0;
}
}
} while (res);
return res;
}
| static int dahdi_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 3973 of file chan_dahdi.c.
References ast_debug, ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), dahdi_pvt::call, dahdi_pvt::lock, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), and ast_channel::tech_pvt.
Referenced by load_module().
{
/* Data will be our digit string */
struct dahdi_pvt *p;
char *digits = (char *) data;
if (ast_strlen_zero(digits)) {
ast_debug(1, "No digit string sent to application!\n");
return -1;
}
p = (struct dahdi_pvt *)chan->tech_pvt;
if (!p) {
ast_debug(1, "Unable to find technology private\n");
return -1;
}
ast_mutex_lock(&p->lock);
if (!p->pri || !p->call) {
ast_debug(1, "Unable to find pri or call on channel!\n");
ast_mutex_unlock(&p->lock);
return -1;
}
if (!pri_grab(p, p->pri)) {
pri_keypad_facility(p->pri->pri, p->call, digits);
pri_rel(p->pri);
} else {
ast_debug(1, "Unable to grab pri to send keypad facility!\n");
ast_mutex_unlock(&p->lock);
return -1;
}
ast_mutex_unlock(&p->lock);
return 0;
}
| static int dahdi_sendtext | ( | struct ast_channel * | c, | |
| const char * | text | |||
| ) | [static] |
Definition at line 17481 of file chan_dahdi.c.
References ASCII_BYTES_PER_CHAR, ast_check_hangup(), ast_debug, ast_free, AST_LAW, ast_log(), ast_malloc, buf, dahdi_pvt::channel, dahdi_get_index(), dahdi_subchannel::dfd, END_SILENCE_LEN, errno, HEADER_LEN, LOG_ERROR, LOG_WARNING, dahdi_pvt::mate, PUT_CLID, READ_SIZE, dahdi_pvt::subs, dahdi_pvt::tdd, TDD_BYTES_PER_CHAR, tdd_generate(), and ast_channel::tech_pvt.
{
#define END_SILENCE_LEN 400
#define HEADER_MS 50
#define TRAILER_MS 5
#define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
#define ASCII_BYTES_PER_CHAR 80
unsigned char *buf,*mybuf;
struct dahdi_pvt *p = c->tech_pvt;
struct pollfd fds[1];
int size,res,fd,len,x;
int bytes=0;
/* Initial carrier (imaginary) */
float cr = 1.0;
float ci = 0.0;
float scont = 0.0;
int idx;
idx = dahdi_get_index(c, p, 0);
if (idx < 0) {
ast_log(LOG_WARNING, "Huh? I don't exist?\n");
return -1;
}
if (!text[0]) return(0); /* if nothing to send, dont */
if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */
if (p->mate)
buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
else
buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
if (!buf)
return -1;
mybuf = buf;
if (p->mate) {
int codec = AST_LAW(p);
for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */
PUT_CLID_MARKMS;
}
/* Put actual message */
for (x = 0; text[x]; x++) {
PUT_CLID(text[x]);
}
for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */
PUT_CLID_MARKMS;
}
len = bytes;
buf = mybuf;
} else {
len = tdd_generate(p->tdd, buf, text);
if (len < 1) {
ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
ast_free(mybuf);
return -1;
}
}
memset(buf + len, 0x7f, END_SILENCE_LEN);
len += END_SILENCE_LEN;
fd = p->subs[idx].dfd;
while (len) {
if (ast_check_hangup(c)) {
ast_free(mybuf);
return -1;
}
size = len;
if (size > READ_SIZE)
size = READ_SIZE;
fds[0].fd = fd;
fds[0].events = POLLOUT | POLLPRI;
fds[0].revents = 0;
res = poll(fds, 1, -1);
if (!res) {
ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
continue;
}
/* if got exception */
if (fds[0].revents & POLLPRI) {
ast_free(mybuf);
return -1;
}
if (!(fds[0].revents & POLLOUT)) {
ast_debug(1, "write fd not ready on channel %d\n", p->channel);
continue;
}
res = write(fd, buf, size);
if (res != size) {
if (res == -1) {
ast_free(mybuf);
return -1;
}
ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
break;
}
len -= size;
buf += size;
}
ast_free(mybuf);
return(0);
}
| static char* dahdi_set_dnd | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15238 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_GENERATE, CLI_INIT, ast_cli_entry::command, dahdi_dnd(), ast_cli_args::fd, iflist, iflock, dahdi_pvt::next, and ast_cli_entry::usage.
{
int channel;
int on;
struct dahdi_pvt *dahdi_chan = NULL;
switch (cmd) {
case CLI_INIT:
e->command = "dahdi set dnd";
e->usage =
"Usage: dahdi set dnd <chan#> <on|off>\n"
" Sets/resets DND (Do Not Disturb) mode on a channel.\n"
" Changes take effect immediately.\n"
" <chan num> is the channel number\n"
" <on|off> Enable or disable DND mode?\n"
;
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 5)
return CLI_SHOWUSAGE;
if ((channel = atoi(a->argv[3])) <= 0) {
ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
return CLI_SHOWUSAGE;
}
if (ast_true(a->argv[4]))
on = 1;
else if (ast_false(a->argv[4]))
on = 0;
else {
ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
return CLI_SHOWUSAGE;
}
ast_mutex_lock(&iflock);
for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
if (dahdi_chan->channel != channel)
continue;
/* Found the channel. Actually set it */
dahdi_dnd(dahdi_chan, on);
break;
}
ast_mutex_unlock(&iflock);
if (!dahdi_chan) {
ast_cli(a->fd, "Unable to find given channel %d\n", channel);
return CLI_FAILURE;
}
return CLI_SUCCESS;
}
| static int dahdi_set_hook | ( | int | fd, | |
| int | hs | |||
| ) | [inline, static] |
Definition at line 2865 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(), mkintf(), mwi_send_process_buffer(), mwi_send_process_event(), and ss_thread().
{
int x, res;
x = hs;
res = ioctl(fd, DAHDI_HOOK, &x);
if (res < 0) {
if (errno == EINPROGRESS)
return 0;
ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
/* will expectedly fail if phone is off hook during operation, such as during a restart */
}
return res;
}
| static char* dahdi_set_hwgain | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15095 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_GENERATE, CLI_INIT, ast_cli_entry::command, dahdi_subchannel::dfd, errno, ast_cli_args::fd, iflist, iflock, dahdi_pvt::next, SUB_REAL, dahdi_pvt::subs, and ast_cli_entry::usage.
{
int channel;
int gain;
int tx;
struct dahdi_hwgain hwgain;
struct dahdi_pvt *tmp = NULL;
switch (cmd) {
case CLI_INIT:
e->command = "dahdi set hwgain";
e->usage =
"Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
" Sets the hardware gain on a a given channel, overriding the\n"
" value provided at module loadtime, whether the channel is in\n"
" use or not. Changes take effect immediately.\n"
" <rx|tx> which direction do you want to change (relative to our module)\n"
" <chan num> is the channel number relative to the device\n"
" <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 6)
return CLI_SHOWUSAGE;
if (!strcasecmp("rx", a->argv[3]))
tx = 0; /* rx */
else if (!strcasecmp("tx", a->argv[3]))
tx = 1; /* tx */
else
return CLI_SHOWUSAGE;
channel = atoi(a->argv[4]);
gain = atof(a->argv[5])*10.0;
ast_mutex_lock(&iflock);
for (tmp = iflist; tmp; tmp = tmp->next) {
if (tmp->channel != channel)
continue;
if (tmp->subs[SUB_REAL].dfd == -1)
break;
hwgain.newgain = gain;
hwgain.tx = tx;
if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
ast_mutex_unlock(&iflock);
return CLI_FAILURE;
}
ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
break;
}
ast_mutex_unlock(&iflock);
if (tmp)
return CLI_SUCCESS;
ast_cli(a->fd, "Unable to find given channel %d\n", channel);
return CLI_FAILURE;
}
| static char* dahdi_set_swgain | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15164 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_GENERATE, CLI_INIT, 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(), SUB_REAL, dahdi_pvt::subs, and ast_cli_entry::usage.
{
int channel;
float gain;
int tx;
int res;
ast_mutex_t *lock;
struct dahdi_pvt *tmp = NULL;
switch (cmd) {
case CLI_INIT:
e->command = "dahdi set swgain";
e->usage =
"Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
" Sets the software gain on a a given channel, overriding the\n"
" value provided at module loadtime, whether the channel is in\n"
" use or not. Changes take effect immediately.\n"
" <rx|tx> which direction do you want to change (relative to our module)\n"
" <chan num> is the channel number relative to the device\n"
" <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
lock = &iflock;
if (a->argc != 6)
return CLI_SHOWUSAGE;
if (!strcasecmp("rx", a->argv[3]))
tx = 0; /* rx */
else if (!strcasecmp("tx", a->argv[3]))
tx = 1; /* tx */
else
return CLI_SHOWUSAGE;
channel = atoi(a->argv[4]);
gain = atof(a->argv[5]);
ast_mutex_lock(lock);
for (tmp = iflist; tmp; tmp = tmp->next) {
if (tmp->channel != channel)
continue;
if (tmp->subs[SUB_REAL].dfd == -1)
break;
if (tx)
res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
else
res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
if (res) {
ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
ast_mutex_unlock(lock);
return CLI_FAILURE;
}
ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
tx ? "tx" : "rx", gain, channel);
break;
}
ast_mutex_unlock(lock);
if (tmp)
return CLI_SUCCESS;
ast_cli(a->fd, "Unable to find given channel %d\n", channel);
return CLI_FAILURE;
}
| static int dahdi_setlaw | ( | int | dfd, | |
| int | law | |||
| ) | [static] |
Definition at line 11215 of file chan_dahdi.c.
Referenced by pri_dchannel(), and ss7_start_call().
{
return ioctl(dfd, DAHDI_SETLAW, &law);
}
| static int dahdi_setlinear | ( | int | dfd, | |
| int | linear | |||
| ) | [static] |
Definition at line 2167 of file chan_dahdi.c.
Referenced by dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_write(), send_callerid(), and ss_thread().
{
int res;
res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
if (res)
return res;
return 0;
}
| static int dahdi_setoption | ( | struct ast_channel * | chan, | |
| int | option, | |||
| void * | data, | |||
| int | datalen | |||
| ) | [static] |
Definition at line 4855 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, 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, LOG_NOTICE, 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, ast_channel::tech_pvt, dahdi_pvt::txgain, and ast_channel_tech::type.
{
char *cp;
signed char *scp;
int x;
int idx;
struct dahdi_pvt *p = chan->tech_pvt, *pp;
struct oprmode *oprmode;
/* all supported options require data */
if (!data || (datalen < 1)) {
errno = EINVAL;
return -1;
}
switch (option) {
case AST_OPTION_TXGAIN:
scp = (signed char *) data;
idx = dahdi_get_index(chan, p, 0);
if (idx < 0) {
ast_log(LOG_WARNING, "No index in TXGAIN?\n");
return -1;
}
ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law);
case AST_OPTION_RXGAIN:
scp = (signed char *) data;
idx = dahdi_get_index(chan, p, 0);
if (idx < 0) {
ast_log(LOG_WARNING, "No index in RXGAIN?\n");
return -1;
}
ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law);
case AST_OPTION_TONE_VERIFY:
if (!p->dsp)
break;
cp = (char *) data;
switch (*cp) {
case 1:
ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */
break;
case 2:
ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */
break;
default:
ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */
break;
}
break;
case AST_OPTION_TDD:
/* turn on or off TDD */
cp = (char *) data;
p->mate = 0;
if (!*cp) { /* turn it off */
ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
if (p->tdd)
tdd_free(p->tdd);
p->tdd = 0;
break;
}
ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
(*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
dahdi_disable_ec(p);
/* otherwise, turn it on */
if (!p->didtdd) { /* if havent done it yet */
unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
unsigned char *buf;
int size, res, fd, len;
struct pollfd fds[1];
buf = mybuf;
memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */
len = 40000;
idx = dahdi_get_index(chan, p, 0);
if (idx < 0) {
ast_log(LOG_WARNING, "No index in TDD?\n");
return -1;
}
fd = p->subs[idx].dfd;
while (len) {
if (ast_check_hangup(chan))
return -1;
size = len;
if (size > READ_SIZE)
size = READ_SIZE;
fds[0].fd = fd;
fds[0].events = POLLPRI | POLLOUT;
fds[0].revents = 0;
res = poll(fds, 1, -1);
if (!res) {
ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
continue;
}
/* if got exception */
if (fds[0].revents & POLLPRI)
return -1;
if (!(fds[0].revents & POLLOUT)) {
ast_debug(1, "write fd not ready on channel %d\n", p->channel);
continue;
}
res = write(fd, buf, size);
if (res != size) {
if (res == -1) return -1;
ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
break;
}
len -= size;
buf += size;
}
p->didtdd = 1; /* set to have done it now */
}
if (*cp == 2) { /* Mate mode */
if (p->tdd)
tdd_free(p->tdd);
p->tdd = 0;
p->mate = 1;
break;
}
if (!p->tdd) { /* if we dont have one yet */
p->tdd = tdd_new(); /* allocate one */
}
break;
case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */
if (!p->dsp)
break;
cp = (char *) data;
ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
*cp ? "ON" : "OFF", (int) *cp, chan->name);
ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
break;
case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */
cp = (char *) data;
if (!*cp) {
ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
x = 0;
dahdi_disable_ec(p);
} else {
ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
x = 1;
}
if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
break;
case AST_OPTION_OPRMODE: /* Operator services mode */
oprmode = (struct oprmode *) data;
/* We don't support operator mode across technologies */
if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
chan->tech->type, oprmode->peer->tech->type);
errno = EINVAL;
return -1;
}
pp = oprmode->peer->tech_pvt;
p->oprmode = pp->oprmode = 0;
/* setup peers */
p->oprpeer = pp;
pp->oprpeer = p;
/* setup modes, if any */
if (oprmode->mode)
{
pp->oprmode = oprmode->mode;
p->oprmode = -oprmode->mode;
}
ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
oprmode->mode, chan->name,oprmode->peer->name);
break;
case AST_OPTION_ECHOCAN:
cp = (char *) data;
if (*cp) {
ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
dahdi_enable_ec(p);
} else {
ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
dahdi_disable_ec(p);
}
break;
}
errno = 0;
return 0;
}
| static char* dahdi_show_channel | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 14734 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::bearer, dahdi_pvt::busy_quietlength, dahdi_pvt::busy_tonelength, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::call, dahdi_pvt::callwaitcas, dahdi_pvt::channel, dahdi_pvt::cic, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_ton, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, dahdi_pvt::confno, dahdi_pvt::context, dahdi_pri::crvs, 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, dahdi_pvt::law, dahdi_subchannel::linear, dahdi_pri::lock, lock, LOG_WARNING, dahdi_pvt::logicalspan, dahdi_pvt::mailbox, dahdi_pvt::master, ast_channel::name, ast_variable::name, dahdi_pvt::next, ast_variable::next, 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, dahdi_pvt::ss7, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, dahdi_pvt::tdd, ast_cli_entry::usage, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.
{
int channel;
struct dahdi_pvt *tmp = NULL;
struct dahdi_confinfo ci;
struct dahdi_params ps;
int x;
ast_mutex_t *lock;
struct dahdi_pvt *start;
#ifdef HAVE_PRI
char *c;
int trunkgroup;
struct dahdi_pri *pri=NULL;
#endif
switch (cmd) {
case CLI_INIT:
e->command = "dahdi show channel";
e->usage =
"Usage: dahdi show channel <chan num>\n"
" Detailed information about a given channel\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
lock = &iflock;
start = iflist;
if (a->argc != 4)
return CLI_SHOWUSAGE;
#ifdef HAVE_PRI
if ((c = strchr(a->argv[3], ':'))) {
if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
return CLI_SHOWUSAGE;
if ((trunkgroup < 1) || (channel < 1))
return CLI_SHOWUSAGE;
for (x = 0; x < NUM_SPANS; x++) {
if (pris[x].trunkgroup == trunkgroup) {
pri = pris + x;
break;
}
}
if (pri) {
start = pri->crvs;
lock = &pri->lock;
} else {
ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
return CLI_FAILURE;
}
} else
#endif
channel = atoi(a->argv[3]);
ast_mutex_lock(lock);
tmp = start;
while (tmp) {
if (tmp->channel == channel) {
#ifdef HAVE_PRI
if (pri)
ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
else
#endif
ast_cli(a->fd, "Channel: %d\n", tmp->channel);
ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
ast_cli(a->fd, "Span: %d\n", tmp->span);
ast_cli(a->fd, "Extension: %s\n", tmp->exten);
ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
ast_cli(a->fd, "Context: %s\n", tmp->context);
ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
if (tmp->vars) {
struct ast_variable *v;
ast_cli(a->fd, "Variables:\n");
for (v = tmp->vars ; v ; v = v->next)
ast_cli(a->fd, " %s = %s\n", v->name, v->value);
}
ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
ast_cli(a->fd, "Radio: %d\n", tmp->radio);
ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
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)" : "");
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)" : "");
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)" : "");
ast_cli(a->fd, "Confno: %d\n", tmp->confno);
ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
if (tmp->busydetect) {
#if defined(BUSYDETECT_TONEONLY)
ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
#elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
#endif
#ifdef BUSYDETECT_DEBUG
ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
#endif
ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
}
ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
ast_cli(a->fd, "Echo Cancellation:\n");
if (tmp->echocancel.head.tap_length) {
ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
for (x = 0; x < tmp->echocancel.head.param_count; x++) {
ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
}
ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
} else {
ast_cli(a->fd, "\tnone\n");
}
ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
if (tmp->master)
ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
for (x = 0; x < MAX_SLAVES; x++) {
if (tmp->slaves[x])
ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
}
#ifdef HAVE_OPENR2
if (tmp->mfcr2) {
char calldir[OR2_MAX_PATH];
openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
openr2_variant_t r2variant = openr2_context_get_variant(r2context);
ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
#endif
ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
}
#endif
#ifdef HAVE_SS7
if (tmp->ss7) {
ast_cli(a->fd, "CIC: %d\n", tmp->cic);
}
#endif
#ifdef HAVE_PRI
if (tmp->pri) {
ast_cli(a->fd, "PRI Flags: ");
if (tmp->resetting)
ast_cli(a->fd, "Resetting ");
if (tmp->call)
ast_cli(a->fd, "Call ");
if (tmp->bearer)
ast_cli(a->fd, "Bearer ");
ast_cli(a->fd, "\n");
if (tmp->logicalspan)
ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
else
ast_cli(a->fd, "PRI Logical Span: Implicit\n");
}
#endif
memset(&ci, 0, sizeof(ci));
ps.channo = tmp->channel;
if (tmp->subs[SUB_REAL].dfd > -1) {
memset(&ci, 0, sizeof(ci));
if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
}
if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
}
memset(&ps, 0, sizeof(ps));
if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
} else {
ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
}
}
ast_mutex_unlock(lock);
return CLI_SUCCESS;
}
tmp = tmp->next;
}
ast_cli(a->fd, "Unable to find given channel %d\n", channel);
ast_mutex_unlock(lock);
return CLI_FAILURE;
}
| static char* dahdi_show_channels | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 14610 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_GENERATE, CLI_INIT, ast_cli_entry::command, dahdi_pvt::context, dahdi_pri::crvs, dahdi_pvt::exten, ast_cli_args::fd, FORMAT, FORMAT2, dahdi_pvt::group, iflist, iflock, dahdi_pvt::language, dahdi_pvt::locallyblocked, dahdi_pri::lock, lock, dahdi_pvt::mohinterpret, dahdi_pvt::next, dahdi_pri::pri, pris, dahdi_pvt::remotelyblocked, and ast_cli_entry::usage.
{
#define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
#define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
unsigned int targetnum = 0;
int filtertype = 0;
struct dahdi_pvt *tmp = NULL;
char tmps[20] = "";
char statestr[20] = "";
char blockstr[20] = "";
ast_mutex_t *lock;
struct dahdi_pvt *start;
#ifdef HAVE_PRI
int trunkgroup;
struct dahdi_pri *pri = NULL;
int x;
#endif
switch (cmd) {
case CLI_INIT:
e->command = "dahdi show channels [trunkgroup|group|context]";
e->usage =
"Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
" Shows a list of available channels with optional filtering\n"
" <group> must be a number between 0 and 63\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
lock = &iflock;
start = iflist;
/* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */
if (!((a->argc == 3) || (a->argc == 5)))
return CLI_SHOWUSAGE;
if (a->argc == 5) {
#ifdef HAVE_PRI
if (!strcasecmp(a->argv[3], "trunkgroup")) {
/* this option requires no special handling, so leave filtertype to zero */
if ((trunkgroup = atoi(a->argv[4])) < 1)
return CLI_SHOWUSAGE;
for (x = 0; x < NUM_SPANS; x++) {
if (pris[x].trunkgroup == trunkgroup) {
pri = pris + x;
break;
}
}
if (pri) {
start = pri->crvs;
lock = &pri->lock;
} else {
ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
return CLI_FAILURE;
}
} else
#endif
if (!strcasecmp(a->argv[3], "group")) {
targetnum = atoi(a->argv[4]);
if ((targetnum < 0) || (targetnum > 63))
return CLI_SHOWUSAGE;
targetnum = 1 << targetnum;
filtertype = 1;
} else if (!strcasecmp(a->argv[3], "context")) {
filtertype = 2;
}
}
ast_mutex_lock(lock);
#ifdef HAVE_PRI
ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
#else
ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
#endif
tmp = start;
while (tmp) {
if (filtertype) {
switch(filtertype) {
case 1: /* dahdi show channels group <group> */
if (!(tmp->group & targetnum)) {
tmp = tmp->next;
continue;
}
break;
case 2: /* dahdi show channels context <context> */
if (strcasecmp(tmp->context, a->argv[4])) {
tmp = tmp->next;
continue;
}
break;
default:
;
}
}
if (tmp->channel > 0) {
snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
} else
ast_copy_string(tmps, "pseudo", sizeof(tmps));
if (tmp->locallyblocked)
blockstr[0] = 'L';
else
blockstr[0] = ' ';
if (tmp->remotelyblocked)
blockstr[1] = 'R';
else
blockstr[1] = ' ';
blockstr[2] = '\0';
snprintf(statestr, sizeof(statestr), "%s", "In Service");
ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
tmp = tmp->next;
}
ast_mutex_unlock(lock);
return CLI_SUCCESS;
#undef FORMAT
#undef FORMAT2
}
| static char* dahdi_show_status | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 14979 of file chan_dahdi.c.
References ast_cli(), CLI_GENERATE, CLI_INIT, ast_cli_entry::command, errno, ast_cli_args::fd, FORMAT, FORMAT2, and ast_cli_entry::usage.
{
#define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
#define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
int span;
int res;
char alarmstr[50];
int ctl;
struct dahdi_spaninfo s;
switch (cmd) {
case CLI_INIT:
e->command = "dahdi show status";
e->usage =
"Usage: dahdi show status\n"
" Shows a list of DAHDI cards with status\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
ctl = open("/dev/dahdi/ctl", O_RDWR);
if (ctl < 0) {
ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
return CLI_FAILURE;
}
ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
s.spanno = span;
res = ioctl(ctl, DAHDI_SPANSTAT, &s);
if (res) {
continue;
}
alarmstr[0] = '\0';
if (s.alarms > 0) {
if (s.alarms & DAHDI_ALARM_BLUE)
strcat(alarmstr, "BLU/");
if (s.alarms & DAHDI_ALARM_YELLOW)
strcat(alarmstr, "YEL/");
if (s.alarms & DAHDI_ALARM_RED)
strcat(alarmstr, "RED/");
if (s.alarms & DAHDI_ALARM_LOOPBACK)
strcat(alarmstr, "LB/");
if (s.alarms & DAHDI_ALARM_RECOVER)
strcat(alarmstr, "REC/");
if (s.alarms & DAHDI_ALARM_NOTOPEN)
strcat(alarmstr, "NOP/");
if (!strlen(alarmstr))
strcat(alarmstr, "UUU/");
if (strlen(alarmstr)) {
/* Strip trailing / */
alarmstr[strlen(alarmstr) - 1] = '\0';
}
} else {
if (s.numchans)
strcpy(alarmstr, "OK");
else
strcpy(alarmstr, "UNCONFIGURED");
}
ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
"CAS",
s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
"Unk",
s.lineconfig & DAHDI_CONFIG_CRC4 ?
s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
lbostr[s.lbo]
);
}
close(ctl);
return CLI_SUCCESS;
#undef FORMAT
#undef FORMAT2
}
| static char* dahdi_show_version | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15062 of file chan_dahdi.c.
References ast_cli(), CLI_GENERATE, CLI_INIT, ast_cli_entry::command, errno, ast_cli_args::fd, and ast_cli_entry::usage.
{
int pseudo_fd = -1;
struct dahdi_versioninfo vi;
switch (cmd) {
case CLI_INIT:
e->command = "dahdi show version";
e->usage =
"Usage: dahdi show version\n"
" Shows the DAHDI version in use\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
ast_cli(a->fd, "Failed to open control file to get version.\n");
return CLI_SUCCESS;
}
strcpy(vi.version, "Unknown");
strcpy(vi.echo_canceller, "Unknown");
if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
else
ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
close(pseudo_fd);
return CLI_SUCCESS;
}
| static char* dahdi_sig2str | ( | int | sig | ) | [static] |
Definition at line 2410 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_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, and SIG_SS7.
{
static char buf[256];
switch (sig) {
case SIG_EM:
return "E & M Immediate";
case SIG_EMWINK:
return "E & M Wink";
case SIG_EM_E1:
return "E & M E1";
case SIG_FEATD:
return "Feature Group D (DTMF)";
case SIG_FEATDMF:
return "Feature Group D (MF)";
case SIG_FEATDMF_TA:
return "Feature Groud D (MF) Tandem Access";
case SIG_FEATB:
return "Feature Group B (MF)";
case SIG_E911:
return "E911 (MF)";
case SIG_FGC_CAMA:
return "FGC/CAMA (Dialpulse)";
case SIG_FGC_CAMAMF:
return "FGC/CAMA (MF)";
case SIG_FXSLS:
return "FXS Loopstart";
case SIG_FXSGS:
return "FXS Groundstart";
case SIG_FXSKS:
return "FXS Kewlstart";
case SIG_FXOLS:
return "FXO Loopstart";
case SIG_FXOGS:
return "FXO Groundstart";
case SIG_FXOKS:
return "FXO Kewlstart";
case SIG_PRI:
return "ISDN PRI";
case SIG_BRI:
return "ISDN BRI Point to Point";
case SIG_BRI_PTMP:
return "ISDN BRI Point to MultiPoint";
case SIG_SS7:
return "SS7";
case SIG_MFCR2:
return "MFC/R2";
case SIG_SF:
return "SF (Tone) Immediate";
case SIG_SFWINK:
return "SF (Tone) Wink";
case SIG_SF_FEATD:
return "SF (Tone) with Feature Group D (DTMF)";
case SIG_SF_FEATDMF:
return "SF (Tone) with Feature Group D (MF)";
case SIG_SF_FEATB:
return "SF (Tone) with Feature Group B (MF)";
case SIG_GR303FXOKS:
return "GR-303 with FXOKS";
case SIG_GR303FXSKS:
return "GR-303 with FXSKS";
case 0:
return "Pseudo";
default:
snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
return buf;
}
}
| static void dahdi_softhangup_all | ( | void | ) | [static] |
Definition at line 14434 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().
{
struct dahdi_pvt *p;
retry:
ast_mutex_lock(&iflock);
for (p = iflist; p; p = p->next) {
ast_mutex_lock(&p->lock);
if (p->owner && !p->restartpending) {
if (ast_channel_trylock(p->owner)) {
if (option_debug > 2)
ast_verbose("Avoiding deadlock\n");
/* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
ast_mutex_unlock(&p->lock);
ast_mutex_unlock(&iflock);
goto retry;
}
if (option_debug > 2)
ast_verbose("Softhanging up on %s\n", p->owner->name);
ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
p->restartpending = 1;
num_restart_pending++;
ast_channel_unlock(p->owner);
}
ast_mutex_unlock(&p->lock);
}
ast_mutex_unlock(&iflock);
}
| static void dahdi_ss7_error | ( | struct ss7 * | ss7, | |
| char * | s | |||
| ) | [static] |
Definition at line 12064 of file chan_dahdi.c.
References ast_log(), linksets, and LOG_ERROR.
Referenced by dahdi_restart(), and load_module().
| static void dahdi_ss7_message | ( | struct ss7 * | ss7, | |
| char * | s | |||
| ) | [static] |
Definition at line 12047 of file chan_dahdi.c.
References ast_verbose(), and linksets.
Referenced by dahdi_restart(), and load_module().
{
#if 0
int i;
for (i = 0; i < NUM_SPANS; i++)
if (linksets[i].ss7 == ss7)
break;
ast_verbose("[%d] %s", i+1, s);
#else
ast_verbose("%s", s);
#endif
}
| static void dahdi_train_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2694 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, dahdi_pvt::echocanon, dahdi_pvt::echotraining, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_answer(), and dahdi_handle_event().
{
int x;
int res;
if (p && p->echocanon && p->echotraining) {
x = p->echotraining;
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
if (res)
ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
else
ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
} else {
ast_debug(1, "No echo training requested\n");
}
}
| static void dahdi_unlink | ( | struct dahdi_pvt * | slave, | |
| struct dahdi_pvt * | master, | |||
| int | needlock | |||
| ) | [static] |
Definition at line 5127 of file chan_dahdi.c.
References ast_debug, ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), dahdi_pvt::channel, conf_del(), DEADLOCK_AVOIDANCE, dahdi_pvt::inconference, dahdi_pvt::lock, dahdi_pvt::master, dahdi_pvt::slaves, SUB_REAL, dahdi_pvt::subs, and update_conf().
Referenced by dahdi_bridge(), and dahdi_fixup().
{
/* Unlink a specific slave or all slaves/masters from a given master */
int x;
int hasslaves;
if (!master)
return;
if (needlock) {
ast_mutex_lock(&master->lock);
if (slave) {
while (ast_mutex_trylock(&slave->lock)) {
DEADLOCK_AVOIDANCE(&master->lock);
}
}
}
hasslaves = 0;
for (x = 0; x < MAX_SLAVES; x++) {
if (master->slaves[x]) {
if (!slave || (master->slaves[x] == slave)) {
/* Take slave out of the conference */
ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
master->slaves[x]->master = NULL;
master->slaves[x] = NULL;
} else
hasslaves = 1;
}
if (!hasslaves)
master->inconference = 0;
}
if (!slave) {
if (master->master) {
/* Take master out of the conference */
conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
hasslaves = 0;
for (x = 0; x < MAX_SLAVES; x++) {
if (master->master->slaves[x] == master)
master->master->slaves[x] = NULL;
else if (master->master->slaves[x])
hasslaves = 1;
}
if (!hasslaves)
master->master->inconference = 0;
}
master->master = NULL;
}
update_conf(master);
if (needlock) {
if (slave)
ast_mutex_unlock(&slave->lock);
ast_mutex_unlock(&master->lock);
}
}
| static int dahdi_wait_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition at line 385 of file chan_dahdi.c.
Referenced by ss_thread().
{
int i, j = 0;
i = DAHDI_IOMUX_SIGEVENT;
if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
return -1;
if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
return -1;
return j;
}
| static int dahdi_wink | ( | struct dahdi_pvt * | p, | |
| int | idx | |||
| ) | [static] |
Definition at line 7721 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by ss_thread().
{
int j;
dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
for (;;)
{
/* set bits of interest */
j = DAHDI_IOMUX_SIGEVENT;
/* wait for some happening */
if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
/* exit loop if we have it */
if (j & DAHDI_IOMUX_SIGEVENT) break;
}
/* get the event info */
if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
return 0;
}
| static int dahdi_write | ( | struct ast_channel * | ast, | |
| struct ast_frame * | frame | |||
| ) | [static] |
Definition at line 7176 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, LOG_WARNING, 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.
{
struct dahdi_pvt *p = ast->tech_pvt;
int res;
int idx;
idx = dahdi_get_index(ast, p, 0);
if (idx < 0) {
ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
return -1;
}
#if 0
#ifdef HAVE_PRI
ast_mutex_lock(&p->lock);
if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
if (p->pri->pri) {
if (!pri_grab(p, p->pri)) {
pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
pri_rel(p->pri);
} else
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
}
p->proceeding=1;
}
ast_mutex_unlock(&p->lock);
#endif
#endif
/* Write a frame of (presumably voice) data */
if (frame->frametype != AST_FRAME_VOICE) {
if (frame->frametype != AST_FRAME_IMAGE)
ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
return 0;
}
if ((frame->subclass != AST_FORMAT_SLINEAR) &&
(frame->subclass != AST_FORMAT_ULAW) &&
(frame->subclass != AST_FORMAT_ALAW)) {
ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
return -1;
}
if (p->dialing) {
ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
return 0;
}
if (!p->owner) {
ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
return 0;
}
if (p->cidspill) {
ast_debug(1, "Dropping frame since I've still got a callerid spill\n");
return 0;
}
/* Return if it's not valid data */
if (!frame->data.ptr || !frame->datalen)
return 0;
if (frame->subclass == AST_FORMAT_SLINEAR) {
if (!p->subs[idx].linear) {
p->subs[idx].linear = 1;
res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
if (res)
ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
}
res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
} else {
/* x-law already */
if (p->subs[idx].linear) {
p->subs[idx].linear = 0;
res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
if (res)
ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
}
res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
}
if (res < 0) {
ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
return -1;
}
return 0;
}
| static void destroy_all_channels | ( | void | ) | [static] |
Definition at line 3940 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().
{
int x;
struct dahdi_pvt *p, *pl;
while (num_restart_pending) {
usleep(1);
}
ast_mutex_lock(&iflock);
/* Destroy all the interfaces and free their memory */
p = iflist;
while (p) {
/* Free any callerid */
if (p->cidspill)
ast_free(p->cidspill);
pl = p;
p = p->next;
x = pl->channel;
/* Free associated memory */
if (pl)
destroy_dahdi_pvt(&pl);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
}
iflist = NULL;
ifcount = 0;
ast_mutex_unlock(&iflock);
}
Definition at line 3890 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().
{
int owned = 0;
int i = 0;
if (!now) {
if (cur->owner) {
owned = 1;
}
for (i = 0; i < 3; i++) {
if (cur->subs[i].owner) {
owned = 1;
}
}
if (!owned) {
if (prev) {
prev->next = cur->next;
if (prev->next)
prev->next->prev = prev;
else
ifend = prev;
} else {
iflist = cur->next;
if (iflist)
iflist->prev = NULL;
else
ifend = NULL;
}
destroy_dahdi_pvt(&cur);
}
} else {
if (prev) {
prev->next = cur->next;
if (prev->next)
prev->next->prev = prev;
else
ifend = prev;
} else {
iflist = cur->next;
if (iflist)
iflist->prev = NULL;
else
ifend = NULL;
}
destroy_dahdi_pvt(&cur);
}
return 0;
}
| static void destroy_dahdi_pvt | ( | struct dahdi_pvt ** | pvt | ) | [static] |
Definition at line 3867 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 destroy_all_channels(), destroy_channel(), duplicate_pseudo(), and mkintf().
{
struct dahdi_pvt *p = *pvt;
/* Remove channel from the list */
if (p->prev)
p->prev->next = p->next;
if (p->next)
p->next->prev = p->prev;
if (p->use_smdi)
ast_smdi_interface_unref(p->smdi_iface);
if (p->mwi_event_sub)
ast_event_unsubscribe(p->mwi_event_sub);
if (p->vars) {
ast_variables_destroy(p->vars);
}
ast_mutex_destroy(&p->lock);
dahdi_close_sub(p, SUB_REAL);
if (p->owner)
p->owner->tech_pvt = NULL;
free(p);
*pvt = NULL;
}
| static char* dialplan2str | ( | int | dialplan | ) | [static] |
Definition at line 2401 of file chan_dahdi.c.
Referenced by dahdi_call(), and mkintf().
{
if (dialplan == -1 || dialplan == -2) {
return("Dynamically set dialplan in ISDN");
}
return (pri_plan2str(dialplan));
}
| static int digit_to_dtmfindex | ( | char | digit | ) | [static] |
Definition at line 2231 of file chan_dahdi.c.
Referenced by dahdi_digit_begin().
{
if (isdigit(digit))
return DAHDI_TONE_DTMF_BASE + (digit - '0');
else if (digit >= 'A' && digit <= 'D')
return DAHDI_TONE_DTMF_A + (digit - 'A');
else if (digit >= 'a' && digit <= 'd')
return DAHDI_TONE_DTMF_A + (digit - 'a');
else if (digit == '*')
return DAHDI_TONE_DTMF_s;
else if (digit == '#')
return DAHDI_TONE_DTMF_p;
else
return -1;
}
| static void disable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5206 of file chan_dahdi.c.
References ast_dsp_set_features(), dahdi_subchannel::dfd, dahdi_pvt::dsp, dahdi_pvt::dsp_features, dahdi_pvt::hardwaredtmf, dahdi_pvt::ignoredtmf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_bridge().
{
int val;
p->ignoredtmf = 1;
val = 0;
ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
if (!p->hardwaredtmf && p->dsp) {
p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
ast_dsp_set_features(p->dsp, p->dsp_features);
}
}
| static void* do_idle_thread | ( | void * | vchan | ) | [static] |
Definition at line 12287 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(), dahdi_pvt::channel, ast_channel::context, ast_channel::exten, ast_frame::frametype, dahdi_pri::idlecontext, dahdi_pri::idledial, dahdi_pri::idleext, LOG_WARNING, ast_channel::name, dahdi_pvt::pri, ast_channel::priority, ast_frame::subclass, and ast_channel::tech_pvt.
Referenced by pri_dchannel().
{
struct ast_channel *chan = vchan;
struct dahdi_pvt *pvt = chan->tech_pvt;
struct ast_frame *f;
char ex[80];
/* Wait up to 30 seconds for an answer */
int newms, ms = 30000;
ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
if (ast_call(chan, ex, 0)) {
ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
ast_hangup(chan);
return NULL;
}
while ((newms = ast_waitfor(chan, ms)) > 0) {
f = ast_read(chan);
if (!f) {
/* Got hangup */
break;
}
if (f->frametype == AST_FRAME_CONTROL) {
switch (f->subclass) {
case AST_CONTROL_ANSWER:
/* Launch the PBX */
ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
chan->priority = 1;
ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
ast_pbx_run(chan);
/* It's already hungup, return immediately */
return NULL;
case AST_CONTROL_BUSY:
ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
break;
case AST_CONTROL_CONGESTION:
ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
break;
};
}
ast_frfree(f);
ms = newms;
}
/* Hangup the channel since nothing happend */
ast_hangup(chan);
return NULL;
}
| static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 9609 of file chan_dahdi.c.
References ast_calloc, ast_debug, ast_fdisset(), ast_free, AST_LAW, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_background, ast_strlen_zero(), mwi_thread_data::buf, buf, calc_energy(), dahdi_pvt::channel, dahdi_pvt::cidspill, dahdi_destroy_channel_bynum(), dahdi_get_event(), dahdi_subchannel::dfd, errno, event2str(), dahdi_pvt::fxsoffhookstate, handle_init_event(), has_voicemail(), iflist, iflock, last, mwi_thread_data::len, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pvt::msgstate, mwi_send_init(), mwi_send_process_buffer(), mwi_send_process_event(), mwi_thread(), dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitoractive, dahdi_pvt::mwisendactive, dahdi_pvt::next, dahdi_pvt::onhooktime, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pri, mwi_thread_data::pvt, dahdi_pvt::radio, dahdi_pvt::sig, SIG_MFCR2, SUB_REAL, and dahdi_pvt::subs.
Referenced by restart_monitor().
{
int count, res, res2, spoint, pollres=0;
struct dahdi_pvt *i;
struct dahdi_pvt *last = NULL;
struct dahdi_pvt *doomed;
time_t thispass = 0, lastpass = 0;
int found;
char buf[1024];
struct pollfd *pfds=NULL;
int lastalloc = -1;
/* This thread monitors all the frame relay interfaces which are not yet in use
(and thus do not have a separate thread) indefinitely */
/* From here on out, we die whenever asked */
#if 0
if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
return NULL;
}
ast_debug(1, "Monitor starting...\n");
#endif
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
for (;;) {
/* Lock the interface list */
ast_mutex_lock(&iflock);
if (!pfds || (lastalloc != ifcount)) {
if (pfds) {
ast_free(pfds);
pfds = NULL;
}
if (ifcount) {
if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
ast_mutex_unlock(&iflock);
return NULL;
}
}
lastalloc = ifcount;
}
/* Build the stuff we're going to poll on, that is the socket of every
dahdi_pvt that does not have an associated owner channel */
count = 0;
i = iflist;
while (i) {
if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
/* This needs to be watched, as it lacks an owner */
pfds[count].fd = i->subs[SUB_REAL].dfd;
pfds[count].events = POLLPRI;
pfds[count].revents = 0;
/* If we are monitoring for VMWI or sending CID, we need to
read from the channel as well */
if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk)
pfds[count].events |= POLLIN;
count++;
}
}
i = i->next;
}
/* Okay, now that we know what to do, release the interface lock */
ast_mutex_unlock(&iflock);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_testcancel();
/* Wait at least a second for something to happen */
res = poll(pfds, count, 1000);
pthread_testcancel();
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
/* Okay, poll has finished. Let's see what happened. */
if (res < 0) {
if ((errno != EAGAIN) && (errno != EINTR))
ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
continue;
}
/* Alright, lock the interface list again, and let's look and see what has
happened */
ast_mutex_lock(&iflock);
found = 0;
spoint = 0;
lastpass = thispass;
thispass = time(NULL);
i = iflist;
doomed = NULL;
for (i = iflist;; i = i->next) {
if (doomed) {
int res;
res = dahdi_destroy_channel_bynum(doomed->channel);
if (!res) {
ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
}
doomed = NULL;
}
if (!i) {
break;
}
if (thispass != lastpass) {
if (!found && ((i == last) || ((i == iflist) && !last))) {
last = i;
if (last) {
/* Only allow MWI to be initiated on a quiescent fxs port */
if (!last->mwisendactive && last->sig & __DAHDI_SIG_FXO &&
!last->fxsoffhookstate && !last->owner &&
!ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3)) {
res = has_voicemail(last);
if (last->msgstate != res) {
/* Set driver resources for signalling VMWI */
res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
if (res2) {
/* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
}
/* If enabled for FSK spill then initiate it */
if (mwi_send_init(last)) {
ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
}
last->msgstate = res;
found ++;
}
}
last = last->next;
}
}
}
if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
if (i->radio && !i->owner)
{
res = dahdi_get_event(i->subs[SUB_REAL].dfd);
if (res)
{
ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
/* Don't hold iflock while handling init events */
ast_mutex_unlock(&iflock);
doomed = handle_init_event(i, res);
ast_mutex_lock(&iflock);
}
continue;
}
pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
if (pollres & POLLIN) {
if (i->owner || i->subs[SUB_REAL].owner) {
#ifdef HAVE_PRI
if (!i->pri)
#endif
ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
continue;
}
if (!i->mwimonitor_fsk && !i->mwisendactive) {
ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
continue;
}
res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
if (res > 0) {
if (i->mwimonitor_fsk) {
if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
pthread_attr_t attr;
pthread_t threadid;
struct mwi_thread_data *mtd;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
mtd->pvt = i;
memcpy(mtd->buf, buf, res);
mtd->len = res;
if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
ast_free(mtd);
}
i->mwimonitoractive = 1;
}
}
}
if (i->mwisendactive) {
mwi_send_process_buffer(i, res);
}
} else {
ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
}
}
if (pollres & POLLPRI) {
if (i->owner || i->subs[SUB_REAL].owner) {
#ifdef HAVE_PRI
if (!i->pri)
#endif
ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
continue;
}
res = dahdi_get_event(i->subs[SUB_REAL].dfd);
ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
/* Don't hold iflock while handling init events */
ast_mutex_unlock(&iflock);
if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
doomed = handle_init_event(i, res);
}
ast_mutex_lock(&iflock);
}
}
}
ast_mutex_unlock(&iflock);
}
/* Never reached */
return NULL;
}
Definition at line 10896 of file chan_dahdi.c.
References ast_log(), ast_malloc, ast_mutex_init(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_open(), dahdi_pvt::destroy, destroy_dahdi_pvt(), dahdi_subchannel::dfd, errno, iflist, dahdi_pvt::lock, LOG_ERROR, LOG_WARNING, dahdi_pvt::next, dahdi_pvt::prev, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_request().
{
struct dahdi_pvt *p;
struct dahdi_bufferinfo bi;
int res;
if ((p = ast_malloc(sizeof(*p)))) {
memcpy(p, src, sizeof(struct dahdi_pvt));
ast_mutex_init(&p->lock);
p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
if (p->subs[SUB_REAL].dfd < 0) {
ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
destroy_dahdi_pvt(&p);
return NULL;
}
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
if (!res) {
bi.txbufpolicy = src->buf_policy;
bi.rxbufpolicy = src->buf_policy;
bi.numbufs = src->buf_no;
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
}
} else
ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
}
p->destroy = 1;
p->next = iflist;
p->prev = NULL;
iflist = p;
if (iflist->next)
iflist->next->prev = p;
return p;
}
| static void enable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5221 of file chan_dahdi.c.
References ast_dsp_set_features(), CHAN_PSEUDO, dahdi_pvt::channel, dahdi_subchannel::dfd, dahdi_pvt::dsp, dahdi_pvt::dsp_features, dahdi_pvt::hardwaredtmf, dahdi_pvt::ignoredtmf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_bridge().
{
int val;
if (p->channel == CHAN_PSEUDO)
return;
p->ignoredtmf = 0;
val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
if (!p->hardwaredtmf && p->dsp) {
p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
ast_dsp_set_features(p->dsp, p->dsp_features);
}
}
| static char* event2str | ( | int | event | ) | [static] |
Definition at line 2391 of file chan_dahdi.c.
References ARRAY_LEN, and buf.
Referenced by __dahdi_exception(), dahdi_handle_event(), do_monitor(), mwi_thread(), pri_dchannel(), and ss_thread().
| static void fill_rxgain | ( | struct dahdi_gains * | g, | |
| float | gain, | |||
| int | law | |||
| ) | [static] |
Definition at line 2763 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_rxgain().
{
int j;
int k;
float linear_gain = pow(10.0, gain / 20.0);
switch (law) {
case DAHDI_LAW_ALAW:
for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
if (gain) {
k = (int) (((float) AST_ALAW(j)) * linear_gain);
if (k > 32767) k = 32767;
if (k < -32767) k = -32767;
g->rxgain[j] = AST_LIN2A(k);
} else {
g->rxgain[j] = j;
}
}
break;
case DAHDI_LAW_MULAW:
for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
if (gain) {
k = (int) (((float) AST_MULAW(j)) * linear_gain);
if (k > 32767) k = 32767;
if (k < -32767) k = -32767;
g->rxgain[j] = AST_LIN2MU(k);
} else {
g->rxgain[j] = j;
}
}
break;
}
}
| static void fill_txgain | ( | struct dahdi_gains * | g, | |
| float | gain, | |||
| int | law | |||
| ) | [static] |
Definition at line 2729 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_txgain().
{
int j;
int k;
float linear_gain = pow(10.0, gain / 20.0);
switch (law) {
case DAHDI_LAW_ALAW:
for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
if (gain) {
k = (int) (((float) AST_ALAW(j)) * linear_gain);
if (k > 32767) k = 32767;
if (k < -32767) k = -32767;
g->txgain[j] = AST_LIN2A(k);
} else {
g->txgain[j] = j;
}
}
break;
case DAHDI_LAW_MULAW:
for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
if (gain) {
k = (int) (((float) AST_MULAW(j)) * linear_gain);
if (k > 32767) k = 32767;
if (k < -32767) k = -32767;
g->txgain[j] = AST_LIN2MU(k);
} else {
g->txgain[j] = j;
}
}
break;
}
}
| static struct dahdi_pvt* find_channel | ( | int | channel | ) | [static, read] |
Definition at line 15327 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().
| static int get_alarms | ( | struct dahdi_pvt * | p | ) | [static] |
Checks channel for alarms
| p | a channel to check for alarms. |
Definition at line 5665 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, errno, LOG_WARNING, dahdi_pvt::span, SUB_REAL, and dahdi_pvt::subs.
Referenced by action_dahdishowchannels(), dahdi_handle_event(), handle_init_event(), mkintf(), and mwi_thread().
{
int res;
struct dahdi_spaninfo zi;
struct dahdi_params params;
memset(&zi, 0, sizeof(zi));
zi.spanno = p->span;
if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
if (zi.alarms != DAHDI_ALARM_NONE)
return zi.alarms;
} else {
ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
return 0;
}
/* No alarms on the span. Check for channel alarms. */
memset(¶ms, 0, sizeof(params));
if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
return params.chan_alarms;
ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
return DAHDI_ALARM_NONE;
}
| static void handle_alarms | ( | struct dahdi_pvt * | p, | |
| int | alms | |||
| ) | [static] |
Definition at line 5773 of file chan_dahdi.c.
References alarm2str(), ast_log(), dahdi_pvt::channel, EVENT_FLAG_SYSTEM, LOG_WARNING, and manager_event.
Referenced by dahdi_handle_event(), handle_init_event(), mkintf(), and mwi_thread().
{
const char *alarm_str = alarm2str(alms);
ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
manager_event(EVENT_FLAG_SYSTEM, "Alarm",
"Alarm: %s\r\n"
"Channel: %d\r\n",
alarm_str, p->channel);
}
| static char* handle_dahdi_show_cadences | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 14942 of file chan_dahdi.c.
References ast_cli(), CLI_GENERATE, CLI_INIT, COLOR_BLACK, COLOR_GREEN, COLOR_MAGENTA, ast_cli_entry::command, ast_cli_args::fd, term_color(), and ast_cli_entry::usage.
{
int i, j;
switch (cmd) {
case CLI_INIT:
e->command = "dahdi show cadences";
e->usage =
"Usage: dahdi show cadences\n"
" Shows all cadences currently defined\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
for (i = 0; i < num_cadence; i++) {
char output[1024];
char tmp[16], tmp2[64];
snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
for (j = 0; j < 16; j++) {
if (cadences[i].ringcadence[j] == 0)
break;
snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
if (cidrings[i] * 2 - 1 == j)
term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
else
term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
if (j != 0)
strncat(output, ",", sizeof(output) - strlen(output) - 1);
strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
}
ast_cli(a->fd,"%s\n",output);
}
return CLI_SUCCESS;
}
Definition at line 9382 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, 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(), dahdi_subchannel::dfd, errno, EVENT_FLAG_SYSTEM, dahdi_pvt::fxsoffhookstate, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::immediate, dahdi_pvt::inalarm, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, manager_event, dahdi_pvt::mwimonitor_neon, notify_message(), dahdi_pvt::polarity, 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 do_monitor().
{
int res;
pthread_t threadid;
struct ast_channel *chan;
/* Handle an event on a given channel for the monitor thread. */
switch (event) {
case DAHDI_EVENT_NONE:
case DAHDI_EVENT_BITSCHANGED:
break;
case DAHDI_EVENT_WINKFLASH:
case DAHDI_EVENT_RINGOFFHOOK:
if (i->inalarm) break;
if (i->radio) break;
/* Got a ring/answer. What kind of channel are we? */
switch (i->sig) {
case SIG_FXOLS:
case SIG_FXOGS:
case SIG_FXOKS:
res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
i->fxsoffhookstate = 1;
if (res && (errno == EBUSY))
break;
if (i->cidspill) {
/* Cancel VMWI spill */
ast_free(i->cidspill);
i->cidspill = NULL;
}
if (i->immediate) {
dahdi_enable_ec(i);
/* The channel is immediately up. Start right away */
res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
if (!chan) {
ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
if (res < 0)
ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
}
} else {
/* Check for callerid, digits, etc */
chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
if (chan) {
if (has_voicemail(i))
res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
else
res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
if (res < 0)
ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
if (res < 0)
ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
ast_hangup(chan);
}
} else
ast_log(LOG_WARNING, "Unable to create channel\n");
}
break;
case SIG_FXSLS:
case SIG_FXSGS:
case SIG_FXSKS:
i->ringt = i->ringt_base;
/* Fall through */
case SIG_EMWINK:
case SIG_FEATD:
case SIG_FEATDMF:
case SIG_FEATDMF_TA:
case SIG_E911:
case SIG_FGC_CAMA:
case SIG_FGC_CAMAMF:
case SIG_FEATB:
case SIG_EM:
case SIG_EM_E1:
case SIG_SFWINK:
case SIG_SF_FEATD:
case SIG_SF_FEATDMF:
case SIG_SF_FEATB:
case SIG_SF:
/* Check for callerid, digits, etc */
if (i->cid_start == CID_START_POLARITY_IN) {
chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
} else {
chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
}
if (!chan) {
ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
} else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
}
ast_hangup(chan);
}
break;
default:
ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
if (res < 0)
ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
return NULL;
}
break;
case DAHDI_EVENT_NOALARM:
i->inalarm = 0;
ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
"Channel: %d\r\n", i->channel);
break;
case DAHDI_EVENT_ALARM:
i->inalarm = 1;
res = get_alarms(i);
handle_alarms(i, res);
/* fall thru intentionally */
case DAHDI_EVENT_ONHOOK:
if (i->radio)
break;
/* Back on hook. Hang up. */
switch (i->sig) {
case SIG_FXOLS:
case SIG_FXOGS:
case SIG_FEATD:
case SIG_FEATDMF:
case SIG_FEATDMF_TA:
case SIG_E911:
case SIG_FGC_CAMA:
case SIG_FGC_CAMAMF:
case SIG_FEATB:
case SIG_EM:
case SIG_EM_E1:
case SIG_EMWINK:
case SIG_SF_FEATD:
case SIG_SF_FEATDMF:
case SIG_SF_FEATB:
case SIG_SF:
case SIG_SFWINK:
case SIG_FXSLS:
case SIG_FXSGS:
case SIG_FXSKS:
case SIG_GR303FXSKS:
dahdi_disable_ec(i);
res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
break;
case SIG_GR303FXOKS:
case SIG_FXOKS:
dahdi_disable_ec(i);
/* Diddle the battery for the zhone */
#ifdef ZHONE_HACK
dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
usleep(1);
#endif
res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
break;
case SIG_PRI:
case SIG_SS7:
case SIG_BRI:
case SIG_BRI_PTMP:
dahdi_disable_ec(i);
res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
break;
default:
ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
return NULL;
}
if (i->sig & __DAHDI_SIG_FXO) {
i->fxsoffhookstate = 0;
}
break;
case DAHDI_EVENT_POLARITY:
switch (i->sig) {
case SIG_FXSLS:
case SIG_FXSKS:
case SIG_FXSGS:
/* We have already got a PR before the channel was
created, but it wasn't handled. We need polarity
to be REV for remote hangup detection to work.
At least in Spain */
if (i->hanguponpolarityswitch)
i->polarity = POLARITY_REV;
if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
i->polarity = POLARITY_REV;
ast_verb(2, "Starting post polarity "
"CID detection on channel %d\n",
i->channel);
chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
if (!chan) {
ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
} else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
}
}
break;
default:
ast_log(LOG_WARNING, "handle_init_event detected "
"polarity reversal on non-FXO (SIG_FXS) "
"interface %d\n", i->channel);
}
break;
case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
ast_log(LOG_NOTICE,
"Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
i->channel);
return i;
case DAHDI_EVENT_NEONMWI_ACTIVE:
if (i->mwimonitor_neon) {
notify_message(i->mailbox, 1);
ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
}
break;
case DAHDI_EVENT_NEONMWI_INACTIVE:
if (i->mwimonitor_neon) {
notify_message(i->mailbox, 0);
ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
}
break;
}
return NULL;
}
| static char* handle_pri_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13832 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), CLI_GENERATE, CLI_INIT, 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, pridebugfdlock, pris, ast_cli_entry::usage, and ast_cli_args::word.
{
int span;
int x;
int level = 0;
switch (cmd) {
case CLI_INIT:
e->command = "pri set debug {on|off|0|1|2} span";
e->usage =
"Usage: pri set debug {<level>|on|off} span <span>\n"
" Enables debugging on a given PRI span\n";
return NULL;
case CLI_GENERATE:
return complete_span_4(a->line, a->word, a->pos, a->n);
}
if (a->argc < 6) {
return CLI_SHOWUSAGE;
}
if (!strcasecmp(a->argv[3], "on")) {
level = 1;
} else if (!strcasecmp(a->argv[3], "off")) {
level = 0;
} else {
level = atoi(a->argv[3]);
}
span = atoi(a->argv[5]);
if ((span < 1) || (span > NUM_SPANS)) {
ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
return CLI_SUCCESS;
}
if (!pris[span-1].pri) {
ast_cli(a->fd, "No PRI running on span %d\n", span);
return CLI_SUCCESS;
}
for (x = 0; x < NUM_DCHANS; x++) {
if (pris[span-1].dchans[x]) {
if (level == 1) {
pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
PRI_DEBUG_Q921_STATE);
ast_cli(a->fd, "Enabled debugging on span %d\n", span);
} else if (level == 0) {
pri_set_debug(pris[span-1].dchans[x], 0);
//close the file if it's set
ast_mutex_lock(&pridebugfdlock);
close(pridebugfd);
pridebugfd = -1;
ast_cli(a->fd, "PRI debug output to file disabled\n");
ast_mutex_unlock(&pridebugfdlock);
} else {
pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
ast_cli(a->fd, "Enabled debugging on span %d\n", span);
}
}
}
return CLI_SUCCESS;
}
| static char* handle_pri_set_debug_file | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13794 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, ast_cli_entry::command, ast_cli_args::fd, pridebugfdlock, and ast_cli_entry::usage.
{
int myfd;
switch (cmd) {
case CLI_INIT:
e->command = "pri set debug file";
e->usage = "Usage: pri set debug file [output-file]\n"
" Sends PRI debug output to the specified output file\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc < 5)
return CLI_SHOWUSAGE;
if (ast_strlen_zero(a->argv[4]))
return CLI_SHOWUSAGE;
myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
if (myfd < 0) {
ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
return CLI_SUCCESS;
}
ast_mutex_lock(&pridebugfdlock);
if (pridebugfd >= 0)
close(pridebugfd);
pridebugfd = myfd;
ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
ast_mutex_unlock(&pridebugfdlock);
ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
return CLI_SUCCESS;
}
| static char* handle_pri_show_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 14005 of file chan_dahdi.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), CLI_GENERATE, CLI_INIT, ast_cli_entry::command, debug, ast_cli_args::fd, pridebugfdlock, pris, and ast_cli_entry::usage.
{
int x;
int span;
int count=0;
int debug=0;
switch (cmd) {
case CLI_INIT:
e->command = "pri show debug";
e->usage =
"Usage: pri show debug\n"
" Show the debug state of pri spans\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
for (span = 0; span < NUM_SPANS; span++) {
if (pris[span].pri) {
for (x = 0; x < NUM_DCHANS; x++) {
debug = 0;
if (pris[span].dchans[x]) {
debug = pri_get_debug(pris[span].dchans[x]);
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" );
count++;
}
}
}
}
ast_mutex_lock(&pridebugfdlock);
if (pridebugfd >= 0)
ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
ast_mutex_unlock(&pridebugfdlock);
if (!count)
ast_cli(a->fd, "No debug set or no PRI running\n");
return CLI_SUCCESS;
}
| static char* handle_pri_show_span | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13953 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_free, build_status(), CLI_GENERATE, CLI_INIT, 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, status, ast_cli_entry::usage, and ast_cli_args::word.
{
int span;
int x;
char status[256];
switch (cmd) {
case CLI_INIT:
e->command = "pri show span";
e->usage =
"Usage: pri show span <span>\n"
" Displays PRI Information on a given PRI span\n";
return NULL;
case CLI_GENERATE:
return complete_span_4(a->line, a->word, a->pos, a->n);
}
if (a->argc < 4)
return CLI_SHOWUSAGE;
span = atoi(a->argv[3]);
if ((span < 1) || (span > NUM_SPANS)) {
ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
return CLI_SUCCESS;
}
if (!pris[span-1].pri) {
ast_cli(a->fd, "No PRI running on span %d\n", span);
return CLI_SUCCESS;
}
for (x = 0; x < NUM_DCHANS; x++) {
if (pris[span-1].dchannels[x]) {
#ifdef PRI_DUMP_INFO_STR
char *info_str = NULL;
#endif
ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
ast_cli(a->fd, "Status: %s\n", status);
#ifdef PRI_DUMP_INFO_STR
info_str = pri_dump_info_str(pris[span-1].pri);
if (info_str) {
ast_cli(a->fd, "%s", info_str);
ast_free(info_str);
}
#else
pri_dump_info(pris[span-1].pri);
#endif
ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
}
}
return CLI_SUCCESS;
}
| static char* handle_pri_show_spans | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13918 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli(), build_status(), CLI_GENERATE, CLI_INIT, ast_cli_entry::command, ast_cli_args::fd, pris, status, and ast_cli_entry::usage.
{
int span;
int x;
char status[256];
switch (cmd) {
case CLI_INIT:
e->command = "pri show spans";
e->usage =
"Usage: pri show spans\n"
" Displays PRI Information\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 3)
return CLI_SHOWUSAGE;
for (span = 0; span < NUM_SPANS; span++) {
if (pris[span].pri) {
for (x = 0; x < NUM_DCHANS; x++) {
if (pris[span].dchannels[x]) {
build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
}
}
}
}
return CLI_SUCCESS;
}
| static char* handle_pri_version | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 14048 of file chan_dahdi.c.
References ast_cli(), CLI_GENERATE, CLI_INIT, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
| static char* handle_ss7_block_cic | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15695 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), CLI_GENERATE, CLI_INIT, ast_cli_entry::command, ast_cli_args::fd, linksets, dahdi_pvt::locallyblocked, lock, master, NUM_SPANS, dahdi_ss7::numchans, dahdi_ss7::pvts, pvts, and ast_cli_entry::usage.
{
int linkset, cic;
int blocked = -1, i;
switch (cmd) {
case CLI_INIT:
e->command = "ss7 block cic";
e->usage =
"Usage: ss7 block cic <linkset> <CIC>\n"
" Sends a remote blocking request for the given CIC on the specified linkset\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc == 5)
linkset = atoi(a->argv[3]);
else
return CLI_SHOWUSAGE;
if ((linkset < 1) || (linkset > NUM_SPANS)) {
ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
return CLI_SUCCESS;
}
if (!linksets[linkset-1].ss7) {
ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
return CLI_SUCCESS;
}
cic = atoi(a->argv[4]);
if (cic < 1) {
ast_cli(a->fd, "Invalid CIC specified!\n");
return CLI_SUCCESS;
}
for (i = 0; i < linksets[linkset-1].numchans; i++) {
if (linksets[linkset-1].pvts[i]->cic == cic) {
blocked = linksets[linkset-1].pvts[i]->locallyblocked;
if (!blocked) {
ast_mutex_lock(&linksets[linkset-1].lock);
isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
ast_mutex_unlock(&linksets[linkset-1].lock);
}
}
}
if (blocked < 0) {
ast_cli(a->fd, "Invalid CIC specified!\n");
return CLI_SUCCESS;
}
if (!blocked)
ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
else
ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
/* Break poll on the linkset so it sends our messages */
pthread_kill(linksets[linkset-1].master, SIGURG);
return CLI_SUCCESS;
}
| static char* handle_ss7_block_linkset | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15760 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::cic, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, ast_cli_args::fd, linksets, lock, master, NUM_SPANS, dahdi_ss7::numchans, pvts, dahdi_ss7::pvts, and ast_cli_entry::usage.
{
int linkset;
int i;
switch (cmd) {
case CLI_INIT:
e->command = "ss7 block linkset";
e->usage =
"Usage: ss7 block linkset <linkset number>\n"
" Sends a remote blocking request for all CICs on the given linkset\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc == 4)
linkset = atoi(a->argv[3]);
else
return CLI_SHOWUSAGE;
if ((linkset < 1) || (linkset > NUM_SPANS)) {
ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
return CLI_SUCCESS;
}
if (!linksets[linkset-1].ss7) {
ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
return CLI_SUCCESS;
}
for (i = 0; i < linksets[linkset-1].numchans; i++) {
ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
ast_mutex_lock(&linksets[linkset-1].lock);
isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
ast_mutex_unlock(&linksets[linkset-1].lock);
}
/* Break poll on the linkset so it sends our messages */
pthread_kill(linksets[linkset-1].master, SIGURG);
return CLI_SUCCESS;
}
| static char* handle_ss7_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15656 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, ast_cli_entry::command, ast_cli_args::fd, linksets, NUM_SPANS, and ast_cli_entry::usage.
{
int span;
switch (cmd) {
case CLI_INIT:
e->command = "ss7 set debug {on|off} linkset";
e->usage =
"Usage: ss7 set debug {on|off} linkset <linkset>\n"
" Enables debugging on a given SS7 linkset\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc < 6)
return CLI_SHOWUSAGE;
span = atoi(a->argv[5]);
if ((span < 1) || (span > NUM_SPANS)) {
ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
return CLI_SUCCESS;
}
if (!linksets[span-1].ss7) {
ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
return CLI_SUCCESS;
}
if (linksets[span-1].ss7) {
if (!strcasecmp(a->argv[3], "on")) {
ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
} else {
ss7_set_debug(linksets[span-1].ss7, 0);
ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
}
}
return CLI_SUCCESS;
}
| static char* handle_ss7_show_linkset | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15908 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, ast_cli_entry::command, ast_cli_args::fd, dahdi_ss7::LINKSET_STATE_UP, linksets, NUM_SPANS, dahdi_ss7::ss7, dahdi_ss7::state, and ast_cli_entry::usage.
{
int linkset;
struct dahdi_ss7 *ss7;
switch (cmd) {
case CLI_INIT:
e->command = "ss7 show linkset";
e->usage =
"Usage: ss7 show linkset <span>\n"
" Shows the status of an SS7 linkset.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc < 4)
return CLI_SHOWUSAGE;
linkset = atoi(a->argv[3]);
if ((linkset < 1) || (linkset > NUM_SPANS)) {
ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
return CLI_SUCCESS;
}
if (!linksets[linkset-1].ss7) {
ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
return CLI_SUCCESS;
}
if (linksets[linkset-1].ss7)
ss7 = &linksets[linkset-1];
ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
return CLI_SUCCESS;
}
| static char* handle_ss7_unblock_cic | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15804 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), CLI_GENERATE, CLI_INIT, ast_cli_entry::command, ast_cli_args::fd, linksets, dahdi_pvt::locallyblocked, lock, master, NUM_SPANS, dahdi_ss7::numchans, dahdi_ss7::pvts, pvts, and ast_cli_entry::usage.
{
int linkset, cic;
int i, blocked = -1;
switch (cmd) {
case CLI_INIT:
e->command = "ss7 unblock cic";
e->usage =
"Usage: ss7 unblock cic <linkset> <CIC>\n"
" Sends a remote unblocking request for the given CIC on the specified linkset\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc == 5)
linkset = atoi(a->argv[3]);
else
return CLI_SHOWUSAGE;
if ((linkset < 1) || (linkset > NUM_SPANS)) {
ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
return CLI_SUCCESS;
}
if (!linksets[linkset-1].ss7) {
ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
return CLI_SUCCESS;
}
cic = atoi(a->argv[4]);
if (cic < 1) {
ast_cli(a->fd, "Invalid CIC specified!\n");
return CLI_SUCCESS;
}
for (i = 0; i < linksets[linkset-1].numchans; i++) {
if (linksets[linkset-1].pvts[i]->cic == cic) {
blocked = linksets[linkset-1].pvts[i]->locallyblocked;
if (blocked) {
ast_mutex_lock(&linksets[linkset-1].lock);
isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
ast_mutex_unlock(&linksets[linkset-1].lock);
}
}
}
if (blocked > 0)
ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
/* Break poll on the linkset so it sends our messages */
pthread_kill(linksets[linkset-1].master, SIGURG);
return CLI_SUCCESS;
}
| static char* handle_ss7_unblock_linkset | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15863 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::cic, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, ast_cli_args::fd, linksets, lock, master, NUM_SPANS, dahdi_ss7::numchans, pvts, dahdi_ss7::pvts, and ast_cli_entry::usage.
{
int linkset;
int i;
switch (cmd) {
case CLI_INIT:
e->command = "ss7 unblock linkset";
e->usage =
"Usage: ss7 unblock linkset <linkset number>\n"
" Sends a remote unblocking request for all CICs on the specified linkset\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc == 4)
linkset = atoi(a->argv[3]);
else
return CLI_SHOWUSAGE;
if ((linkset < 1) || (linkset > NUM_SPANS)) {
ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
return CLI_SUCCESS;
}
if (!linksets[linkset-1].ss7) {
ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
return CLI_SUCCESS;
}
for (i = 0; i < linksets[linkset-1].numchans; i++) {
ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
ast_mutex_lock(&linksets[linkset-1].lock);
isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
ast_mutex_unlock(&linksets[linkset-1].lock);
}
/* Break poll on the linkset so it sends our messages */
pthread_kill(linksets[linkset-1].master, SIGURG);
return CLI_SUCCESS;
}
| static char* handle_ss7_version | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15944 of file chan_dahdi.c.
References ast_cli(), CLI_GENERATE, CLI_INIT, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
| static int has_voicemail | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3003 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_monitor(), handle_init_event(), and mwi_send_init().
{
int new_msgs;
struct ast_event *event;
char *mailbox, *context;
mailbox = context = ast_strdupa(p->mailbox);
strsep(&context, "@");
if (ast_strlen_zero(context))
context = "default";
event = ast_event_get_cached(AST_EVENT_MWI,
AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
AST_EVENT_IE_END);
if (event) {
new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
ast_event_destroy(event);
} else
new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
return new_msgs;
}
| static int isourconf | ( | struct dahdi_pvt * | p, | |
| struct dahdi_subchannel * | c | |||
| ) | [static] |
Definition at line 2518 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::confno, and dahdi_subchannel::curconf.
Referenced by conf_del().
{
/* If they're listening to our channel, they're ours */
if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
return 1;
/* If they're a talker on our (allocated) conference, they're ours */
if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
return 1;
return 0;
}
Definition at line 2548 of file chan_dahdi.c.
References dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, dahdi_pvt::law, dahdi_pvt::slaves, and dahdi_pvt::subs.
Referenced by update_conf().
{
int x;
int useslavenative;
struct dahdi_pvt *slave = NULL;
/* Start out optimistic */
useslavenative = 1;
/* Update conference state in a stateless fashion */
for (x = 0; x < 3; x++) {
/* Any three-way calling makes slave native mode *definitely* out
of the question */
if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
useslavenative = 0;
}
/* If we don't have any 3-way calls, check to see if we have
precisely one slave */
if (useslavenative) {
for (x = 0; x < MAX_SLAVES; x++) {
if (p->slaves[x]) {
if (slave) {
/* Whoops already have a slave! No
slave native and stop right away */
slave = NULL;
useslavenative = 0;
break;
} else {
/* We have one slave so far */
slave = p->slaves[x];
}
}
}
}
/* If no slave, slave native definitely out */
if (!slave)
useslavenative = 0;
else if (slave->law != p->law) {
useslavenative = 0;
slave = NULL;
}
if (out)
*out = slave;
return useslavenative;
}
| static int linkset_addsigchan | ( | int | sigchan | ) | [static] |
Definition at line 15533 of file chan_dahdi.c.
References ast_log(), dahdi_close_ss7_fd(), errno, LINKSTATE_DOWN, LOG_ERROR, NUM_DCHANS, NUM_SPANS, and ss7_resolve_linkset().
Referenced by process_dahdi().
{
struct dahdi_ss7 *link;
int res;
int curfd;
struct dahdi_params p;
struct dahdi_bufferinfo bi;
struct dahdi_spaninfo si;
link = ss7_resolve_linkset(cur_linkset);
if (!link) {
ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
return -1;
}
if (cur_ss7type < 0) {
ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
return -1;
}
if (!link->ss7)
link->ss7 = ss7_new(cur_ss7type);
if (!link->ss7) {
ast_log(LOG_ERROR, "Can't create new SS7!\n");
return -1;
}
link->type = cur_ss7type;
if (cur_pointcode < 0) {
ast_log(LOG_ERROR, "Unspecified pointcode!\n");
return -1;
} else
ss7_set_pc(link->ss7, cur_pointcode);
if (sigchan < 0) {
ast_log(LOG_ERROR, "Invalid sigchan!\n");
return -1;
} else {
if (link->numsigchans >= NUM_DCHANS) {
ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
return -1;
}
curfd = link->numsigchans;
link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
return -1;
}
memset(&p, 0, sizeof(p));
res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
if (res) {
dahdi_close_ss7_fd(link, curfd);
ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
return -1;
}
if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
dahdi_close_ss7_fd(link, curfd);
ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
return -1;
}
memset(&bi, 0, sizeof(bi));
bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
bi.numbufs = 32;
bi.bufsize = 512;
if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
dahdi_close_ss7_fd(link, curfd);
return -1;
}
if (p.sigtype == DAHDI_SIG_MTP2)
ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
else
ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
link->numsigchans++;
memset(&si, 0, sizeof(si));
res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
if (res) {
dahdi_close_ss7_fd(link, curfd);
ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
}
if (!si.alarms) {
link->linkstate[curfd] = LINKSTATE_DOWN;
ss7_link_noalarm(link->ss7, link->fds[curfd]);
} else {
link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
ss7_link_alarm(link->ss7, link->fds[curfd]);
}
}
if (cur_adjpointcode < 0) {
ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
return -1;
} else {
ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
}
if (cur_defaultdpc < 0) {
ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
return -1;
}
if (cur_networkindicator < 0) {
ast_log(LOG_ERROR, "Invalid networkindicator!\n");
return -1;
} else
ss7_set_network_ind(link->ss7, cur_networkindicator);
return 0;
}
| static int load_module | ( | void | ) | [static] |
Definition at line 17409 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_mutex_init(), ast_register_application_xml, ast_string_field_init, ast_string_field_set, dahdi_pri_error(), dahdi_pri_message(), dahdi_send_keypad_facility_exec(), dahdi_ss7_error(), dahdi_ss7_message(), inuse, linksets, lock, LOG_ERROR, dahdi_ss7::master, dahdi_pri::master, name, dahdi_pri::offset, pris, and setup_dahdi().
{
int res;
#if defined(HAVE_PRI) || defined(HAVE_SS7)
int y, i;
#endif
#ifdef HAVE_PRI
memset(pris, 0, sizeof(pris));
for (y = 0; y < NUM_SPANS; y++) {
ast_mutex_init(&pris[y].lock);
pris[y].offset = -1;
pris[y].master = AST_PTHREADT_NULL;
for (i = 0; i < NUM_DCHANS; i++)
pris[y].fds[i] = -1;
}
pri_set_error(dahdi_pri_error);
pri_set_message(dahdi_pri_message);
ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
#ifdef HAVE_PRI_PROG_W_CAUSE
ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
#endif
#endif
#ifdef HAVE_SS7
memset(linksets, 0, sizeof(linksets));
for (y = 0; y < NUM_SPANS; y++) {
ast_mutex_init(&linksets[y].lock);
linksets[y].master = AST_PTHREADT_NULL;
for (i = 0; i < NUM_DCHANS; i++)
linksets[y].fds[i] = -1;
}
ss7_set_error(dahdi_ss7_error);
ss7_set_message(dahdi_ss7_message);
#endif /* HAVE_SS7 */
res = setup_dahdi(0);
/* Make sure we can register our DAHDI channel type */
if (res)
return AST_MODULE_LOAD_DECLINE;
if (ast_channel_register(&dahdi_tech)) {
ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
__unload_module();
return AST_MODULE_LOAD_FAILURE;
}
#ifdef HAVE_PRI
ast_string_field_init(&inuse, 16);
ast_string_field_set(&inuse, name, "GR-303InUse");
ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
#endif
#ifdef HAVE_SS7
ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
#endif
#ifdef HAVE_OPENR2
ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
#endif
ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
memset(round_robin, 0, sizeof(round_robin));
ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
ast_cond_init(&ss_thread_complete, NULL);
return res;
}
| static struct dahdi_pvt* mkintf | ( | int | channel, | |
| const struct dahdi_chan_conf * | conf, | |||
| struct dahdi_pri * | pri, | |||
| int | reloading | |||
| ) | [static, read] |
Definition at line 10103 of file chan_dahdi.c.
References dahdi_pvt::accountcode, dahdi_pvt::adsi, dahdi_pvt::amaflags, dahdi_pvt::answeronpolarityswitch, ast_calloc, ast_copy_string(), ast_dsp_set_digitmode(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_event_subscribe(), ast_log(), ast_mutex_init(), ast_smdi_interface_find(), ast_strdupa, ast_strlen_zero(), ast_variable_new(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::bufsize, dahdi_pvt::busy_quietlength, dahdi_pvt::busy_tonelength, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::call, dahdi_ss7::called_nai, dahdi_pvt::callgroup, dahdi_ss7::calling_nai, dahdi_pvt::callprogress, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, dahdi_pvt::cancallforward, dahdi_pvt::canpark, dahdi_chan_conf::chan, CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::cic, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_rxgain, CID_SIG_SMDI, dahdi_pvt::cid_signalling, dahdi_pvt::cid_start, dahdi_pvt::cid_ton, dahdi_pvt::confno, context, dahdi_pvt::context, dahdi_pri::crvend, dahdi_pri::crvs, dahdi_open(), dahdi_set_hook(), dahdi_pvt::dahditrcallerid, dahdi_pvt::defcontext, dahdi_pvt::destroy, destroy_dahdi_pvt(), dahdi_subchannel::dfd, dahdi_pri::dialplan, dialplan2str(), dahdi_pri::discardremoteholdretrieval, dahdi_pvt::dpc, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echotraining, errno, dahdi_pri::facilityenable, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, ast_variable::file, dahdi_pvt::firstradio, free, dahdi_pvt::fxsoffhookstate, get_alarms(), dahdi_pvt::group, handle_alarms(), dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::head, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pri::idledial, dahdi_pri::idleext, iflist, dahdi_pvt::immediate, dahdi_pvt::inalarm, dahdi_pri::inbanddisconnect, dahdi_pvt::inservice, dahdi_pri::internationalprefix, dahdi_ss7::internationalprefix, dahdi_chan_conf::is_sig_auto, dahdi_pvt::language, dahdi_pvt::law, dahdi_pri::localdialplan, dahdi_pvt::locallyblocked, dahdi_pri::localprefix, dahdi_pvt::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, dahdi_pvt::logicalspan, mailbox, dahdi_pvt::mailbox, MAX_CHANNELS, dahdi_pri::minidle, dahdi_pri::minunused, dahdi_pvt::mohinterpret, dahdi_pvt::mohsuggest, dahdi_pvt::msgstate, mwi_event_cb(), dahdi_pvt::mwi_event_sub, dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitor_neon, dahdi_pvt::mwimonitor_rpas, ast_variable::name, dahdi_pri::nationalprefix, dahdi_ss7::nationalprefix, ast_variable::next, dahdi_pvt::next, dahdi_pri::nodetype, dahdi_pri::nsf, NUM_SPANS, dahdi_pri::numchans, dahdi_ss7::numchans, dahdi_pvt::onhooktime, dahdi_pvt::outsigmod, dahdi_pri::overlapdial, dahdi_pvt::parkinglot, dahdi_pvt::permcallwaiting, dahdi_pvt::permhidecallerid, dahdi_pvt::pickupgroup, dahdi_pvt::polarityonanswerdelay, dahdi_pvt::prev, dahdi_pvt::pri, dahdi_chan_conf::pri, pri_is_up(), pri_resolve_span(), dahdi_pvt::priexclusive, dahdi_pvt::priindication_oob, dahdi_pri::prilogicalspan, dahdi_pvt::prioffset, pris, dahdi_pri::privateprefix, dahdi_pvt::propconfno, dahdi_pvt::pulse, dahdi_pri::pvts, dahdi_ss7::pvts, dahdi_pri::qsigchannelmapping, dahdi_pvt::radio, distRingData::range, dahdi_pvt::remotelyblocked, dahdi_pri::resetinterval, dahdi_pvt::restrictcid, dahdi_distRings::ringnum, dahdi_pvt::ringt_base, dahdi_pvt::rxgain, dahdi_pvt::sendcalleridafter, set_actual_gain(), dahdi_pri::sig, 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_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, sigtype_to_signalling(), dahdi_pvt::smdi_iface, dahdi_chan_conf::smdi_port, dahdi_pvt::span, dahdi_chan_conf::ss7, dahdi_pvt::ss7, dahdi_ss7::ss7, ss7_resolve_linkset(), dahdi_pvt::ss7call, dahdi_pvt::stripmsd, strsep(), SUB_REAL, dahdi_pvt::subs, dahdi_ss7::subscriberprefix, dahdi_pri::switchtype, dahdi_pvt::threewaycalling, dahdi_chan_conf::timing, dahdi_pvt::tonezone, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, dahdi_pvt::txgain, dahdi_pri::unknownprefix, dahdi_ss7::unknownprefix, update_conf(), dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, dahdi_pvt::use_smdi, dahdi_pvt::usedistinctiveringdetection, dahdi_pvt::usefaxbuffers, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.
Referenced by build_channels(), and process_dahdi().
{
/* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
char fn[80];
struct dahdi_bufferinfo bi;
int res;
int span = 0;
int here = 0;
int x;
struct dahdi_pvt **wlist;
struct dahdi_pvt **wend;
struct dahdi_params p;
wlist = &iflist;
wend = &ifend;
#ifdef HAVE_PRI
if (pri) {
wlist = &pri->crvs;
wend = &pri->crvend;
}
#endif
tmp2 = *wlist;
prev = NULL;
while (tmp2) {
if (!tmp2->destroy) {
if (tmp2->channel == channel) {
tmp = tmp2;
here = 1;
break;
}
if (tmp2->channel > channel) {
break;
}
}
prev = tmp2;
tmp2 = tmp2->next;
}
if (!here && reloading != 1) {
if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
if (tmp)
free(tmp);
return NULL;
}
ast_mutex_init(&tmp->lock);
ifcount++;
for (x = 0; x < 3; x++)
tmp->subs[x].dfd = -1;
tmp->channel = channel;
tmp->priindication_oob = conf->chan.priindication_oob;
}
if (tmp) {
int chan_sig = conf->chan.sig;
if (!here) {
if ((channel != CHAN_PSEUDO) && !pri) {
int count = 0;
snprintf(fn, sizeof(fn), "%d", channel);
/* Open non-blocking */
tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
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 */
usleep(1);
tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
count++;
}
/* Allocate a DAHDI structure */
if (tmp->subs[SUB_REAL].dfd < 0) {
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);
destroy_dahdi_pvt(&tmp);
return NULL;
}
memset(&p, 0, sizeof(p));
res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
if (res < 0) {
ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
destroy_dahdi_pvt(&tmp);
return NULL;
}
if (conf->is_sig_auto)
chan_sig = sigtype_to_signalling(p.sigtype);
if (p.sigtype != (chan_sig & 0x3ffff)) {
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));
destroy_dahdi_pvt(&tmp);
return NULL;
}
tmp->law = p.curlaw;
tmp->span = p.spanno;
span = p.spanno - 1;
} else {
if (channel == CHAN_PSEUDO)
chan_sig = 0;
else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
return NULL;
}
}
tmp->outsigmod = conf->chan.outsigmod;
#ifdef HAVE_SS7
if (chan_sig == SIG_SS7) {
struct dahdi_ss7 *ss7;
int clear = 0;
if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
destroy_dahdi_pvt(&tmp);
return NULL;
}
ss7 = ss7_resolve_linkset(cur_linkset);
if (!ss7) {
ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
destroy_dahdi_pvt(&tmp);
return NULL;
}
if (cur_cicbeginswith < 0) {
ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
destroy_dahdi_pvt(&tmp);
return NULL;
}
tmp->cic = cur_cicbeginswith++;
/* DB: Add CIC's DPC information */
tmp->dpc = cur_defaultdpc;
tmp->ss7 = ss7;
tmp->ss7call = NULL;
ss7->pvts[ss7->numchans++] = tmp;
ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix));
ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix));
ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix));
ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix));
ss7->called_nai = conf->ss7.called_nai;
ss7->calling_nai = conf->ss7.calling_nai;
}
#endif
#ifdef HAVE_OPENR2
if (chan_sig == SIG_MFCR2 && reloading != 1) {
struct dahdi_mfcr2 *r2_link;
r2_link = dahdi_r2_get_link();
if (!r2_link) {
ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
destroy_dahdi_pvt(&tmp);
return NULL;
}
if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
destroy_dahdi_pvt(&tmp);
return NULL;
}
if (r2_link->numchans == (sizeof(r2_link->pvts)/sizeof(r2_link->pvts[0]))) {
ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
destroy_dahdi_pvt(&tmp);
return NULL;
}
r2_link->pvts[r2_link->numchans++] = tmp;
tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
tmp->subs[SUB_REAL].dfd,
NULL, NULL);
if (!tmp->r2chan) {
openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
destroy_dahdi_pvt(&tmp);
return NULL;
}
tmp->mfcr2 = r2_link;
if (conf->mfcr2.call_files) {
openr2_chan_enable_call_files(tmp->r2chan);
}
openr2_chan_set_client_data(tmp->r2chan, tmp);
/* cast seems to be needed to get rid of the annoying warning regarding format attribute */
openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
tmp->mfcr2_category = conf->mfcr2.category;
tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
tmp->mfcr2call = 0;
tmp->mfcr2_dnis_index = 0;
tmp->mfcr2_ani_index = 0;
r2_link->monitored_count++;
}
#endif
#ifdef HAVE_PRI
if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
int offset;
int myswitchtype;
int matchesdchan;
int x,y;
offset = 0;
if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP))
&& ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
destroy_dahdi_pvt(&tmp);
return NULL;
}
if (span >= NUM_SPANS) {
ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
destroy_dahdi_pvt(&tmp);
return NULL;
} else {
struct dahdi_spaninfo si;
si.spanno = 0;
if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
destroy_dahdi_pvt(&tmp);
return NULL;
}
/* Store the logical span first based upon the real span */
tmp->logicalspan = pris[span].prilogicalspan;
pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
if (span < 0) {
ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
destroy_dahdi_pvt(&tmp);
return NULL;
}
if ((chan_sig == SIG_PRI) ||
(chan_sig == SIG_BRI) ||
(chan_sig == SIG_BRI_PTMP))
myswitchtype = conf->pri.switchtype;
else
myswitchtype = PRI_SWITCH_GR303_TMC;
/* Make sure this isn't a d-channel */
matchesdchan=0;
for (x = 0; x < NUM_SPANS; x++) {
for (y = 0; y < NUM_DCHANS; y++) {
if (pris[x].dchannels[y] == tmp->channel) {
matchesdchan = 1;
break;
}
}
}
offset = p.chanpos;
if (!matchesdchan) {
if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
destroy_dahdi_pvt(&tmp);
return NULL;
}
if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
destroy_dahdi_pvt(&tmp);
return NULL;
}
if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
destroy_dahdi_pvt(&tmp);
return NULL;
}
if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
destroy_dahdi_pvt(&tmp);
return NULL;
}
if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
destroy_dahdi_pvt(&tmp);
return NULL;
}
if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
destroy_dahdi_pvt(&tmp);
return NULL;
}
if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
destroy_dahdi_pvt(&tmp);
return NULL;
}
if (pris[span].numchans >= MAX_CHANNELS) {
ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
pris[span].trunkgroup);
destroy_dahdi_pvt(&tmp);
return NULL;
}
pris[span].sig = chan_sig;
pris[span].nodetype = conf->pri.nodetype;
pris[span].switchtype = myswitchtype;
pris[span].nsf = conf->pri.nsf;
pris[span].dialplan = conf->pri.dialplan;
pris[span].localdialplan = conf->pri.localdialplan;
pris[span].pvts[pris[span].numchans++] = tmp;
pris[span].minunused = conf->pri.minunused;
pris[span].minidle = conf->pri.minidle;
pris[span].overlapdial = conf->pri.overlapdial;
pris[span].qsigchannelmapping = conf->pri.qsigchannelmapping;
pris[span].discardremoteholdretrieval = conf->pri.discardremoteholdretrieval;
#ifdef HAVE_PRI_INBANDDISCONNECT
pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
#endif
pris[span].facilityenable = conf->pri.facilityenable;
ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
pris[span].resetinterval = conf->pri.resetinterval;
tmp->pri = &pris[span];
tmp->prioffset = offset;
tmp->call = NULL;
tmp->priexclusive = conf->chan.priexclusive;
} else {
ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
destroy_dahdi_pvt(&tmp);
return NULL;
}
}
} else {
tmp->prioffset = 0;
}
#endif
} else {
chan_sig = tmp->sig;
if (tmp->subs[SUB_REAL].dfd > -1) {
memset(&p, 0, sizeof(p));
res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
}
}
/* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
switch (chan_sig) {
case SIG_FXSKS:
case SIG_FXSLS:
case SIG_EM:
case SIG_EM_E1:
case SIG_EMWINK:
case SIG_FEATD:
case SIG_FEATDMF:
case SIG_FEATDMF_TA:
case SIG_FEATB:
case SIG_E911:
case SIG_SF:
case SIG_SFWINK:
case SIG_FGC_CAMA:
case SIG_FGC_CAMAMF:
case SIG_SF_FEATD:
case SIG_SF_FEATDMF:
case SIG_SF_FEATB:
p.starttime = 250;
break;
}
if (tmp->radio) {
/* XXX Waiting to hear back from Jim if these should be adjustable XXX */
p.channo = channel;
p.rxwinktime = 1;
p.rxflashtime = 1;
p.starttime = 1;
p.debouncetime = 5;
}
if (!tmp->radio) {
p.channo = channel;
/* Override timing settings based on config file */
if (conf->timing.prewinktime >= 0)
p.prewinktime = conf->timing.prewinktime;
if (conf->timing.preflashtime >= 0)
p.preflashtime = conf->timing.preflashtime;
if (conf->timing.winktime >= 0)
p.winktime = conf->timing.winktime;
if (conf->timing.flashtime >= 0)
p.flashtime = conf->timing.flashtime;
if (conf->timing.starttime >= 0)
p.starttime = conf->timing.starttime;
if (conf->timing.rxwinktime >= 0)
p.rxwinktime = conf->timing.rxwinktime;
if (conf->timing.rxflashtime >= 0)
p.rxflashtime = conf->timing.rxflashtime;
if (conf->timing.debouncetime >= 0)
p.debouncetime = conf->timing.debouncetime;
}
/* dont set parms on a pseudo-channel (or CRV) */
if (tmp->subs[SUB_REAL].dfd >= 0)
{
res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
if (res < 0) {
ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
destroy_dahdi_pvt(&tmp);
return NULL;
}
}
#if 1
if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
memset(&bi, 0, sizeof(bi));
res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
if (!res) {
bi.txbufpolicy = conf->chan.buf_policy;
bi.rxbufpolicy = conf->chan.buf_policy;
bi.numbufs = conf->chan.buf_no;
res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
}
} else {
ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
}
tmp->buf_policy = conf->chan.buf_policy;
tmp->buf_no = conf->chan.buf_no;
tmp->usefaxbuffers = conf->chan.usefaxbuffers;
tmp->faxbuf_policy = conf->chan.faxbuf_policy;
tmp->faxbuf_no = conf->chan.faxbuf_no;
/* This is not as gnarly as it may first appear. If the ioctl above failed, we'd be setting
* tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
* The reason the ioctl call above failed should to be determined before worrying about the
* faxbuffer-related ioctl calls */
tmp->bufsize = bi.bufsize;
}
#endif
tmp->immediate = conf->chan.immediate;
tmp->transfertobusy = conf->chan.transfertobusy;
if (chan_sig & __DAHDI_SIG_FXS) {
tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
}
tmp->sig = chan_sig;
tmp->ringt_base = ringt_base;
tmp->firstradio = 0;
if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
tmp->permcallwaiting = conf->chan.callwaiting;
else
tmp->permcallwaiting = 0;
/* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
tmp->destroy = 0;
tmp->drings = conf->chan.drings;
/* 10 is a nice default. */
if (tmp->drings.ringnum[0].range == 0)
tmp->drings.ringnum[0].range = 10;
if (tmp->drings.ringnum[1].range == 0)
tmp->drings.ringnum[1].range = 10;
if (tmp->drings.ringnum[2].range == 0)
tmp->drings.ringnum[2].range = 10;
tmp->usedistinctiveringdetection = usedistinctiveringdetection;
tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
tmp->threewaycalling = conf->chan.threewaycalling;
tmp->adsi = conf->chan.adsi;
tmp->use_smdi = conf->chan.use_smdi;
tmp->permhidecallerid = conf->chan.hidecallerid;
tmp->hidecalleridname = conf->chan.hidecalleridname;
tmp->callreturn = conf->chan.callreturn;
tmp->echocancel = conf->chan.echocancel;
tmp->echotraining = conf->chan.echotraining;
tmp->pulse = conf->chan.pulse;
if (tmp->echocancel.head.tap_length) {
tmp->echocanbridged = conf->chan.echocanbridged;
} else {
if (conf->chan.echocanbridged)
ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
tmp->echocanbridged = 0;
}
tmp->busydetect = conf->chan.busydetect;
tmp->busycount = conf->chan.busycount;
tmp->busy_tonelength = conf->chan.busy_tonelength;
tmp->busy_quietlength = conf->chan.busy_quietlength;
tmp->callprogress = conf->chan.callprogress;
tmp->waitfordialtone = conf->chan.waitfordialtone;
tmp->cancallforward = conf->chan.cancallforward;
tmp->dtmfrelax = conf->chan.dtmfrelax;
tmp->callwaiting = tmp->permcallwaiting;
tmp->hidecallerid = tmp->permhidecallerid;
tmp->channel = channel;
tmp->stripmsd = conf->chan.stripmsd;
tmp->use_callerid = conf->chan.use_callerid;
tmp->cid_signalling = conf->chan.cid_signalling;
tmp->cid_start = conf->chan.cid_start;
tmp->dahditrcallerid = conf->chan.dahditrcallerid;
tmp->restrictcid = conf->chan.restrictcid;
tmp->use_callingpres = conf->chan.use_callingpres;
if (tmp->usedistinctiveringdetection) {
if (!tmp->use_callerid) {
ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
tmp->use_callerid = 1;
}
}
if (tmp->cid_signalling == CID_SIG_SMDI) {
if (!tmp->use_smdi) {
ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
tmp->use_smdi = 1;
}
}
if (tmp->use_smdi) {
tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
if (!(tmp->smdi_iface)) {
ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
tmp->use_smdi = 0;
}
}
ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
tmp->amaflags = conf->chan.amaflags;
if (!here) {
tmp->confno = -1;
tmp->propconfno = -1;
}
tmp->canpark = conf->chan.canpark;
tmp->transfer = conf->chan.transfer;
ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
tmp->cid_ton = 0;
switch (tmp->sig) {
case SIG_PRI:
case SIG_BRI:
case SIG_BRI_PTMP:
case SIG_SS7:
case SIG_MFCR2:
tmp->cid_num[0] = '\0';
tmp->cid_name[0] = '\0';
break;
default:
ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
break;
}
ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
char *mailbox, *context;
mailbox = context = ast_strdupa(tmp->mailbox);
strsep(&context, "@");
if (ast_strlen_zero(context))
context = "default";
tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
AST_EVENT_IE_END);
}
tmp->msgstate = -1;
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
tmp->mwisend_setting = conf->chan.mwisend_setting;
tmp->mwisend_fsk = conf->chan.mwisend_fsk;
tmp->mwisend_rpas = conf->chan.mwisend_rpas;
#endif
if (chan_sig & __DAHDI_SIG_FXO) {
memset(&p, 0, sizeof(p));
res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
if (!res) {
tmp->fxsoffhookstate = p.rxisoffhook;
}
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
#endif
}
tmp->onhooktime = time(NULL);
tmp->group = conf->chan.group;
tmp->callgroup = conf->chan.callgroup;
tmp->pickupgroup= conf->chan.pickupgroup;
if (conf->chan.vars) {
struct ast_variable *v, *tmpvar;
for (v = conf->chan.vars ; v ; v = v->next) {
if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
tmpvar->next = tmp->vars;
tmp->vars = tmpvar;
}
}
}
tmp->cid_rxgain = conf->chan.cid_rxgain;
tmp->rxgain = conf->chan.rxgain;
tmp->txgain = conf->chan.txgain;
tmp->tonezone = conf->chan.tonezone;
if (tmp->subs[SUB_REAL].dfd > -1) {
set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
if (tmp->dsp)
ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
update_conf(tmp);
if (!here) {
if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI)
&& (chan_sig != SIG_SS7) && (chan_sig != SIG_MFCR2))
/* Hang it up to be sure it's good */
dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
}
ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
#ifdef HAVE_PRI
/* the dchannel is down so put the channel in alarm */
if (tmp->pri && !pri_is_up(tmp->pri))
tmp->inalarm = 1;
#endif
if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
tmp->inalarm = 1;
handle_alarms(tmp, res);
}
}
tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
tmp->sendcalleridafter = conf->chan.sendcalleridafter;
if (!here) {
tmp->locallyblocked = tmp->remotelyblocked = 0;
if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
tmp->inservice = 0;
else /* We default to in service on protocols that don't have a reset */
tmp->inservice = 1;
}
}
if (tmp && !here) {
/* nothing on the iflist */
if (!*wlist) {
*wlist = tmp;
tmp->prev = NULL;
tmp->next = NULL;
*wend = tmp;
} else {
/* at least one member on the iflist */
struct dahdi_pvt *working = *wlist;
/* check if we maybe have to put it on the begining */
if (working->channel > tmp->channel) {
tmp->next = *wlist;
tmp->prev = NULL;
(*wlist)->prev = tmp;
*wlist = tmp;
} else {
/* go through all the members and put the member in the right place */
while (working) {
/* in the middle */
if (working->next) {
if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
tmp->next = working->next;
tmp->prev = working;
working->next->prev = tmp;
working->next = tmp;
break;
}
} else {
/* the last */
if (working->channel < tmp->channel) {
working->next = tmp;
tmp->next = NULL;
tmp->prev = working;
*wend = tmp;
break;
}
}
working = working->next;
}
}
}
}
return tmp;
}
| static void mwi_event_cb | ( | const struct ast_event * | event, | |
| void * | userdata | |||
| ) | [static] |
Definition at line 367 of file chan_dahdi.c.
Referenced by mkintf().
{
/* This module does not handle MWI in an event-based manner. However, it
* subscribes to MWI for each mailbox that is configured so that the core
* knows that we care about it. Then, chan_dahdi will get the MWI from the
* event cache instead of checking the mailbox directly. */
}
| static int mwi_send_init | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 9176 of file chan_dahdi.c.
References ast_calloc, ast_free, AST_LAW, ast_log(), CID_MWI_TYPE_MDMF_FULL, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_subchannel::dfd, has_voicemail(), LOG_WARNING, MAX_CALLERID_SIZE, mwisend_info::mwisend_current, dahdi_pvt::mwisend_data, dahdi_pvt::mwisendactive, SUB_REAL, dahdi_pvt::subs, and vmwi_generate().
Referenced by do_monitor().
{
int x, res;
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
/* Determine how this spill is to be sent */
if (pvt->mwisend_rpas) {
pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
pvt->mwisendactive = 1;
} else if (pvt->mwisend_fsk) {
pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
pvt->mwisendactive = 1;
} else {
pvt->mwisendactive = 0;
return 0;
}
#else
if (mwisend_rpas) {
pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
} else {
pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
}
pvt->mwisendactive = 1;
#endif
if (pvt->cidspill) {
ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
ast_free(pvt->cidspill);
pvt->cidspill = NULL;
pvt->cidpos = 0;
pvt->cidlen = 0;
}
pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
if (!pvt->cidspill) {
pvt->mwisendactive = 0;
return -1;
}
x = DAHDI_FLUSH_BOTH;
res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
x = 3000;
ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
if (pvt->mwisend_fsk) {
#endif
pvt->cidlen = vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
pvt->cidpos = 0;
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
}
#endif
return 0;
}
| static int mwi_send_process_buffer | ( | struct dahdi_pvt * | pvt, | |
| int | num_read | |||
| ) | [static] |
Definition at line 9229 of file chan_dahdi.c.
References ast_free, ast_log(), dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_set_hook(), dahdi_subchannel::dfd, errno, LOG_WARNING, MWI_SEND_CLEANUP, MWI_SEND_DONE, MWI_SEND_PAUSE, MWI_SEND_SA, MWI_SEND_SA_WAIT, MWI_SEND_SPILL, mwisend_info::mwisend_current, dahdi_pvt::mwisend_data, dahdi_pvt::mwisendactive, mwisend_info::pause, quit, SUB_REAL, and dahdi_pvt::subs.
Referenced by do_monitor().
{
struct timeval now;
int res;
/* sanity check to catch if this had been interrupted previously
* i.e. state says there is more to do but there is no spill allocated
*/
if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
} else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
/* Normal processing -- Perform mwi send action */
switch ( pvt->mwisend_data.mwisend_current) {
case MWI_SEND_SA:
/* Send the Ring Pulse Signal Alert */
res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
if (res) {
ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
goto quit;
}
res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
break;
case MWI_SEND_SA_WAIT: /* do nothing until I get RINGEROFF event */
break;
case MWI_SEND_PAUSE: /* Wait between alert and spill - min of 500 mS*/
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
if (pvt->mwisend_fsk) {
#endif
gettimeofday(&now, NULL);
if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
}
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
} else { /* support for mwisendtype=nofsk */
pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
}
#endif
break;
case MWI_SEND_SPILL:
/* We read some number of bytes. Write an equal amount of data */
if(0 < num_read) {
if (num_read > pvt->cidlen - pvt->cidpos)
num_read = pvt->cidlen - pvt->cidpos;
res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
if (res > 0) {
pvt->cidpos += res;
if (pvt->cidpos >= pvt->cidlen) {
pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
}
} else {
ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
goto quit;
}
}
break;
case MWI_SEND_CLEANUP:
/* For now, do nothing */
pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
break;
default:
/* Should not get here, punt*/
goto quit;
}
}
if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
if (pvt->cidspill) {
ast_free(pvt->cidspill);
pvt->cidspill = NULL;
pvt->cidpos = 0;
pvt->cidlen = 0;
}
pvt->mwisendactive = 0;
}
return 0;
quit:
if (pvt->cidspill) {
ast_free(pvt->cidspill);
pvt->cidspill = NULL;
pvt->cidpos = 0;
pvt->cidlen = 0;
}
pvt->mwisendactive = 0;
return -1;
}
| static int mwi_send_process_event | ( | struct dahdi_pvt * | pvt, | |
| int | event | |||
| ) | [static] |
Definition at line 9316 of file chan_dahdi.c.
References ast_free, ast_log(), dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_set_hook(), dahdi_subchannel::dfd, errno, LOG_WARNING, MWI_SEND_DONE, MWI_SEND_SA_WAIT, mwisend_info::mwisend_current, dahdi_pvt::mwisend_data, dahdi_pvt::mwisendactive, mwisend_info::pause, SUB_REAL, and dahdi_pvt::subs.
Referenced by do_monitor().
{
int handled = 0;
if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
switch (event) {
case DAHDI_EVENT_RINGEROFF:
if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
handled = 1;
if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s mwi send aborted\n", strerror(errno));
if(pvt->cidspill) {
ast_free(pvt->cidspill);
pvt->cidspill = NULL;
}
pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
pvt->mwisendactive = 0;
} else {
pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
gettimeofday(&pvt->mwisend_data.pause, NULL);
}
}
break;
/* Going off hook, I need to punt this spill */
case DAHDI_EVENT_RINGOFFHOOK:
if (pvt->cidspill) {
ast_free(pvt->cidspill);
pvt->cidspill = NULL;
pvt->cidpos = 0;
pvt->cidlen = 0;
}
pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
pvt->mwisendactive = 0;
break;
case DAHDI_EVENT_RINGERON:
case DAHDI_EVENT_HOOKCOMPLETE:
break;
default:
break;
}
}
return handled;
}
| static void* mwi_thread | ( | void * | data | ) | [static] |
Definition at line 9034 of file chan_dahdi.c.
References ast_free, 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_get(), callerid_new(), dahdi_pvt::channel, CID_MSGWAITING, CID_NOMSGWAITING, dahdi_pvt::cid_signalling, dahdi_get_event(), dahdi_new(), dahdi_subchannel::dfd, errno, event2str(), EVENT_FLAG_SYSTEM, callerid_state::flags, get_alarms(), handle_alarms(), dahdi_pvt::inalarm, mwi_thread_data::len, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, manager_event, dahdi_pvt::mwimonitoractive, name, notify_message(), mwi_thread_data::pvt, quit, restore_gains(), dahdi_pvt::ringt, dahdi_pvt::ringt_base, ss_thread(), SUB_REAL, and dahdi_pvt::subs.
Referenced by do_monitor().
{
struct mwi_thread_data *mtd = data;
struct callerid_state *cs;
pthread_t threadid;
int samples = 0;
char *name, *number;
int flags;
int i, res;
unsigned int spill_done = 0;
int spill_result = -1;
if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
mtd->pvt->mwimonitoractive = 0;
return NULL;
}
callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
bump_gains(mtd->pvt);
for (;;) {
i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
goto quit;
}
if (i & DAHDI_IOMUX_SIGEVENT) {
struct ast_channel *chan;
/* If we get an event, screen out events that we do not act on.
* Otherwise, cancel and go to the simple switch to let it deal with it.
*/
res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
switch (res) {
case DAHDI_EVENT_NEONMWI_ACTIVE:
case DAHDI_EVENT_NEONMWI_INACTIVE:
case DAHDI_EVENT_NONE:
case DAHDI_EVENT_BITSCHANGED:
break;
case DAHDI_EVENT_NOALARM:
mtd->pvt->inalarm = 0;
ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel);
manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
"Channel: %d\r\n", mtd->pvt->channel);
break;
case DAHDI_EVENT_ALARM:
mtd->pvt->inalarm = 1;
res = get_alarms(mtd->pvt);
handle_alarms(mtd->pvt, res);
break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
default:
ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to ss_thread\n", res, event2str(res));
callerid_free(cs);
restore_gains(mtd->pvt);
mtd->pvt->ringt = mtd->pvt->ringt_base;
if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
if (res < 0)
ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
ast_hangup(chan);
goto quit;
}
goto quit_no_clean;
} else {
ast_log(LOG_WARNING, "Could not create channel to handle call\n");
}
}
} else if (i & DAHDI_IOMUX_READ) {
if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
if (errno != ELAST) {
ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
goto quit;
}
break;
}
samples += res;
if (!spill_done) {
if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
/*
* The previous diagnostic message output likely
* explains why it failed.
*/
ast_log(LOG_WARNING, "Failed to decode CallerID\n");
break;
} else if (spill_result) {
spill_done = 1;
}
} else {
/* keep reading data until the energy level drops below the threshold
so we don't get another 'trigger' on the remaining carrier signal
*/
if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
break;
}
if (samples > (8000 * 4)) /*Termination case - time to give up*/
break;
}
}
if (spill_result == 1) {
callerid_get(cs, &name, &number, &flags);
if (flags & CID_MSGWAITING) {
ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
notify_message(mtd->pvt->mailbox, 1);
} else if (flags & CID_NOMSGWAITING) {
ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
notify_message(mtd->pvt->mailbox, 0);
} else {
ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
}
}
quit:
callerid_free(cs);
restore_gains(mtd->pvt);
quit_no_clean:
mtd->pvt->mwimonitoractive = 0;
ast_free(mtd);
return NULL;
}
| static int my_dahdi_write | ( | struct dahdi_pvt * | p, | |
| unsigned char * | buf, | |||
| int | len, | |||
| int | idx, | |||
| int | linear | |||
| ) | [static] |
Definition at line 7154 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().
{
int sent=0;
int size;
int res;
int fd;
fd = p->subs[idx].dfd;
while (len) {
size = len;
if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
size = (linear ? READ_SIZE * 2 : READ_SIZE);
res = write(fd, buf, size);
if (res != size) {
ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
return sent;
}
len -= size;
buf += size;
}
return sent;
}
| static int my_getsigstr | ( | struct ast_channel * | chan, | |
| char * | str, | |||
| const char * | term, | |||
| int | ms | |||
| ) | [static] |
Definition at line 7702 of file chan_dahdi.c.
References ast_waitfordigit().
Referenced by ss_thread().
{
char c;
*str = 0; /* start with empty output buffer */
for (;;)
{
/* Wait for the first digit (up to specified ms). */
c = ast_waitfordigit(chan, ms);
/* if timeout, hangup or error, return as such */
if (c < 1)
return c;
*str++ = c;
*str = 0;
if (strchr(term, c))
return 1;
}
}
| static void notify_message | ( | char * | mailbox_full, | |
| int | thereornot | |||
| ) | [static] |
Send MWI state change.
This function does two things:
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 2942 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(), mwi_thread(), and ss_thread().
{
char s[sizeof(mwimonitornotify) + 80];
struct ast_event *event;
char *mailbox, *context;
/* Strip off @default */
context = mailbox = ast_strdupa(mailbox_full);
strsep(&context, "@");
if (ast_strlen_zero(context))
context = "default";
if (!(event = ast_event_new(AST_EVENT_MWI,
AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
AST_EVENT_IE_END))) {
return;
}
ast_event_queue_and_cache(event);
if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
ast_safe_system(s);
}
}
| static int parse_buffers_policy | ( | const char * | parse, | |
| int * | num_buffers, | |||
| int * | policy | |||
| ) | [static] |
Definition at line 5065 of file chan_dahdi.c.
References ast_log(), and LOG_WARNING.
Referenced by dahdi_func_write(), and process_dahdi().
{
int res;
char policy_str[21] = "";
if (((res = sscanf(parse, "%d,%20s", num_buffers, policy_str)) != 2) &&
((res = sscanf(parse, "%d|%20s", num_buffers, policy_str)) != 2)) {
ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
return 1;
}
if (*num_buffers < 0) {
ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
return -1;
}
if (!strcasecmp(policy_str, "full")) {
*policy = DAHDI_POLICY_WHEN_FULL;
} else if (!strcasecmp(policy_str, "immediate")) {
*policy = DAHDI_POLICY_IMMEDIATE;
#ifdef DAHDI_POLICY_HALF_FULL
} else if (!strcasecmp(policy_str, "half")) {
*policy = DAHDI_POLICY_HALF_FULL;
#endif
} else {
ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
return -1;
}
return 0;
}
| static unsigned int parse_pointcode | ( | const char * | pcstring | ) | [static] |
Definition at line 9971 of file chan_dahdi.c.
Referenced by process_dahdi().
{
unsigned int code1, code2, code3;
int numvals;
numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
if (numvals == 1)
return code1;
if (numvals == 3)
return (code1 << 16) | (code2 << 8) | code3;
return 0;
}
| static int pri_active_dchan_fd | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 4137 of file chan_dahdi.c.
References dahdi_pri::dchans, dahdi_pri::fds, and dahdi_pri::pri.
Referenced by pri_find_principle().
| static int pri_assign_bearer | ( | struct dahdi_pvt * | crv, | |
| struct dahdi_pri * | pri, | |||
| struct dahdi_pvt * | bearer | |||
| ) | [static] |
Definition at line 4103 of file chan_dahdi.c.
References ast_channel_set_fd(), dahdi_pvt::bearer, dahdi_pvt::call, dahdi_subchannel::dfd, inuse, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::realcall, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_request(), pri_dchannel(), and pri_fixup_principle().
| static int pri_check_restart | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 12422 of file chan_dahdi.c.
References dahdi_pvt::call, 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().
{
do {
pri->resetpos++;
} while ((pri->resetpos < pri->numchans) &&
(!pri->pvts[pri->resetpos] ||
pri->pvts[pri->resetpos]->call ||
pri->pvts[pri->resetpos]->resetting));
if (pri->resetpos < pri->numchans) {
/* Mark the channel as resetting and restart it */
pri->pvts[pri->resetpos]->resetting = 1;
pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
} else {
pri->resetting = 0;
time(&pri->lastreset);
}
return 0;
}
| static int pri_create_spanmap | ( | int | span, | |
| int | trunkgroup, | |||
| int | logicalspan | |||
| ) | [static] |
Definition at line 9958 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, dahdi_pri::mastertrunkgroup, dahdi_pri::prilogicalspan, and pris.
Referenced by setup_dahdi().
{
if (pris[span].mastertrunkgroup) {
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);
return -1;
}
pris[span].mastertrunkgroup = trunkgroup;
pris[span].prilogicalspan = logicalspan;
return 0;
}
| static int pri_create_trunkgroup | ( | int | trunkgroup, | |
| int * | channels | |||
| ) | [static] |
Definition at line 9893 of file chan_dahdi.c.
References ast_log(), dahdi_pri::dchanavail, dahdi_pri::dchannels, errno, LOG_WARNING, dahdi_pri::offset, pris, pvts, dahdi_pri::span, and dahdi_pri::trunkgroup.
Referenced by setup_dahdi().
{
struct dahdi_spaninfo si;
struct dahdi_params p;
int fd;
int span;
int ospan=0;
int x,y;
for (x = 0; x < NUM_SPANS; x++) {
if (pris[x].trunkgroup == trunkgroup) {
ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
return -1;
}
}
for (y = 0; y < NUM_DCHANS; y++) {
if (!channels[y])
break;
memset(&si, 0, sizeof(si));
memset(&p, 0, sizeof(p));
fd = open("/dev/dahdi/channel", O_RDWR);
if (fd < 0) {
ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
return -1;
}
x = channels[y];
if (ioctl(fd, DAHDI_SPECIFY, &x)) {
ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
close(fd);
return -1;
}
if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
return -1;
}
if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
close(fd);
return -1;
}
span = p.spanno - 1;
if (pris[span].trunkgroup) {
ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
close(fd);
return -1;
}
if (pris[span].pvts[0]) {
ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
close(fd);
return -1;
}
if (!y) {
pris[span].trunkgroup = trunkgroup;
pris[span].offset = channels[y] - p.chanpos;
ospan = span;
}
pris[ospan].dchannels[y] = channels[y];
pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
pris[span].span = span + 1;
close(fd);
}
return 0;
}
| static void* pri_dchannel | ( | void * | vpri | ) | [static] |
Definition at line 12523 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, dahdi_pvt::alerting, dahdi_pvt::alreadyhungup, apply_plan_to_number(), ast_canmatch_extension(), AST_CAUSE_USER_BUSY, ast_copy_string(), ast_debug, ast_dsp_set_features(), ast_exists_extension(), AST_FORMAT_ULAW, ast_hangup(), ast_log(), ast_matchmore_extension(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), ast_pthread_create_background, ast_pthread_create_detached, ast_shrink_phone_number(), AST_STATE_BUSY, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_UP, ast_strlen_zero(), ast_tv(), ast_tvcmp(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), ast_verb, dahdi_pvt::bearer, dahdi_pvt::call, dahdi_pvt::callingpres, dahdi_pvt::channel, dahdi_pvt::cid_ani, dahdi_pvt::cid_ani2, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_ton, dahdi_pvt::confirmanswer, dahdi_pvt::context, dahdi_enable_ec(), dahdi_hangup(), dahdi_new(), DAHDI_OVERLAPDIAL_INCOMING, dahdi_queue_frame(), dahdi_request(), dahdi_setlaw(), DCHAN_NOTINALARM, DCHAN_UP, dahdi_pri::dchanavail, dahdi_pri::dchannels, dahdi_pri::dchans, dahdi_pri::debug, dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialing, dahdi_pri::discardremoteholdretrieval, dahdi_pvt::dnid, do_idle_thread(), dahdi_pvt::dop, dahdi_pvt::dsp, dahdi_pvt::dsp_features, DSP_PROGRESS_RINGING, errno, event2str(), EVENT_FLAG_SYSTEM, dahdi_pvt::exten, dahdi_pri::fds, ast_channel::hangupcause, dahdi_pri::idlecontext, dahdi_pri::idledial, dahdi_pri::idleext, dahdi_pvt::immediate, dahdi_pvt::inalarm, dahdi_pvt::inservice, inuse, dahdi_pvt::isidlecall, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_pri::lastreset, dahdi_pvt::lock, dahdi_pri::lock, LOG_NOTICE, LOG_WARNING, dahdi_pvt::logicalspan, manager_event, dahdi_pri::minidle, dahdi_pri::minunused, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcallerid, dahdi_subchannel::needcongestion, dahdi_subchannel::needringing, dahdi_pri::numchans, dahdi_pri::overlapdial, dahdi_pvt::owner, pbx_builtin_setvar_helper(), dahdi_pvt::pri, dahdi_pri::pri, pri_assign_bearer(), PRI_CHANNEL, pri_check_restart(), pri_find_crv(), pri_find_dchan(), pri_find_empty_chan(), pri_find_principle(), pri_fixup_principle(), pri_hangup_all(), pri_is_up(), pri_order(), PRI_SPAN, dahdi_pvt::prioffset, dahdi_pvt::proceeding, dahdi_pvt::progress, PVT_TO_CHANNEL, dahdi_pri::pvts, dahdi_pvt::rdnis, dahdi_pvt::realcall, redirectingreason2str(), dahdi_pri::resetinterval, dahdi_pri::resetpos, dahdi_pvt::resetting, dahdi_pri::resetting, dahdi_pvt::rxgain, S_OR, set_actual_gain(), dahdi_pvt::setup_ack, dahdi_pvt::sig, dahdi_pri::sig, SIG_BRI_PTMP, SIG_FXSKS, dahdi_pri::span, ss_thread(), SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, dahdi_pri::switchtype, dahdi_pri::trunkgroup, dahdi_pvt::txgain, and dahdi_pvt::use_callerid.
Referenced by start_pri().
{
struct dahdi_pri *pri = vpri;
pri_event *e;
struct pollfd fds[NUM_DCHANS];
int res;
int chanpos = 0;
int x;
int haveidles;
int activeidles;
int nextidle = -1;
struct ast_channel *c;
struct timeval tv, lowest, *next;
struct timeval lastidle = ast_tvnow();
int doidling=0;
char *cc;
char idlen[80];
struct ast_channel *idle;
pthread_t p;
time_t t;
int i, which=-1;
int numdchans;
int cause=0;
struct dahdi_pvt *crv;
pthread_t threadid;
char ani2str[6];
char plancallingnum[256];
char plancallingani[256];
char calledtonstr[10];
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
gettimeofday(&lastidle, NULL);
if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
/* Need to do idle dialing, check to be sure though */
cc = strchr(pri->idleext, '@');
if (cc) {
*cc = '\0';
cc++;
ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
#if 0
/* Extensions may not be loaded yet */
if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
else
#endif
doidling = 1;
} else
ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
}
for (;;) {
for (i = 0; i < NUM_DCHANS; i++) {
if (!pri->dchannels[i])
break;
fds[i].fd = pri->fds[i];
fds[i].events = POLLIN | POLLPRI;
fds[i].revents = 0;
}
numdchans = i;
time(&t);
ast_mutex_lock(&pri->lock);
if ((pri->switchtype != PRI_SWITCH_GR303_TMC) && (pri->sig != SIG_BRI_PTMP) && (pri->resetinterval > 0)) {
if (pri->resetting && pri_is_up(pri)) {
if (pri->resetpos < 0)
pri_check_restart(pri);
} else {
if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
pri->resetting = 1;
pri->resetpos = -1;
}
}
}
/* Look for any idle channels if appropriate */
if (doidling && pri_is_up(pri)) {
nextidle = -1;
haveidles = 0;
activeidles = 0;
for (x = pri->numchans; x >= 0; x--) {
if (pri->pvts[x] && !pri->pvts[x]->owner &&
!pri->pvts[x]->call) {
if (haveidles < pri->minunused) {
haveidles++;
} else if (!pri->pvts[x]->resetting) {
nextidle = x;
break;
}
} else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
activeidles++;
}
if (nextidle > -1) {
if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
/* Don't create a new idle call more than once per second */
snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
if (idle) {
pri->pvts[nextidle]->isidlecall = 1;
if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
dahdi_hangup(idle);
}
} else
ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
lastidle = ast_tvnow();
}
} else if ((haveidles < pri->minunused) &&
(activeidles > pri->minidle)) {
/* Mark something for hangup if there is something
that can be hungup */
for (x = pri->numchans; x >= 0; x--) {
/* find a candidate channel */
if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
haveidles++;
/* Stop if we have enough idle channels or
can't spare any more active idle ones */
if ((haveidles >= pri->minunused) ||
(activeidles <= pri->minidle))
break;
}
}
}
}
/* Start with reasonable max */
lowest = ast_tv(60, 0);
for (i = 0; i < NUM_DCHANS; i++) {
/* Find lowest available d-channel */
if (!pri->dchannels[i])
break;
if ((next = pri_schedule_next(pri->dchans[i]))) {
/* We need relative time here */
tv = ast_tvsub(*next, ast_tvnow());
if (tv.tv_sec < 0) {
tv = ast_tv(0,0);
}
if (doidling || pri->resetting) {
if (tv.tv_sec > 1) {
tv = ast_tv(1, 0);
}
} else {
if (tv.tv_sec > 60) {
tv = ast_tv(60, 0);
}
}
} else if (doidling || pri->resetting) {
/* Make sure we stop at least once per second if we're
monitoring idle channels */
tv = ast_tv(1,0);
} else {
/* Don't poll for more than 60 seconds */
tv = ast_tv(60, 0);
}
if (!i || ast_tvcmp(tv, lowest) < 0) {
lowest = tv;
}
}
ast_mutex_unlock(&pri->lock);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_testcancel();
e = NULL;
res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
pthread_testcancel();
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
ast_mutex_lock(&pri->lock);
if (!res) {
for (which = 0; which < NUM_DCHANS; which++) {
if (!pri->dchans[which])
break;
/* Just a timeout, run the scheduler */
e = pri_schedule_run(pri->dchans[which]);
if (e)
break;
}
} else if (res > -1) {
for (which = 0; which < NUM_DCHANS; which++) {
if (!pri->dchans[which])
break;
if (fds[which].revents & POLLPRI) {
/* Check for an event */
x = 0;
res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
if (x) {
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);
manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
"PRIEvent: %s\r\n"
"PRIEventCode: %d\r\n"
"D-channel: %s\r\n"
"Span: %d\r\n",
event2str(x),
x,
pri_order(which),
pri->span
);
}
/* Keep track of alarm state */
if (x == DAHDI_EVENT_ALARM) {
pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
pri_find_dchan(pri);
} else if (x == DAHDI_EVENT_NOALARM) {
pri->dchanavail[which] |= DCHAN_NOTINALARM;
pri_restart(pri->dchans[which]);
}
ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
} else if (fds[which].revents & POLLIN) {
e = pri_check_event(pri->dchans[which]);
}
if (e)
break;
}
} else if (errno != EINTR)
ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
if (e) {
if (pri->debug)
pri_dump_event(pri->dchans[which], e);
if (e->e != PRI_EVENT_DCHAN_DOWN) {
if (!(pri->dchanavail[which] & DCHAN_UP)) {
ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
}
pri->dchanavail[which] |= DCHAN_UP;
} else if (pri->sig != SIG_BRI_PTMP) {
if (pri->dchanavail[which] & DCHAN_UP) {
ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
}
pri->dchanavail[which] &= ~DCHAN_UP;
}
if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
/* Must be an NFAS group that has the secondary dchan active */
pri->pri = pri->dchans[which];
switch (e->e) {
case PRI_EVENT_DCHAN_UP:
if (!pri->pri) pri_find_dchan(pri);
/* Note presense of D-channel */
time(&pri->lastreset);
/* Restart in 5 seconds */
if (pri->resetinterval > -1) {
pri->lastreset -= pri->resetinterval;
pri->lastreset += 5;
}
pri->resetting = 0;
/* Take the channels from inalarm condition */
for (i = 0; i < pri->numchans; i++)
if (pri->pvts[i]) {
pri->pvts[i]->inalarm = 0;
}
break;
case PRI_EVENT_DCHAN_DOWN:
pri_find_dchan(pri);
if (!pri_is_up(pri)) {
pri->resetting = 0;
/* Hangup active channels and put them in alarm mode */
for (i = 0; i < pri->numchans; i++) {
struct dahdi_pvt *p = pri->pvts[i];
if (p) {
if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
/* T309 is not enabled : hangup calls when alarm occurs */
if (p->call) {
if (p->pri && p->pri->pri) {
pri_hangup(p->pri->pri, p->call, -1);
pri_destroycall(p->pri->pri, p->call);
p->call = NULL;
} else
ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
}
if (p->realcall) {
pri_hangup_all(p->realcall, pri);
} else if (p->owner)
p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
}
/* For PTMP connections with non persistent layer 2 we want
* to *not* declare inalarm unless there actually is an alarm */
if (p->sig != SIG_BRI_PTMP) {
p->inalarm = 1;
}
}
}
}
break;
case PRI_EVENT_RESTART:
if (e->restart.channel > -1) {
chanpos = pri_find_principle(pri, e->restart.channel);
if (chanpos < 0)
ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
else {
ast_verb(3, "B-channel %d/%d restarted on span %d\n",
PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
ast_mutex_lock(&pri->pvts[chanpos]->lock);
if (pri->pvts[chanpos]->call) {
pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
pri->pvts[chanpos]->call = NULL;
}
/* Force soft hangup if appropriate */
if (pri->pvts[chanpos]->realcall)
pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
else if (pri->pvts[chanpos]->owner)
pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
}
} else {
ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
for (x = 0; x < pri->numchans; x++)
if (pri->pvts[x]) {
ast_mutex_lock(&pri->pvts[x]->lock);
if (pri->pvts[x]->call) {
pri_destroycall(pri->pri, pri->pvts[x]->call);
pri->pvts[x]->call = NULL;
}
if (pri->pvts[x]->realcall)
pri_hangup_all(pri->pvts[x]->realcall, pri);
else if (pri->pvts[x]->owner)
pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
ast_mutex_unlock(&pri->pvts[x]->lock);
}
}
break;
case PRI_EVENT_KEYPAD_DIGIT:
chanpos = pri_find_principle(pri, e->digit.channel);
if (chanpos < 0) {
ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
} else {
chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
if (chanpos > -1) {
ast_mutex_lock(&pri->pvts[chanpos]->lock);
/* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
/* how to do that */
int digitlen = strlen(e->digit.digits);
char digit;
int i;
for (i = 0; i < digitlen; i++) {
digit = e->digit.digits[i];
{
struct ast_frame f = { AST_FRAME_DTMF, digit, };
dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
}
}
}
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
}
}
break;
case PRI_EVENT_INFO_RECEIVED:
chanpos = pri_find_principle(pri, e->ring.channel);
if (chanpos < 0) {
ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
} else {
chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
if (chanpos > -1) {
ast_mutex_lock(&pri->pvts[chanpos]->lock);
/* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
/* how to do that */
int digitlen = strlen(e->ring.callednum);
char digit;
int i;
for (i = 0; i < digitlen; i++) {
digit = e->ring.callednum[i];
{
struct ast_frame f = { AST_FRAME_DTMF, digit, };
dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
}
}
}
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
}
}
break;
case PRI_EVENT_RING:
crv = NULL;
if (e->ring.channel == -1)
chanpos = pri_find_empty_chan(pri, 1);
else
chanpos = pri_find_principle(pri, e->ring.channel);
/* if no channel specified find one empty */
if (chanpos < 0) {
ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
} else {
ast_mutex_lock(&pri->pvts[chanpos]->lock);
if (pri->pvts[chanpos]->owner) {
if (pri->pvts[chanpos]->call == e->ring.call) {
ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
break;
} else {
/* This is where we handle initial glare */
ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n",
PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
chanpos = -1;
}
}
if (chanpos > -1)
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
}
if ((chanpos < 0) && (e->ring.flexible))
chanpos = pri_find_empty_chan(pri, 1);
if (chanpos > -1) {
ast_mutex_lock(&pri->pvts[chanpos]->lock);
if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
/* Should be safe to lock CRV AFAIK while bearer is still locked */
crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
if (crv)
ast_mutex_lock(&crv->lock);
if (!crv || crv->owner) {
pri->pvts[chanpos]->call = NULL;
if (crv) {
if (crv->owner)
crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
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);
} else
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);
pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
if (crv)
ast_mutex_unlock(&crv->lock);
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
break;
}
}
pri->pvts[chanpos]->call = e->ring.call;
apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
if (pri->pvts[chanpos]->use_callerid) {
ast_shrink_phone_number(plancallingnum);
ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
#ifdef PRI_ANI
if (!ast_strlen_zero(e->ring.callingani)) {
apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
ast_shrink_phone_number(plancallingani);
ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
} else {
pri->pvts[chanpos]->cid_ani[0] = '\0';
}
#endif
ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
} else {
pri->pvts[chanpos]->cid_num[0] = '\0';
pri->pvts[chanpos]->cid_ani[0] = '\0';
pri->pvts[chanpos]->cid_name[0] = '\0';
pri->pvts[chanpos]->cid_ton = 0;
}
apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
e->ring.redirectingnum, e->ring.callingplanrdnis);
/* Set DNID on all incoming calls -- even immediate */
ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
/* If immediate=yes go to s|1 */
if (pri->pvts[chanpos]->immediate) {
ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
pri->pvts[chanpos]->exten[0] = 's';
pri->pvts[chanpos]->exten[1] = '\0';
}
/* Get called number */
else if (!ast_strlen_zero(e->ring.callednum)) {
ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
} else if (pri->overlapdial)
pri->pvts[chanpos]->exten[0] = '\0';
else {
/* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
pri->pvts[chanpos]->exten[0] = 's';
pri->pvts[chanpos]->exten[1] = '\0';
}
/* No number yet, but received "sending complete"? */
if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
ast_verb(3, "Going to extension s|1 because of Complete received\n");
pri->pvts[chanpos]->exten[0] = 's';
pri->pvts[chanpos]->exten[1] = '\0';
}
/* Make sure extension exists (or in overlap dial mode, can exist) */
if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
/* Setup law */
int law;
if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
/* Set to audio mode at this point */
law = 1;
if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
}
if (e->ring.layer1 == PRI_LAYER_1_ALAW)
law = DAHDI_LAW_ALAW;
else
law = DAHDI_LAW_MULAW;
res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
if (res < 0)
ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
if (res < 0)
ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
/* Just announce proceeding */
pri->pvts[chanpos]->proceeding = 1;
pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
} else {
if (pri->switchtype != PRI_SWITCH_GR303_TMC)
pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
else
pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
}
/* Get the use_callingpres state */
pri->pvts[chanpos]->callingpres = e->ring.callingpres;
/* Start PBX */
if (!e->ring.complete
&& (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
&& ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
/*
* Release the PRI lock while we create the channel
* so other threads can send D channel messages.
*/
ast_mutex_unlock(&pri->lock);
if (crv) {
/* Set bearer and such */
pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
pri->pvts[chanpos]->owner = &inuse;
ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
} else {
c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
}
ast_mutex_lock(&pri->lock);
if (c) {
if (!ast_strlen_zero(e->ring.callingsubaddr)) {
pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
}
if (e->ring.ani2 >= 0) {
snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
pbx_builtin_setvar_helper(c, "ANI2", ani2str);
pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
}
#ifdef SUPPORT_USERUSER
if (!ast_strlen_zero(e->ring.useruserinfo)) {
pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
}
#endif
snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
if (e->ring.redirectingreason >= 0)
pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
}
if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
} else {
ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
if (c)
ast_hangup(c);
else {
pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
pri->pvts[chanpos]->call = NULL;
}
}
} else {
/*
* Release the PRI lock while we create the channel
* so other threads can send D channel messages.
*/
ast_mutex_unlock(&pri->lock);
c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
ast_mutex_lock(&pri->lock);
if (c) {
/*
* It is reasonably safe to set the following
* channel variables while the PRI and DAHDI private
* structures are locked. The PBX has not been
* started yet and it is unlikely that any other task
* will do anything with the channel we have just
* created.
*/
if (!ast_strlen_zero(e->ring.callingsubaddr)) {
pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
}
if (e->ring.ani2 >= 0) {
snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
pbx_builtin_setvar_helper(c, "ANI2", ani2str);
pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
}
#ifdef SUPPORT_USERUSER
if (!ast_strlen_zero(e->ring.useruserinfo)) {
pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
}
#endif
if (e->ring.redirectingreason >= 0)
pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
}
if (c && !ast_pbx_start(c)) {
ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
plancallingnum, pri->pvts[chanpos]->exten,
pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
dahdi_enable_ec(pri->pvts[chanpos]);
} else {
ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
if (c) {
ast_hangup(c);
} else {
pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
pri->pvts[chanpos]->call = NULL;
}
}
}
} else {
ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
pri->pvts[chanpos]->prioffset, pri->span);
pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
pri->pvts[chanpos]->call = NULL;
pri->pvts[chanpos]->exten[0] = '\0';
}
if (crv)
ast_mutex_unlock(&crv->lock);
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
} else {
if (e->ring.flexible)
pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
else
pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
}
break;
case PRI_EVENT_RINGING:
chanpos = pri_find_principle(pri, e->ringing.channel);
if (chanpos < 0) {
ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
} else {
chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
if (chanpos < 0) {
ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
} else {
ast_mutex_lock(&pri->pvts[chanpos]->lock);
if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
dahdi_enable_ec(pri->pvts[chanpos]);
pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
pri->pvts[chanpos]->alerting = 1;
} else
ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
if (
#ifdef PRI_PROGRESS_MASK
e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE
#else
e->ringing.progress == 8
#endif
) {
/* Now we can do call progress detection */
if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
/* RINGING detection isn't required because we got ALERTING signal */
ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
pri->pvts[chanpos]->dsp_features = 0;
}
}
#ifdef SUPPORT_USERUSER
if (!ast_strlen_zero(e->ringing.useruserinfo)) {
struct ast_channel *owner = pri->pvts[chanpos]->owner;
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
ast_mutex_lock(&pri->pvts[chanpos]->lock);
}
#endif
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
}
}
break;
case PRI_EVENT_PROGRESS:
/* Get chan value if e->e is not PRI_EVNT_RINGING */
chanpos = pri_find_principle(pri, e->proceeding.channel);
if (chanpos > -1) {
if ((!pri->pvts[chanpos]->progress)
#ifdef PRI_PROGRESS_MASK
|| (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
#else
|| (e->proceeding.progress == 8)
#endif
) {
struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
if (e->proceeding.cause > -1) {
ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
/* Work around broken, out of spec USER_BUSY cause in a progress message */
if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
if (pri->pvts[chanpos]->owner) {
ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
f.subclass = AST_CONTROL_BUSY;
}
}
}
ast_mutex_lock(&pri->pvts[chanpos]->lock);
ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
if (
#ifdef PRI_PROGRESS_MASK
e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
#else
e->proceeding.progress == 8
#endif
) {
/* Now we can do call progress detection */
if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
pri->pvts[chanpos]->dsp_features = 0;
}
/* Bring voice path up */
f.subclass = AST_CONTROL_PROGRESS;
dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
}
pri->pvts[chanpos]->progress = 1;
pri->pvts[chanpos]->dialing = 0;
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
}
}
break;
case PRI_EVENT_PROCEEDING:
chanpos = pri_find_principle(pri, e->proceeding.channel);
if (chanpos > -1) {
if (!pri->pvts[chanpos]->proceeding) {
struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
ast_mutex_lock(&pri->pvts[chanpos]->lock);
ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
if (
#ifdef PRI_PROGRESS_MASK
e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
#else
e->proceeding.progress == 8
#endif
) {
/* Now we can do call progress detection */
if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
pri->pvts[chanpos]->dsp_features = 0;
}
/* Bring voice path up */
f.subclass = AST_CONTROL_PROGRESS;
dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
}
pri->pvts[chanpos]->proceeding = 1;
pri->pvts[chanpos]->dialing = 0;
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
}
}
break;
case PRI_EVENT_FACNAME:
chanpos = pri_find_principle(pri, e->facname.channel);
if (chanpos < 0) {
ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
} else {
chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
if (chanpos < 0) {
ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
} else if (pri->pvts[chanpos]->use_callerid) {
/* Re-use *69 field for PRI */
ast_mutex_lock(&pri->pvts[chanpos]->lock);
ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
pri->pvts[chanpos]->subs[SUB_REAL].needcallerid = 1;
dahdi_enable_ec(pri->pvts[chanpos]);
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
}
}
break;
case PRI_EVENT_ANSWER:
chanpos = pri_find_principle(pri, e->answer.channel);
if (chanpos < 0) {
ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
} else {
chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
if (chanpos < 0) {
ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
} else {
ast_mutex_lock(&pri->pvts[chanpos]->lock);
/* Now we can do call progress detection */
/* We changed this so it turns on the DSP no matter what... progress or no progress.
* By this time, we need DTMF detection and other features that were previously disabled
* -- Matt F */
if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
pri->pvts[chanpos]->dsp_features = 0;
}
if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
x = DAHDI_START;
res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
if (res < 0) {
if (errno != EINPROGRESS) {
ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
}
}
} else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
pri->pvts[chanpos]->dialing = 1;
/* Send any "w" waited stuff */
res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
pri->pvts[chanpos]->dop.dialstr[0] = '\0';
} else
ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
pri->pvts[chanpos]->dop.dialstr[0] = '\0';
} else if (pri->pvts[chanpos]->confirmanswer) {
ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
} else {
pri->pvts[chanpos]->dialing = 0;
pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
/* Enable echo cancellation if it's not on already */
dahdi_enable_ec(pri->pvts[chanpos]);
}
#ifdef SUPPORT_USERUSER
if (!ast_strlen_zero(e->answer.useruserinfo)) {
struct ast_channel *owner = pri->pvts[chanpos]->owner;
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
ast_mutex_lock(&pri->pvts[chanpos]->lock);
}
#endif
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
}
}
break;
case PRI_EVENT_HANGUP:
chanpos = pri_find_principle(pri, e->hangup.channel);
if (chanpos < 0) {
ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
} else {
chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
if (chanpos > -1) {
ast_mutex_lock(&pri->pvts[chanpos]->lock);
if (!pri->pvts[chanpos]->alreadyhungup) {
/* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
pri->pvts[chanpos]->alreadyhungup = 1;
if (pri->pvts[chanpos]->realcall)
pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
else if (pri->pvts[chanpos]->owner) {
/* Queue a BUSY instead of a hangup if our cause is appropriate */
pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
switch (pri->pvts[chanpos]->owner->_state) {
case AST_STATE_BUSY:
case AST_STATE_UP:
pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
break;
default:
switch (e->hangup.cause) {
case PRI_CAUSE_USER_BUSY:
pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
break;
case PRI_CAUSE_CALL_REJECTED:
case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
case PRI_CAUSE_SWITCH_CONGESTION:
case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
break;
default:
pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
}
break;
}
}
ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
} else {
pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
pri->pvts[chanpos]->call = NULL;
}
if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
pri->pvts[chanpos]->resetting = 1;
}
if (e->hangup.aoc_units > -1)
ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
#ifdef SUPPORT_USERUSER
if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
struct ast_channel *owner = pri->pvts[chanpos]->owner;
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
ast_mutex_lock(&pri->pvts[chanpos]->lock);
}
#endif
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
} else {
ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
}
}
break;
#ifndef PRI_EVENT_HANGUP_REQ
#error please update libpri
#endif
case PRI_EVENT_HANGUP_REQ:
chanpos = pri_find_principle(pri, e->hangup.channel);
if (chanpos < 0) {
ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
} else {
chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
if (chanpos > -1) {
ast_mutex_lock(&pri->pvts[chanpos]->lock);
if (pri->pvts[chanpos]->realcall)
pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
else if (pri->pvts[chanpos]->owner) {
pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
switch (pri->pvts[chanpos]->owner->_state) {
case AST_STATE_BUSY:
case AST_STATE_UP:
pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
break;
default:
switch (e->hangup.cause) {
case PRI_CAUSE_USER_BUSY:
pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
break;
case PRI_CAUSE_CALL_REJECTED:
case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
case PRI_CAUSE_SWITCH_CONGESTION:
case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
break;
default:
pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
break;
}
break;
}
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);
if (e->hangup.aoc_units > -1)
ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
} else {
pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
pri->pvts[chanpos]->call = NULL;
}
if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
pri->pvts[chanpos]->resetting = 1;
}
#ifdef SUPPORT_USERUSER
if (!ast_strlen_zero(e->hangup.useruserinfo)) {
struct ast_channel *owner = pri->pvts[chanpos]->owner;
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
ast_mutex_lock(&pri->pvts[chanpos]->lock);
}
#endif
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
} else {
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);
}
}
break;
case PRI_EVENT_HANGUP_ACK:
chanpos = pri_find_principle(pri, e->hangup.channel);
if (chanpos < 0) {
ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
} else {
chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
if (chanpos > -1) {
ast_mutex_lock(&pri->pvts[chanpos]->lock);
pri->pvts[chanpos]->call = NULL;
pri->pvts[chanpos]->resetting = 0;
if (pri->pvts[chanpos]->owner) {
ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
}
#ifdef SUPPORT_USERUSER
if (!ast_strlen_zero(e->hangup.useruserinfo)) {
struct ast_channel *owner = pri->pvts[chanpos]->owner;
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
ast_mutex_lock(&pri->pvts[chanpos]->lock);
}
#endif
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
}
}
break;
case PRI_EVENT_CONFIG_ERR:
ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->span, e->err.err);
break;
case PRI_EVENT_RESTART_ACK:
chanpos = pri_find_principle(pri, e->restartack.channel);
if (chanpos < 0) {
/* Sometime switches (e.g. I421 / British Telecom) don't give us the
channel number, so we have to figure it out... This must be why
everybody resets exactly a channel at a time. */
for (x = 0; x < pri->numchans; x++) {
if (pri->pvts[x] && pri->pvts[x]->resetting) {
chanpos = x;
ast_mutex_lock(&pri->pvts[chanpos]->lock);
ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
pri->pvts[chanpos]->prioffset, pri->span);
if (pri->pvts[chanpos]->realcall)
pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
else if (pri->pvts[chanpos]->owner) {
ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
pri->pvts[chanpos]->prioffset, pri->span);
pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
}
pri->pvts[chanpos]->resetting = 0;
ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
pri->pvts[chanpos]->prioffset, pri->span);
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
if (pri->resetting)
pri_check_restart(pri);
break;
}
}
if (chanpos < 0) {
ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
}
} else {
if (pri->pvts[chanpos]) {
ast_mutex_lock(&pri->pvts[chanpos]->lock);
if (pri->pvts[chanpos]->realcall)
pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
else if (pri->pvts[chanpos]->owner) {
ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
}
pri->pvts[chanpos]->resetting = 0;
pri->pvts[chanpos]->inservice = 1;
ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
pri->pvts[chanpos]->prioffset, pri->span);
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
if (pri->resetting)
pri_check_restart(pri);
}
}
break;
case PRI_EVENT_SETUP_ACK:
chanpos = pri_find_principle(pri, e->setup_ack.channel);
if (chanpos < 0) {
ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
} else {
chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
if (chanpos > -1) {
ast_mutex_lock(&pri->pvts[chanpos]->lock);
pri->pvts[chanpos]->setup_ack = 1;
/* Send any queued digits */
for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
pri_information(pri->pri, pri->pvts[chanpos]->call,
pri->pvts[chanpos]->dialdest[x]);
}
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
} else
ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
}
break;
case PRI_EVENT_NOTIFY:
chanpos = pri_find_principle(pri, e->notify.channel);
if (chanpos < 0) {
ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
} else if (!pri->discardremoteholdretrieval) {
struct ast_frame f = { AST_FRAME_CONTROL, };
ast_mutex_lock(&pri->pvts[chanpos]->lock);
switch (e->notify.info) {
case PRI_NOTIFY_REMOTE_HOLD:
f.subclass = AST_CONTROL_HOLD;
dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
break;
case PRI_NOTIFY_REMOTE_RETRIEVAL:
f.subclass = AST_CONTROL_UNHOLD;
dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
break;
}
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
}
break;
default:
ast_debug(1, "Event: %d\n", e->e);
}
}
ast_mutex_unlock(&pri->lock);
}
/* Never reached */
return NULL;
}
Definition at line 12158 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pri::crvs, and dahdi_pvt::next.
Referenced by pri_dchannel().
| static int pri_find_dchan | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 4151 of file chan_dahdi.c.
References ast_log(), DCHAN_AVAILABLE, dahdi_pri::dchanavail, dahdi_pri::dchannels, dahdi_pri::dchans, LOG_NOTICE, LOG_WARNING, dahdi_pri::pri, dahdi_pri::sig, and SIG_BRI_PTMP.
Referenced by pri_dchannel().
{
int oldslot = -1;
struct pri *old;
int newslot = -1;
int x;
old = pri->pri;
for (x = 0; x < NUM_DCHANS; x++) {
if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
newslot = x;
if (pri->dchans[x] == old) {
oldslot = x;
}
}
if (newslot < 0) {
newslot = 0;
/* This is annoying to see on non persistent layer 2 connections. Let's not complain in that case */
if (pri->sig != SIG_BRI_PTMP) {
ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
pri->dchannels[newslot]);
}
}
if (old && (oldslot != newslot))
ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
pri->dchannels[oldslot], pri->dchannels[newslot]);
pri->pri = pri->dchans[newslot];
return 0;
}
| static int pri_find_empty_chan | ( | struct dahdi_pri * | pri, | |
| int | backwards | |||
| ) | [static] |
Definition at line 10933 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(), and pri_dchannel().
{
int x;
if (backwards)
x = pri->numchans;
else
x = 0;
for (;;) {
if (backwards && (x < 0))
break;
if (!backwards && (x >= pri->numchans))
break;
if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
ast_debug(1, "Found empty available channel %d/%d\n",
pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
return x;
}
if (backwards)
x--;
else
x++;
}
return -1;
}
| static int pri_find_principle | ( | struct dahdi_pri * | pri, | |
| int | channel | |||
| ) | [static] |
Definition at line 12172 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.
Referenced by pri_dchannel().
{
int x;
int span = PRI_SPAN(channel);
int spanfd;
struct dahdi_params param;
int principle = -1;
int explicit = PRI_EXPLICIT(channel);
channel = PRI_CHANNEL(channel);
if (!explicit) {
spanfd = pri_active_dchan_fd(pri);
memset(¶m, 0, sizeof(param));
if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m))
return -1;
span = pris[param.spanno - 1].prilogicalspan;
}
for (x = 0; x < pri->numchans; x++) {
if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
principle = x;
break;
}
}
return principle;
}
| static int pri_fixup_principle | ( | struct dahdi_pri * | pri, | |
| int | principle, | |||
| q931_call * | c | |||
| ) | [static] |
Definition at line 12202 of file chan_dahdi.c.
References ast_channel_set_fd(), ast_debug, ast_log(), ast_string_field_build, ast_verb, dahdi_pvt::bearer, dahdi_pvt::call, dahdi_pvt::channel, dahdi_pri::crvs, dahdi_close_sub(), LOG_WARNING, dahdi_pvt::logicalspan, name, dahdi_pvt::next, dahdi_pri::numchans, dahdi_pvt::owner, pri_assign_bearer(), dahdi_pvt::prioffset, dahdi_pri::pvts, SUB_REAL, dahdi_pri::trunkgroup, and wakeup_sub().
Referenced by pri_dchannel().
{
int x;
struct dahdi_pvt *crv;
if (!c) {
if (principle < 0)
return -1;
return principle;
}
if ((principle > -1) &&
(principle < pri->numchans) &&
(pri->pvts[principle]) &&
(pri->pvts[principle]->call == c))
return principle;
/* First, check for other bearers */
for (x = 0; x < pri->numchans; x++) {
if (!pri->pvts[x])
continue;
if (pri->pvts[x]->call == c) {
/* Found our call */
if (principle != x) {
struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
ast_verb(3, "Moving call from channel %d to channel %d\n",
old->channel, new->channel);
if (new->owner) {
ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
old->channel, new->channel, new->channel);
return -1;
}
/* Fix it all up now */
new->owner = old->owner;
old->owner = NULL;
if (new->owner) {
ast_string_field_build(new->owner, name,
"DAHDI/%d:%d-%d", pri->trunkgroup,
new->channel, 1);
new->owner->tech_pvt = new;
ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
old->subs[SUB_REAL].owner = NULL;
} else
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);
new->call = old->call;
old->call = NULL;
/* Copy any DSP that may be present */
new->dsp = old->dsp;
new->dsp_features = old->dsp_features;
old->dsp = NULL;
old->dsp_features = 0;
}
return principle;
}
}
/* Now check for a CRV with no bearer */
crv = pri->crvs;
while (crv) {
if (crv->call == c) {
/* This is our match... Perform some basic checks */
if (crv->bearer)
ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
else if (pri->pvts[principle]->owner)
ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
else {
/* Looks good. Drop the pseudo channel now, clear up the assignment, and
wakeup the potential sleeper */
dahdi_close_sub(crv, SUB_REAL);
pri->pvts[principle]->call = crv->call;
pri_assign_bearer(crv, pri, pri->pvts[principle]);
ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
pri->trunkgroup, crv->channel);
wakeup_sub(crv, SUB_REAL, pri);
}
return principle;
}
crv = crv->next;
}
ast_log(LOG_WARNING, "Call specified, but not found?\n");
return -1;
}
Definition at line 1433 of file chan_dahdi.c.
References ast_mutex_trylock(), AST_PTHREADT_NULL, DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_pri::lock, and dahdi_pri::master.
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().
{
int res;
/* Grab the lock first */
do {
res = ast_mutex_trylock(&pri->lock);
if (res) {
DEADLOCK_AVOIDANCE(&pvt->lock);
}
} while (res);
/* Then break the poll */
if (pri->master != AST_PTHREADT_NULL)
pthread_kill(pri->master, SIGURG);
return 0;
}
Definition at line 12443 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.
Referenced by pri_dchannel().
{
int x;
int redo;
ast_mutex_unlock(&pri->lock);
ast_mutex_lock(&p->lock);
do {
redo = 0;
for (x = 0; x < 3; x++) {
while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
redo++;
DEADLOCK_AVOIDANCE(&p->lock);
}
if (p->subs[x].owner) {
ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
ast_channel_unlock(p->subs[x].owner);
}
}
} while (redo);
ast_mutex_unlock(&p->lock);
ast_mutex_lock(&pri->lock);
return 0;
}
| static int pri_is_up | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 4091 of file chan_dahdi.c.
References DCHAN_AVAILABLE, and dahdi_pri::dchanavail.
Referenced by mkintf(), and pri_dchannel().
{
int x;
for (x = 0; x < NUM_DCHANS; x++) {
if (pri->dchanavail[x] == DCHAN_AVAILABLE)
return 1;
}
return 0;
}
| static char* pri_order | ( | int | level | ) | [static] |
Definition at line 4118 of file chan_dahdi.c.
Referenced by handle_pri_show_span(), and pri_dchannel().
{
switch (level) {
case 0:
return "Primary";
case 1:
return "Secondary";
case 2:
return "Tertiary";
case 3:
return "Quaternary";
default:
return "<Unknown>";
}
}
| static void pri_rel | ( | struct dahdi_pri * | pri | ) | [inline, static] |
Definition at line 569 of file chan_dahdi.c.
References ast_mutex_unlock(), and dahdi_pri::lock.
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().
{
ast_mutex_unlock(&pri->lock);
}
| static int pri_resolve_span | ( | int * | span, | |
| int | channel, | |||
| int | offset, | |||
| struct dahdi_spaninfo * | si | |||
| ) | [static] |
Definition at line 9845 of file chan_dahdi.c.
References ast_log(), dahdi_pri::dchanavail, dahdi_pri::dchannels, LOG_WARNING, dahdi_pri::mastertrunkgroup, dahdi_pri::offset, pris, and dahdi_pri::span.
Referenced by mkintf().
{
int x;
int trunkgroup;
/* Get appropriate trunk group if there is one */
trunkgroup = pris[*span].mastertrunkgroup;
if (trunkgroup) {
/* Select a specific trunk group */
for (x = 0; x < NUM_SPANS; x++) {
if (pris[x].trunkgroup == trunkgroup) {
*span = x;
return 0;
}
}
ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
*span = -1;
} else {
if (pris[*span].trunkgroup) {
ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
*span = -1;
} else if (pris[*span].mastertrunkgroup) {
ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
*span = -1;
} else {
if (si->totalchans == 31) {
/* E1 */
pris[*span].dchannels[0] = 16 + offset;
} else if (si->totalchans == 24) {
/* T1 or J1 */
pris[*span].dchannels[0] = 24 + offset;
} else if (si->totalchans == 3) {
/* BRI */
pris[*span].dchannels[0] = 3 + offset;
} else {
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);
*span = -1;
return 0;
}
pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
pris[*span].offset = offset;
pris[*span].span = *span + 1;
}
}
return 0;
}
| static int process_dahdi | ( | struct dahdi_chan_conf * | confp, | |
| const char * | cat, | |||
| struct ast_variable * | v, | |||
| int | reload, | |||
| int | options | |||
| ) | [static] |
Definition at line 16222 of file chan_dahdi.c.
References dahdi_pvt::accountcode, dahdi_pvt::adsi, dahdi_pvt::amaflags, dahdi_pvt::answeronpolarityswitch, ast_callerid_split(), ast_cdr_amaflags2int(), ast_copy_string(), ast_get_group(), ast_jb_read_conf(), ast_log(), AST_MAX_EXTENSION, ast_strdupa, ast_strlen_zero(), ast_true(), ast_variable_new(), ast_verb, dahdi_pvt::buf_no, dahdi_pvt::buf_policy, build_channels(), dahdi_pvt::busy_quietlength, dahdi_pvt::busy_tonelength, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_ss7::called_nai, dahdi_pvt::callgroup, dahdi_ss7::calling_nai, dahdi_pvt::callprogress, CALLPROGRESS_FAX_INCOMING, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, dahdi_pvt::cancallforward, dahdi_pvt::canpark, dahdi_chan_conf::chan, CHAN_PSEUDO, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_rxgain, dahdi_pvt::cid_signalling, dahdi_pvt::cid_start, dahdi_pvt::context, ringContextData::contextData, dahdi_chan_conf_default(), dahdi_pvt::dahditrcallerid, dahdi_pri::dialplan, dahdi_pri::discardremoteholdretrieval, dahdi_pvt::drings, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echotraining, errno, dahdi_pri::facilityenable, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, dahdi_ss7::flags, global_jbconf, dahdi_pvt::group, dahdi_pvt::hanguponpolarityswitch, HAVE_PRI, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pri::idledial, dahdi_pri::idleext, dahdi_pvt::immediate, dahdi_pri::inbanddisconnect, dahdi_ss7::internationalprefix, dahdi_pri::internationalprefix, dahdi_chan_conf::is_sig_auto, dahdi_pvt::language, ast_variable::lineno, linkset_addsigchan(), dahdi_pri::localdialplan, dahdi_pri::localprefix, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pri::minidle, dahdi_pri::minunused, mkintf(), dahdi_pvt::mohinterpret, dahdi_pvt::mohsuggest, dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitor_neon, dahdi_pvt::mwimonitor_rpas, ast_variable::name, dahdi_ss7::nationalprefix, dahdi_pri::nationalprefix, ast_variable::next, dahdi_pri::nodetype, dahdi_pri::nsf, NUM_CADENCE_MAX, NUM_SPANS, dahdi_pvt::outsigmod, dahdi_pri::overlapdial, dahdi_pvt::parkinglot, parse_buffers_policy(), parse_pointcode(), dahdi_pvt::pickupgroup, dahdi_pvt::polarityonanswerdelay, dahdi_chan_conf::pri, dahdi_pvt::priexclusive, dahdi_pvt::priindication_oob, dahdi_pri::privateprefix, PROC_DAHDI_OPT_NOCHAN, PROC_DAHDI_OPT_NOWARN, process_echocancel(), dahdi_pvt::pulse, dahdi_pri::qsigchannelmapping, dahdi_pvt::radio, distRingData::range, READ_SIZE, dahdi_pri::resetinterval, dahdi_pvt::restrictcid, distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::rxgain, dahdi_pvt::sendcalleridafter, dahdi_pvt::sig, dahdi_chan_conf::smdi_port, dahdi_chan_conf::ss7, ss7_resolve_linkset(), strcasestr(), dahdi_pvt::stripmsd, strsep(), dahdi_ss7::subscriberprefix, dahdi_pri::switchtype, dahdi_pvt::threewaycalling, timer, dahdi_chan_conf::timing, dahdi_pvt::tonezone, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, dahdi_pvt::txgain, dahdi_ss7::unknownprefix, dahdi_pri::unknownprefix, dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, dahdi_pvt::use_smdi, dahdi_pvt::usefaxbuffers, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.
Referenced by setup_dahdi().
{
struct dahdi_pvt *tmp;
int y;
int found_pseudo = 0;
char dahdichan[MAX_CHANLIST_LEN] = {};
for (; v; v = v->next) {
if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
continue;
/* must have parkinglot in confp before build_channels is called */
if (!strcasecmp(v->name, "parkinglot")) {
ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
}
/* Create the interface list */
if (!strcasecmp(v->name, "channel")
#ifdef HAVE_PRI
|| !strcasecmp(v->name, "crv")
#endif
) {
int iscrv;
if (options & PROC_DAHDI_OPT_NOCHAN) {
ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
continue;
}
iscrv = !strcasecmp(v->name, "crv");
if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
return -1;
ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
} else if (!strcasecmp(v->name, "buffers")) {
if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
ast_log(LOG_WARNING, "Using default buffer policy.\n");
confp->chan.buf_no = numbufs;
confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
}
} else if (!strcasecmp(v->name, "faxbuffers")) {
if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
confp->chan.usefaxbuffers = 1;
}
} else if (!strcasecmp(v->name, "dahdichan")) {
ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
} else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
usedistinctiveringdetection = ast_true(v->value);
} else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
distinctiveringaftercid = ast_true(v->value);
} else if (!strcasecmp(v->name, "dring1context")) {
ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
} else if (!strcasecmp(v->name, "dring2context")) {
ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
} else if (!strcasecmp(v->name, "dring3context")) {
ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
} else if (!strcasecmp(v->name, "dring1range")) {
confp->chan.drings.ringnum[0].range = atoi(v->value);
} else if (!strcasecmp(v->name, "dring2range")) {
confp->chan.drings.ringnum[1].range = atoi(v->value);
} else if (!strcasecmp(v->name, "dring3range")) {
confp->chan.drings.ringnum[2].range = atoi(v->value);
} else if (!strcasecmp(v->name, "dring1")) {
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]);
} else if (!strcasecmp(v->name, "dring2")) {
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]);
} else if (!strcasecmp(v->name, "dring3")) {
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]);
} else if (!strcasecmp(v->name, "usecallerid")) {
confp->chan.use_callerid = ast_true(v->value);
} else if (!strcasecmp(v->name, "cidsignalling")) {
if (!strcasecmp(v->value, "bell"))
confp->chan.cid_signalling = CID_SIG_BELL;
else if (!strcasecmp(v->value, "v23"))
confp->chan.cid_signalling = CID_SIG_V23;
else if (!strcasecmp(v->value, "dtmf"))
confp->chan.cid_signalling = CID_SIG_DTMF;
else if (!strcasecmp(v->value, "smdi"))
confp->chan.cid_signalling = CID_SIG_SMDI;
else if (!strcasecmp(v->value, "v23_jp"))
confp->chan.cid_signalling = CID_SIG_V23_JP;
else if (ast_true(v->value))
confp->chan.cid_signalling = CID_SIG_BELL;
} else if (!strcasecmp(v->name, "cidstart")) {
if (!strcasecmp(v->value, "ring"))
confp->chan.cid_start = CID_START_RING;
else if (!strcasecmp(v->value, "polarity_in"))
confp->chan.cid_start = CID_START_POLARITY_IN;
else if (!strcasecmp(v->value, "polarity"))
confp->chan.cid_start = CID_START_POLARITY;
else if (ast_true(v->value))
confp->chan.cid_start = CID_START_RING;
} else if (!strcasecmp(v->name, "threewaycalling")) {
confp->chan.threewaycalling = ast_true(v->value);
} else if (!strcasecmp(v->name, "cancallforward")) {
confp->chan.cancallforward = ast_true(v->value);
} else if (!strcasecmp(v->name, "relaxdtmf")) {
if (ast_true(v->value))
confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
else
confp->chan.dtmfrelax = 0;
} else if (!strcasecmp(v->name, "mailbox")) {
ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
} else if (!strcasecmp(v->name, "hasvoicemail")) {
if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
}
} else if (!strcasecmp(v->name, "adsi")) {
confp->chan.adsi = ast_true(v->value);
} else if (!strcasecmp(v->name, "usesmdi")) {
confp->chan.use_smdi = ast_true(v->value);
} else if (!strcasecmp(v->name, "smdiport")) {
ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
} else if (!strcasecmp(v->name, "transfer")) {
confp->chan.transfer = ast_true(v->value);
} else if (!strcasecmp(v->name, "canpark")) {
confp->chan.canpark = ast_true(v->value);
} else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
confp->chan.echocanbridged = ast_true(v->value);
} else if (!strcasecmp(v->name, "busydetect")) {
confp->chan.busydetect = ast_true(v->value);
} else if (!strcasecmp(v->name, "busycount")) {
confp->chan.busycount = atoi(v->value);
} else if (!strcasecmp(v->name, "busypattern")) {
if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
}
} else if (!strcasecmp(v->name, "callprogress")) {
confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
if (ast_true(v->value))
confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
} else if (!strcasecmp(v->name, "waitfordialtone")) {
confp->chan.waitfordialtone = atoi(v->value);
} else if (!strcasecmp(v->name, "faxdetect")) {
confp->chan.callprogress &= ~CALLPROGRESS_FAX;
if (!strcasecmp(v->value, "incoming")) {
confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
} else if (!strcasecmp(v->value, "outgoing")) {
confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
} else if (!strcasecmp(v->value, "both") || ast_true(v->value))
confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
} else if (!strcasecmp(v->name, "echocancel")) {
process_echocancel(confp, v->value, v->lineno);
} else if (!strcasecmp(v->name, "echotraining")) {
if (sscanf(v->value, "%30d", &y) == 1) {
if ((y < 10) || (y > 4000)) {
ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
} else {
confp->chan.echotraining = y;
}
} else if (ast_true(v->value)) {
confp->chan.echotraining = 400;
} else
confp->chan.echotraining = 0;
} else if (!strcasecmp(v->name, "hidecallerid")) {
confp->chan.hidecallerid = ast_true(v->value);
} else if (!strcasecmp(v->name, "hidecalleridname")) {
confp->chan.hidecalleridname = ast_true(v->value);
} else if (!strcasecmp(v->name, "pulsedial")) {
confp->chan.pulse = ast_true(v->value);
} else if (!strcasecmp(v->name, "callreturn")) {
confp->chan.callreturn = ast_true(v->value);
} else if (!strcasecmp(v->name, "callwaiting")) {
confp->chan.callwaiting = ast_true(v->value);
} else if (!strcasecmp(v->name, "callwaitingcallerid")) {
confp->chan.callwaitingcallerid = ast_true(v->value);
} else if (!strcasecmp(v->name, "context")) {
ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
} else if (!strcasecmp(v->name, "language")) {
ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
} else if (!strcasecmp(v->name, "progzone")) {
ast_copy_string(progzone, v->value, sizeof(progzone));
} else if (!strcasecmp(v->name, "mohinterpret")
||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
} else if (!strcasecmp(v->name, "mohsuggest")) {
ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
} else if (!strcasecmp(v->name, "parkinglot")) {
ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
} else if (!strcasecmp(v->name, "stripmsd")) {
ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
confp->chan.stripmsd = atoi(v->value);
} else if (!strcasecmp(v->name, "jitterbuffers")) {
numbufs = atoi(v->value);
} else if (!strcasecmp(v->name, "group")) {
confp->chan.group = ast_get_group(v->value);
} else if (!strcasecmp(v->name, "callgroup")) {
if (!strcasecmp(v->value, "none"))
confp->chan.callgroup = 0;
else
confp->chan.callgroup = ast_get_group(v->value);
} else if (!strcasecmp(v->name, "pickupgroup")) {
if (!strcasecmp(v->value, "none"))
confp->chan.pickupgroup = 0;
else
confp->chan.pickupgroup = ast_get_group(v->value);
} else if (!strcasecmp(v->name, "setvar")) {
char *varname = ast_strdupa(v->value), *varval = NULL;
struct ast_variable *tmpvar;
if (varname && (varval = strchr(varname, '='))) {
*varval++ = '\0';
if ((tmpvar = ast_variable_new(varname, varval, ""))) {
tmpvar->next = confp->chan.vars;
confp->chan.vars = tmpvar;
}
}
} else if (!strcasecmp(v->name, "immediate")) {
confp->chan.immediate = ast_true(v->value);
} else if (!strcasecmp(v->name, "transfertobusy")) {
confp->chan.transfertobusy = ast_true(v->value);
} else if (!strcasecmp(v->name, "mwimonitor")) {
confp->chan.mwimonitor_neon = 0;
confp->chan.mwimonitor_fsk = 0;
confp->chan.mwimonitor_rpas = 0;
if (strcasestr(v->value, "fsk")) {
confp->chan.mwimonitor_fsk = 1;
}
if (strcasestr(v->value, "rpas")) {
confp->chan.mwimonitor_rpas = 1;
}
if (strcasestr(v->value, "neon")) {
confp->chan.mwimonitor_neon = 1;
}
/* If set to true or yes, assume that simple fsk is desired */
if (ast_true(v->value)) {
confp->chan.mwimonitor_fsk = 1;
}
} else if (!strcasecmp(v->name, "cid_rxgain")) {
if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
}
} else if (!strcasecmp(v->name, "rxgain")) {
if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
}
} else if (!strcasecmp(v->name, "txgain")) {
if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
}
} else if (!strcasecmp(v->name, "tonezone")) {
if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
}
} else if (!strcasecmp(v->name, "callerid")) {
if (!strcasecmp(v->value, "asreceived")) {
confp->chan.cid_num[0] = '\0';
confp->chan.cid_name[0] = '\0';
} else {
ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
}
} else if (!strcasecmp(v->name, "fullname")) {
ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
} else if (!strcasecmp(v->name, "cid_number")) {
ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
} else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
confp->chan.dahditrcallerid = ast_true(v->value);
} else if (!strcasecmp(v->name, "restrictcid")) {
confp->chan.restrictcid = ast_true(v->value);
} else if (!strcasecmp(v->name, "usecallingpres")) {
confp->chan.use_callingpres = ast_true(v->value);
} else if (!strcasecmp(v->name, "accountcode")) {
ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
} else if (!strcasecmp(v->name, "amaflags")) {
y = ast_cdr_amaflags2int(v->value);
if (y < 0)
ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
else
confp->chan.amaflags = y;
} else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
confp->chan.polarityonanswerdelay = atoi(v->value);
} else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
confp->chan.answeronpolarityswitch = ast_true(v->value);
} else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
confp->chan.hanguponpolarityswitch = ast_true(v->value);
} else if (!strcasecmp(v->name, "sendcalleridafter")) {
confp->chan.sendcalleridafter = atoi(v->value);
} else if (!strcasecmp(v->name, "mwimonitornotify")) {
ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
} else if (!strcasecmp(v->name, "mwisendtype")) {
#ifndef HAVE_DAHDI_LINEREVERSE_VMWI /* backward compatibility for older dahdi VMWI implementation */
if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
mwisend_rpas = 1;
} else {
mwisend_rpas = 0;
}
#else
/* Default is fsk, to turn it off you must specify nofsk */
memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
if (strcasestr(v->value, "nofsk")) { /* NoFSK */
confp->chan.mwisend_fsk = 0;
} else { /* Default FSK */
confp->chan.mwisend_fsk = 1;
}
if (strcasestr(v->value, "rpas")) { /* Ring Pulse Alert Signal, normally followed by FSK */
confp->chan.mwisend_rpas = 1;
} else {
confp->chan.mwisend_rpas = 0;
}
if (strcasestr(v->value, "lrev")) { /* Line Reversal */
confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
}
if (strcasestr(v->value, "hvdc")) { /* HV 90VDC */
confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
}
if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){ /* 90V DC pulses */
confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
}
#endif
} else if (reload != 1) {
if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
int orig_radio = confp->chan.radio;
int orig_outsigmod = confp->chan.outsigmod;
int orig_auto = confp->is_sig_auto;
confp->chan.radio = 0;
confp->chan.outsigmod = -1;
confp->is_sig_auto = 0;
if (!strcasecmp(v->value, "em")) {
confp->chan.sig = SIG_EM;
} else if (!strcasecmp(v->value, "em_e1")) {
confp->chan.sig = SIG_EM_E1;
} else if (!strcasecmp(v->value, "em_w")) {
confp->chan.sig = SIG_EMWINK;
} else if (!strcasecmp(v->value, "fxs_ls")) {
confp->chan.sig = SIG_FXSLS;
} else if (!strcasecmp(v->value, "fxs_gs")) {
confp->chan.sig = SIG_FXSGS;
} else if (!strcasecmp(v->value, "fxs_ks")) {
confp->chan.sig = SIG_FXSKS;
} else if (!strcasecmp(v->value, "fxo_ls")) {
confp->chan.sig = SIG_FXOLS;
} else if (!strcasecmp(v->value, "fxo_gs")) {
confp->chan.sig = SIG_FXOGS;
} else if (!strcasecmp(v->value, "fxo_ks")) {
confp->chan.sig = SIG_FXOKS;
} else if (!strcasecmp(v->value, "fxs_rx")) {
confp->chan.sig = SIG_FXSKS;
confp->chan.radio = 1;
} else if (!strcasecmp(v->value, "fxo_rx")) {
confp->chan.sig = SIG_FXOLS;
confp->chan.radio = 1;
} else if (!strcasecmp(v->value, "fxs_tx")) {
confp->chan.sig = SIG_FXSLS;
confp->chan.radio = 1;
} else if (!strcasecmp(v->value, "fxo_tx")) {
confp->chan.sig = SIG_FXOGS;
confp->chan.radio = 1;
} else if (!strcasecmp(v->value, "em_rx")) {
confp->chan.sig = SIG_EM;
confp->chan.radio = 1;
} else if (!strcasecmp(v->value, "em_tx")) {
confp->chan.sig = SIG_EM;
confp->chan.radio = 1;
} else if (!strcasecmp(v->value, "em_rxtx")) {
confp->chan.sig = SIG_EM;
confp->chan.radio = 2;
} else if (!strcasecmp(v->value, "em_txrx")) {
confp->chan.sig = SIG_EM;
confp->chan.radio = 2;
} else if (!strcasecmp(v->value, "sf")) {
confp->chan.sig = SIG_SF;
} else if (!strcasecmp(v->value, "sf_w")) {
confp->chan.sig = SIG_SFWINK;
} else if (!strcasecmp(v->value, "sf_featd")) {
confp->chan.sig = SIG_FEATD;
} else if (!strcasecmp(v->value, "sf_featdmf")) {
confp->chan.sig = SIG_FEATDMF;
} else if (!strcasecmp(v->value, "sf_featb")) {
confp->chan.sig = SIG_SF_FEATB;
} else if (!strcasecmp(v->value, "sf")) {
confp->chan.sig = SIG_SF;
} else if (!strcasecmp(v->value, "sf_rx")) {
confp->chan.sig = SIG_SF;
confp->chan.radio = 1;
} else if (!strcasecmp(v->value, "sf_tx")) {
confp->chan.sig = SIG_SF;
confp->chan.radio = 1;
} else if (!strcasecmp(v->value, "sf_rxtx")) {
confp->chan.sig = SIG_SF;
confp->chan.radio = 2;
} else if (!strcasecmp(v->value, "sf_txrx")) {
confp->chan.sig = SIG_SF;
confp->chan.radio = 2;
} else if (!strcasecmp(v->value, "featd")) {
confp->chan.sig = SIG_FEATD;
} else if (!strcasecmp(v->value, "featdmf")) {
confp->chan.sig = SIG_FEATDMF;
} else if (!strcasecmp(v->value, "featdmf_ta")) {
confp->chan.sig = SIG_FEATDMF_TA;
} else if (!strcasecmp(v->value, "e911")) {
confp->chan.sig = SIG_E911;
} else if (!strcasecmp(v->value, "fgccama")) {
confp->chan.sig = SIG_FGC_CAMA;
} else if (!strcasecmp(v->value, "fgccamamf")) {
confp->chan.sig = SIG_FGC_CAMAMF;
} else if (!strcasecmp(v->value, "featb")) {
confp->chan.sig = SIG_FEATB;
#ifdef HAVE_PRI
} else if (!strcasecmp(v->value, "pri_net")) {
confp->chan.sig = SIG_PRI;
confp->pri.nodetype = PRI_NETWORK;
} else if (!strcasecmp(v->value, "pri_cpe")) {
confp->chan.sig = SIG_PRI;
confp->pri.nodetype = PRI_CPE;
} else if (!strcasecmp(v->value, "bri_cpe")) {
confp->chan.sig = SIG_BRI;
confp->pri.nodetype = PRI_CPE;
} else if (!strcasecmp(v->value, "bri_net")) {
confp->chan.sig = SIG_BRI;
confp->pri.nodetype = PRI_NETWORK;
} else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
confp->chan.sig = SIG_BRI_PTMP;
confp->pri.nodetype = PRI_CPE;
} else if (!strcasecmp(v->value, "bri_net_ptmp")) {
ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
} else if (!strcasecmp(v->value, "gr303fxoks_net")) {
confp->chan.sig = SIG_GR303FXOKS;
confp->pri.nodetype = PRI_NETWORK;
} else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
confp->chan.sig = SIG_GR303FXSKS;
confp->pri.nodetype = PRI_CPE;
#endif
#ifdef HAVE_SS7
} else if (!strcasecmp(v->value, "ss7")) {
confp->chan.sig = SIG_SS7;
#endif
#ifdef HAVE_OPENR2
} else if (!strcasecmp(v->value, "mfcr2")) {
confp->chan.sig = SIG_MFCR2;
#endif
} else if (!strcasecmp(v->value, "auto")) {
confp->is_sig_auto = 1;
} else {
confp->chan.outsigmod = orig_outsigmod;
confp->chan.radio = orig_radio;
confp->is_sig_auto = orig_auto;
ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
}
} else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
if (!strcasecmp(v->value, "em")) {
confp->chan.outsigmod = SIG_EM;
} else if (!strcasecmp(v->value, "em_e1")) {
confp->chan.outsigmod = SIG_EM_E1;
} else if (!strcasecmp(v->value, "em_w")) {
confp->chan.outsigmod = SIG_EMWINK;
} else if (!strcasecmp(v->value, "sf")) {
confp->chan.outsigmod = SIG_SF;
} else if (!strcasecmp(v->value, "sf_w")) {
confp->chan.outsigmod = SIG_SFWINK;
} else if (!strcasecmp(v->value, "sf_featd")) {
confp->chan.outsigmod = SIG_FEATD;
} else if (!strcasecmp(v->value, "sf_featdmf")) {
confp->chan.outsigmod = SIG_FEATDMF;
} else if (!strcasecmp(v->value, "sf_featb")) {
confp->chan.outsigmod = SIG_SF_FEATB;
} else if (!strcasecmp(v->value, "sf")) {
confp->chan.outsigmod = SIG_SF;
} else if (!strcasecmp(v->value, "featd")) {
confp->chan.outsigmod = SIG_FEATD;
} else if (!strcasecmp(v->value, "featdmf")) {
confp->chan.outsigmod = SIG_FEATDMF;
} else if (!strcasecmp(v->value, "featdmf_ta")) {
confp->chan.outsigmod = SIG_FEATDMF_TA;
} else if (!strcasecmp(v->value, "e911")) {
confp->chan.outsigmod = SIG_E911;
} else if (!strcasecmp(v->value, "fgccama")) {
confp->chan.outsigmod = SIG_FGC_CAMA;
} else if (!strcasecmp(v->value, "fgccamamf")) {
confp->chan.outsigmod = SIG_FGC_CAMAMF;
} else if (!strcasecmp(v->value, "featb")) {
confp->chan.outsigmod = SIG_FEATB;
} else {
ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
}
#ifdef HAVE_PRI
} else if (!strcasecmp(v->name, "pridialplan")) {
if (!strcasecmp(v->value, "national")) {
confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
} else if (!strcasecmp(v->value, "unknown")) {
confp->pri.dialplan = PRI_UNKNOWN + 1;
} else if (!strcasecmp(v->value, "private")) {
confp->pri.dialplan = PRI_PRIVATE + 1;
} else if (!strcasecmp(v->value, "international")) {
confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
} else if (!strcasecmp(v->value, "local")) {
confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
} else if (!strcasecmp(v->value, "dynamic")) {
confp->pri.dialplan = -1;
} else if (!strcasecmp(v->value, "redundant")) {
confp->pri.dialplan = -2;
} else {
ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
}
} else if (!strcasecmp(v->name, "prilocaldialplan")) {
if (!strcasecmp(v->value, "national")) {
confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
} else if (!strcasecmp(v->value, "unknown")) {
confp->pri.localdialplan = PRI_UNKNOWN + 1;
} else if (!strcasecmp(v->value, "private")) {
confp->pri.localdialplan = PRI_PRIVATE + 1;
} else if (!strcasecmp(v->value, "international")) {
confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
} else if (!strcasecmp(v->value, "local")) {
confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
} else if (!strcasecmp(v->value, "dynamic")) {
confp->pri.localdialplan = -1;
} else if (!strcasecmp(v->value, "redundant")) {
confp->pri.localdialplan = -2;
} else {
ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
}
} else if (!strcasecmp(v->name, "switchtype")) {
if (!strcasecmp(v->value, "national"))
confp->pri.switchtype = PRI_SWITCH_NI2;
else if (!strcasecmp(v->value, "ni1"))
confp->pri.switchtype = PRI_SWITCH_NI1;
else if (!strcasecmp(v->value, "dms100"))
confp->pri.switchtype = PRI_SWITCH_DMS100;
else if (!strcasecmp(v->value, "4ess"))
confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
else if (!strcasecmp(v->value, "5ess"))
confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
else if (!strcasecmp(v->value, "euroisdn"))
confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
else if (!strcasecmp(v->value, "qsig"))
confp->pri.switchtype = PRI_SWITCH_QSIG;
else {
ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
return -1;
}
} else if (!strcasecmp(v->name, "nsf")) {
if (!strcasecmp(v->value, "sdn"))
confp->pri.nsf = PRI_NSF_SDN;
else if (!strcasecmp(v->value, "megacom"))
confp->pri.nsf = PRI_NSF_MEGACOM;
else if (!strcasecmp(v->value, "tollfreemegacom"))
confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
else if (!strcasecmp(v->value, "accunet"))
confp->pri.nsf = PRI_NSF_ACCUNET;
else if (!strcasecmp(v->value, "none"))
confp->pri.nsf = PRI_NSF_NONE;
else {
ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
confp->pri.nsf = PRI_NSF_NONE;
}
} else if (!strcasecmp(v->name, "priindication")) {
if (!strcasecmp(v->value, "outofband"))
confp->chan.priindication_oob = 1;
else if (!strcasecmp(v->value, "inband"))
confp->chan.priindication_oob = 0;
else
ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
v->value, v->lineno);
} else if (!strcasecmp(v->name, "priexclusive")) {
confp->chan.priexclusive = ast_true(v->value);
} else if (!strcasecmp(v->name, "internationalprefix")) {
ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
} else if (!strcasecmp(v->name, "nationalprefix")) {
ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
} else if (!strcasecmp(v->name, "localprefix")) {
ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
} else if (!strcasecmp(v->name, "privateprefix")) {
ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
} else if (!strcasecmp(v->name, "unknownprefix")) {
ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
} else if (!strcasecmp(v->name, "resetinterval")) {
if (!strcasecmp(v->value, "never"))
confp->pri.resetinterval = -1;
else if (atoi(v->value) >= 60)
confp->pri.resetinterval = atoi(v->value);
else
ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
v->value, v->lineno);
} else if (!strcasecmp(v->name, "minunused")) {
confp->pri.minunused = atoi(v->value);
} else if (!strcasecmp(v->name, "minidle")) {
confp->pri.minidle = atoi(v->value);
} else if (!strcasecmp(v->name, "idleext")) {
ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
} else if (!strcasecmp(v->name, "idledial")) {
ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
} else if (!strcasecmp(v->name, "overlapdial")) {
if (ast_true(v->value)) {
confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
} else if (!strcasecmp(v->value, "incoming")) {
confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
} else if (!strcasecmp(v->value, "outgoing")) {
confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
} else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
} else {
confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
}
#ifdef HAVE_PRI_PROG_W_CAUSE
} else if (!strcasecmp(v->name, "qsigchannelmapping")) {
if (!strcasecmp(v->value, "logical")) {
confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
} else if (!strcasecmp(v->value, "physical")) {
confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
} else {
confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
}
#endif
} else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
confp->pri.discardremoteholdretrieval = ast_true(v->value);
#ifdef HAVE_PRI_INBANDDISCONNECT
} else if (!strcasecmp(v->name, "inbanddisconnect")) {
confp->pri.inbanddisconnect = ast_true(v->value);
#endif
} else if (!strcasecmp(v->name, "pritimer")) {
#ifdef PRI_GETSET_TIMERS
char tmp[20];
char *timerc;
char *c;
int timer;
int timeridx;
ast_copy_string(tmp, v->value, sizeof(tmp));
c = tmp;
timerc = strsep(&c, ",");
if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
timeridx = pri_timer2idx(timerc);
timer = atoi(c);
if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
ast_log(LOG_WARNING,
"'%s' is not a valid ISDN timer at line %d.\n", timerc,
v->lineno);
} else if (!timer) {
ast_log(LOG_WARNING,
"'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
c, timerc, v->lineno);
} else {
pritimers[timeridx] = timer;
}
} else {
ast_log(LOG_WARNING,
"'%s' is not a valid ISDN timer configuration string at line %d.\n",
v->value, v->lineno);
}
} else if (!strcasecmp(v->name, "facilityenable")) {
confp->pri.facilityenable = ast_true(v->value);
#endif /* PRI_GETSET_TIMERS */
#endif /* HAVE_PRI */
#ifdef HAVE_SS7
} else if (!strcasecmp(v->name, "ss7type")) {
if (!strcasecmp(v->value, "itu")) {
cur_ss7type = SS7_ITU;
} else if (!strcasecmp(v->value, "ansi")) {
cur_ss7type = SS7_ANSI;
} else
ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
} else if (!strcasecmp(v->name, "linkset")) {
cur_linkset = atoi(v->value);
} else if (!strcasecmp(v->name, "pointcode")) {
cur_pointcode = parse_pointcode(v->value);
} else if (!strcasecmp(v->name, "adjpointcode")) {
cur_adjpointcode = parse_pointcode(v->value);
} else if (!strcasecmp(v->name, "defaultdpc")) {
cur_defaultdpc = parse_pointcode(v->value);
} else if (!strcasecmp(v->name, "cicbeginswith")) {
cur_cicbeginswith = atoi(v->value);
} else if (!strcasecmp(v->name, "networkindicator")) {
if (!strcasecmp(v->value, "national"))
cur_networkindicator = SS7_NI_NAT;
else if (!strcasecmp(v->value, "national_spare"))
cur_networkindicator = SS7_NI_NAT_SPARE;
else if (!strcasecmp(v->value, "international"))
cur_networkindicator = SS7_NI_INT;
else if (!strcasecmp(v->value, "international_spare"))
cur_networkindicator = SS7_NI_INT_SPARE;
else
cur_networkindicator = -1;
} else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
} else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
} else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
} else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
} else if (!strcasecmp(v->name, "ss7_called_nai")) {
if (!strcasecmp(v->value, "national")) {
confp->ss7.called_nai = SS7_NAI_NATIONAL;
} else if (!strcasecmp(v->value, "international")) {
confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
} else if (!strcasecmp(v->value, "subscriber")) {
confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
} else if (!strcasecmp(v->value, "unknown")) {
confp->ss7.called_nai = SS7_NAI_UNKNOWN;
} else if (!strcasecmp(v->value, "dynamic")) {
confp->ss7.called_nai = SS7_NAI_DYNAMIC;
} else {
ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
}
} else if (!strcasecmp(v->name, "ss7_calling_nai")) {
if (!strcasecmp(v->value, "national")) {
confp->ss7.calling_nai = SS7_NAI_NATIONAL;
} else if (!strcasecmp(v->value, "international")) {
confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
} else if (!strcasecmp(v->value, "subscriber")) {
confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
} else if (!strcasecmp(v->value, "unknown")) {
confp->ss7.calling_nai = SS7_NAI_UNKNOWN;
} else if (!strcasecmp(v->value, "dynamic")) {
confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
} else {
ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
}
} else if (!strcasecmp(v->name, "sigchan")) {
int sigchan, res;
sigchan = atoi(v->value);
res = linkset_addsigchan(sigchan);
if (res < 0)
return -1;
} else if (!strcasecmp(v->name, "ss7_explicitacm")) {
struct dahdi_ss7 *link;
link = ss7_resolve_linkset(cur_linkset);
if (!link) {
ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
return -1;
}
if (ast_true(v->value))
link->flags |= LINKSET_FLAG_EXPLICITACM;
#endif /* HAVE_SS7 */
#ifdef HAVE_OPENR2
} else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
ast_log(LOG_WARNING, "MFC/R2 Protocol file '%s' will be used, you only should use this if you *REALLY KNOW WHAT YOU ARE DOING*.\n", confp->mfcr2.r2proto_file);
} else if (!strcasecmp(v->name, "mfcr2_logdir")) {
ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
} else if (!strcasecmp(v->name, "mfcr2_variant")) {
confp->mfcr2.variant = openr2_proto_get_variant(v->value);
if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
confp->mfcr2.variant = OR2_VAR_ITU;
}
} else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
confp->mfcr2.mfback_timeout = atoi(v->value);
if (!confp->mfcr2.mfback_timeout) {
ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
confp->mfcr2.mfback_timeout = -1;
} else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
}
} else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
confp->mfcr2.metering_pulse_timeout = atoi(v->value);
if (confp->mfcr2.metering_pulse_timeout > 500) {
ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
}
} else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
} else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
} else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
} else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
} else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
} else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
} else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
} else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
#endif
} else if (!strcasecmp(v->name, "mfcr2_call_files")) {
confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
} else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
confp->mfcr2.max_ani = atoi(v->value);
if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
}
} else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
confp->mfcr2.max_dnis = atoi(v->value);
if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
}
} else if (!strcasecmp(v->name, "mfcr2_category")) {
confp->mfcr2.category = openr2_proto_get_category(v->value);
if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
v->value, v->lineno);
}
} else if (!strcasecmp(v->name, "mfcr2_logging")) {
openr2_log_level_t tmplevel;
char *clevel;
char *logval = ast_strdupa(v->value);
while (logval) {
clevel = strsep(&logval,",");
if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
continue;
}
confp->mfcr2.loglevel |= tmplevel;
}
#endif /* HAVE_OPENR2 */
} else if (!strcasecmp(v->name, "cadence")) {
/* setup to scan our argument */
int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int i;
struct dahdi_ring_cadence new_cadence;
int cid_location = -1;
int firstcadencepos = 0;
char original_args[80];
int cadence_is_ok = 1;
ast_copy_string(original_args, v->value, sizeof(original_args));
/* 16 cadences allowed (8 pairs) */
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]);
/* Cadence must be even (on/off) */
if (element_count % 2 == 1) {
ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
cadence_is_ok = 0;
}
/* Ring cadences cannot be negative */
for (i = 0; i < element_count; i++) {
if (c[i] == 0) {
ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
cadence_is_ok = 0;
break;
} else if (c[i] < 0) {
if (i % 2 == 1) {
/* Silence duration, negative possibly okay */
if (cid_location == -1) {
cid_location = i;
c[i] *= -1;
} else {
ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
cadence_is_ok = 0;
break;
}
} else {
if (firstcadencepos == 0) {
firstcadencepos = i; /* only recorded to avoid duplicate specification */
/* duration will be passed negative to the DAHDI driver */
} else {
ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
cadence_is_ok = 0;
break;
}
}
}
}
/* Substitute our scanned cadence */
for (i = 0; i < 16; i++) {
new_cadence.ringcadence[i] = c[i];
}
if (cadence_is_ok) {
/* ---we scanned it without getting annoyed; now some sanity checks--- */
if (element_count < 2) {
ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
} else {
if (cid_location == -1) {
/* user didn't say; default to first pause */
cid_location = 1;
} else {
/* convert element_index to cidrings value */
cid_location = (cid_location + 1) / 2;
}
/* ---we like their cadence; try to install it--- */
if (!user_has_defined_cadences++)
/* this is the first user-defined cadence; clear the default user cadences */
num_cadence = 0;
if ((num_cadence+1) >= NUM_CADENCE_MAX)
ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
else {
cadences[num_cadence] = new_cadence;
cidrings[num_cadence++] = cid_location;
ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
}
}
}
} else if (!strcasecmp(v->name, "ringtimeout")) {
ringt_base = (atoi(v->value) * 8) / READ_SIZE;
} else if (!strcasecmp(v->name, "prewink")) {
confp->timing.prewinktime = atoi(v->value);
} else if (!strcasecmp(v->name, "preflash")) {
confp->timing.preflashtime = atoi(v->value);
} else if (!strcasecmp(v->name, "wink")) {
confp->timing.winktime = atoi(v->value);
} else if (!strcasecmp(v->name, "flash")) {
confp->timing.flashtime = atoi(v->value);
} else if (!strcasecmp(v->name, "start")) {
confp->timing.starttime = atoi(v->value);
} else if (!strcasecmp(v->name, "rxwink")) {
confp->timing.rxwinktime = atoi(v->value);
} else if (!strcasecmp(v->name, "rxflash")) {
confp->timing.rxflashtime = atoi(v->value);
} else if (!strcasecmp(v->name, "debounce")) {
confp->timing.debouncetime = atoi(v->value);
} else if (!strcasecmp(v->name, "toneduration")) {
int toneduration;
int ctlfd;
int res;
struct dahdi_dialparams dps;
ctlfd = open("/dev/dahdi/ctl", O_RDWR);
if (ctlfd == -1) {
ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
return -1;
}
toneduration = atoi(v->value);
if (toneduration > -1) {
memset(&dps, 0, sizeof(dps));
dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
if (res < 0) {
ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
close(ctlfd);
return -1;
}
}
close(ctlfd);
} else if (!strcasecmp(v->name, "defaultcic")) {
ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
} else if (!strcasecmp(v->name, "defaultozz")) {
ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
} else if (!strcasecmp(v->name, "mwilevel")) {
mwilevel = atoi(v->value);
}
} else if (!(options & PROC_DAHDI_OPT_NOWARN) )
ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
}
if (dahdichan[0]) {
/* The user has set 'dahdichan' */
/*< \todo pass proper line number instead of 0 */
if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
return -1;
}
}
/*< \todo why check for the pseudo in the per-channel section.
* Any actual use for manual setup of the pseudo channel? */
if (!found_pseudo && reload != 1) {
/* use the default configuration for a channel, so
that any settings from real configured channels
don't "leak" into the pseudo channel config
*/
struct dahdi_chan_conf conf = dahdi_chan_conf_default();
tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
if (tmp) {
ast_verb(3, "Automatically generated pseudo channel\n");
} else {
ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
}
}
return 0;
}
| static void process_echocancel | ( | struct dahdi_chan_conf * | confp, | |
| const char * | data, | |||
| unsigned int | line | |||
| ) | [static] |
Definition at line 16166 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, LOG_WARNING, name, and dahdi_pvt::params.
Referenced by process_dahdi().
{
char *parse = ast_strdupa(data);
char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
unsigned int param_count;
unsigned int x;
if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
return;
memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
/* first parameter is tap length, process it here */
x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
confp->chan.echocancel.head.tap_length = x;
else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
confp->chan.echocancel.head.tap_length = 128;
/* now process any remaining parameters */
for (x = 1; x < param_count; x++) {
struct {
char *name;
char *value;
} param;
if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
continue;
}
if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
continue;
}
strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
if (param.value) {
if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
continue;
}
}
confp->chan.echocancel.head.param_count++;
}
}
| static char* redirectingreason2str | ( | int | redirectingreason | ) | [static] |
Definition at line 12469 of file chan_dahdi.c.
Referenced by pri_dchannel().
{
switch (redirectingreason) {
case 0:
return "UNKNOWN";
case 1:
return "BUSY";
case 2:
return "NO_REPLY";
case 0xF:
return "UNCONDITIONAL";
default:
return "NOREDIRECT";
}
}
| static int reload | ( | void | ) | [static] |
Definition at line 17581 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and setup_dahdi().
{
int res = 0;
res = setup_dahdi(1);
if (res) {
ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
return -1;
}
return 0;
}
| static int reset_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2592 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_pvt::confno, dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_hangup().
{
p->confno = -1;
memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
if (p->subs[SUB_REAL].dfd > -1) {
struct dahdi_confinfo zi;
memset(&zi, 0, sizeof(zi));
if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
}
return 0;
}
| static int restart_monitor | ( | void | ) | [static] |
Definition at line 9818 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, LOG_WARNING, and monlock.
Referenced by dahdi_hangup(), dahdi_request(), and setup_dahdi().
{
/* If we're supposed to be stopped -- stay stopped */
if (monitor_thread == AST_PTHREADT_STOP)
return 0;
ast_mutex_lock(&monlock);
if (monitor_thread == pthread_self()) {
ast_mutex_unlock(&monlock);
ast_log(LOG_WARNING, "Cannot kill myself\n");
return -1;
}
if (monitor_thread != AST_PTHREADT_NULL) {
/* Wake up the thread */
pthread_kill(monitor_thread, SIGURG);
} else {
/* Start a new monitor */
if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
ast_mutex_unlock(&monlock);
ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
return -1;
}
}
ast_mutex_unlock(&monlock);
return 0;
}
| static int restore_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2971 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_subchannel::dfd, errno, LOG_WARNING, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_handle_event(), dahdi_read(), and send_callerid().
| static int restore_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2852 of file chan_dahdi.c.
References ast_log(), dahdi_subchannel::dfd, 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().
{
int res;
res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
if (res) {
ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
return -1;
}
return 0;
}
| static int save_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2898 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_subchannel::dfd, errno, LOG_WARNING, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_callwait(), and dahdi_handle_event().
{
struct dahdi_confinfo c;
int res;
if (p->saveconf.confmode) {
ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
return -1;
}
p->saveconf.chan = 0;
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
if (res) {
ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
p->saveconf.confmode = 0;
return -1;
}
memset(&c, 0, sizeof(c));
c.confmode = DAHDI_CONF_NORMAL;
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
if (res) {
ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
return -1;
}
ast_debug(1, "Disabled conferencing\n");
return 0;
}
| static int send_callerid | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3028 of file chan_dahdi.c.
References ast_free, ast_log(), dahdi_pvt::callwaitcas, dahdi_pvt::cidcwexpire, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_setlinear(), dahdi_subchannel::dfd, 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().
{
/* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
int res;
/* Take out of linear mode if necessary */
if (p->subs[SUB_REAL].linear) {
p->subs[SUB_REAL].linear = 0;
dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
}
while (p->cidpos < p->cidlen) {
res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
if (res < 0) {
if (errno == EAGAIN)
return 0;
else {
ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
return -1;
}
}
if (!res)
return 0;
p->cidpos += res;
}
ast_free(p->cidspill);
p->cidspill = NULL;
if (p->callwaitcas) {
/* Wait for CID/CW to expire */
p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
} else
restore_conference(p);
return 0;
}
| static int send_cwcidspill | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2988 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().
{
p->callwaitcas = 0;
p->cidcwexpire = 0;
if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
return -1;
p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
/* Make sure we account for the end */
p->cidlen += READ_SIZE * 4;
p->cidpos = 0;
send_callerid(p);
ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
return 0;
}
| static int set_actual_gain | ( | int | fd, | |
| int | chan, | |||
| float | rxgain, | |||
| float | txgain, | |||
| int | law | |||
| ) | [static] |
Definition at line 2833 of file chan_dahdi.c.
References set_actual_rxgain(), and set_actual_txgain().
Referenced by bump_gains(), dahdi_call(), mkintf(), pri_dchannel(), and restore_gains().
{
return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
}
| static int set_actual_rxgain | ( | int | fd, | |
| int | chan, | |||
| float | gain, | |||
| int | law | |||
| ) | [static] |
Definition at line 2815 of file chan_dahdi.c.
References ast_debug, errno, and fill_rxgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
{
struct dahdi_gains g;
int res;
memset(&g, 0, sizeof(g));
g.chan = chan;
res = ioctl(fd, DAHDI_GETGAINS, &g);
if (res) {
ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
return res;
}
fill_rxgain(&g, gain, law);
return ioctl(fd, DAHDI_SETGAINS, &g);
}
| static int set_actual_txgain | ( | int | fd, | |
| int | chan, | |||
| float | gain, | |||
| int | law | |||
| ) | [static] |
Definition at line 2797 of file chan_dahdi.c.
References ast_debug, errno, and fill_txgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
{
struct dahdi_gains g;
int res;
memset(&g, 0, sizeof(g));
g.chan = chan;
res = ioctl(fd, DAHDI_GETGAINS, &g);
if (res) {
ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
return res;
}
fill_txgain(&g, gain, law);
return ioctl(fd, DAHDI_SETGAINS, &g);
}
| static int setup_dahdi | ( | int | reload | ) | [static] |
Definition at line 17180 of file chan_dahdi.c.
References ast_category_browse(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, dahdi_chan_conf_default(), global_jbconf, iflock, ast_variable::lineno, linksets, LOG_ERROR, LOG_NOTICE, LOG_WARNING, master, ast_variable::name, ast_variable::next, NUM_DCHANS, pri_create_spanmap(), pri_create_trunkgroup(), pris, PROC_DAHDI_OPT_NOCHAN, PROC_DAHDI_OPT_NOWARN, process_dahdi(), pvts, restart_monitor(), ss7_linkset(), start_pri(), and ast_variable::value.
Referenced by dahdi_restart(), load_module(), and reload().
{
struct ast_config *cfg, *ucfg;
struct ast_variable *v;
struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
struct dahdi_chan_conf conf;
struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
const char *cat;
int res;
#ifdef HAVE_PRI
char *c;
int spanno;
int i;
int logicalspan;
int trunkgroup;
int dchannels[NUM_DCHANS];
#endif
cfg = ast_config_load(config, config_flags);
/* Error if we have no config file */
if (!cfg) {
ast_log(LOG_ERROR, "Unable to load config %s\n", config);
return 0;
} else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
ucfg = ast_config_load("users.conf", config_flags);
if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
return 0;
} else if (ucfg == CONFIG_STATUS_FILEINVALID) {
ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
return 0;
}
ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
ast_config_destroy(ucfg);
return 0;
}
} else if (cfg == CONFIG_STATUS_FILEINVALID) {
ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
return 0;
} else {
ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
ast_config_destroy(cfg);
return 0;
}
}
/* It's a little silly to lock it, but we mind as well just to be sure */
ast_mutex_lock(&iflock);
#ifdef HAVE_PRI
if (reload != 1) {
/* Process trunkgroups first */
v = ast_variable_browse(cfg, "trunkgroups");
while (v) {
if (!strcasecmp(v->name, "trunkgroup")) {
trunkgroup = atoi(v->value);
if (trunkgroup > 0) {
if ((c = strchr(v->value, ','))) {
i = 0;
memset(dchannels, 0, sizeof(dchannels));
while (c && (i < NUM_DCHANS)) {
dchannels[i] = atoi(c + 1);
if (dchannels[i] < 0) {
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);
} else
i++;
c = strchr(c + 1, ',');
}
if (i) {
if (pri_create_trunkgroup(trunkgroup, dchannels)) {
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);
} else
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");
} else
ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
} else
ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
} else
ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
} else if (!strcasecmp(v->name, "spanmap")) {
spanno = atoi(v->value);
if (spanno > 0) {
if ((c = strchr(v->value, ','))) {
trunkgroup = atoi(c + 1);
if (trunkgroup > 0) {
if ((c = strchr(c + 1, ',')))
logicalspan = atoi(c + 1);
else
logicalspan = 0;
if (logicalspan >= 0) {
if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
} else
ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
} else
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);
} else
ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
} else
ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
} else
ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
} else {
ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
}
v = v->next;
}
}
#endif
/* Copy the default jb config over global_jbconf */
memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
mwimonitornotify[0] = '\0';
v = ast_variable_browse(cfg, "channels");
if ((res = process_dahdi(&base_conf, "", v, reload, 0))) {
ast_mutex_unlock(&iflock);
ast_config_destroy(cfg);
if (ucfg) {
ast_config_destroy(ucfg);
}
return res;
}
/* Now get configuration from all normal sections in chan_dahdi.conf: */
for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
/* [channels] and [trunkgroups] are used. Let's also reserve
* [globals] and [general] for future use
*/
if (!strcasecmp(cat, "general") ||
!strcasecmp(cat, "trunkgroups") ||
!strcasecmp(cat, "globals") ||
!strcasecmp(cat, "channels")) {
continue;
}
memcpy(&conf, &base_conf, sizeof(conf));
if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
ast_mutex_unlock(&iflock);
ast_config_destroy(cfg);
if (ucfg) {
ast_config_destroy(ucfg);
}
return res;
}
}
ast_config_destroy(cfg);
if (ucfg) {
const char *chans;
process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
if (!strcasecmp(cat, "general")) {
continue;
}
chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
if (ast_strlen_zero(chans)) {
continue;
}
memcpy(&conf, &base_conf, sizeof(conf));
if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
ast_config_destroy(ucfg);
ast_mutex_unlock(&iflock);
return res;
}
}
ast_config_destroy(ucfg);
}
ast_mutex_unlock(&iflock);
#ifdef HAVE_PRI
if (reload != 1) {
int x;
for (x = 0; x < NUM_SPANS; x++) {
if (pris[x].pvts[0]) {
if (start_pri(pris + x)) {
ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
return -1;
} else
ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
}
}
}
#endif
#ifdef HAVE_SS7
if (reload != 1) {
int x;
for (x = 0; x < NUM_SPANS; x++) {
if (linksets[x].ss7) {
if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
return -1;
} else
ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
}
}
}
#endif
#ifdef HAVE_OPENR2
if (reload != 1) {
int x;
for (x = 0; x < r2links_count; x++) {
if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
return -1;
} else {
ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
}
}
}
#endif
/* And start the monitor for the first time */
restart_monitor();
return 0;
}
| static int sigtype_to_signalling | ( | int | sigtype | ) | [static] |
| static void ss7_apply_plan_to_number | ( | char * | buf, | |
| size_t | size, | |||
| const struct dahdi_ss7 * | ss7, | |||
| const char * | number, | |||
| const unsigned | nai | |||
| ) | [static] |
Definition at line 11478 of file chan_dahdi.c.
References ast_strlen_zero(), dahdi_ss7::internationalprefix, dahdi_ss7::nationalprefix, dahdi_ss7::subscriberprefix, and dahdi_ss7::unknownprefix.
Referenced by ss7_linkset().
{
if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
if (size) {
*buf = '\0';
}
return;
}
switch (nai) {
case SS7_NAI_INTERNATIONAL:
snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
break;
case SS7_NAI_NATIONAL:
snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
break;
case SS7_NAI_SUBSCRIBER:
snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
break;
case SS7_NAI_UNKNOWN:
snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
break;
default:
snprintf(buf, size, "%s", number);
break;
}
}
| static void ss7_block_cics | ( | struct dahdi_ss7 * | linkset, | |
| int | startcic, | |||
| int | endcic, | |||
| unsigned int | dpc, | |||
| unsigned char | state[], | |||
| int | block | |||
| ) | [inline, static] |
Definition at line 11287 of file chan_dahdi.c.
References dahdi_pvt::cic, dahdi_pvt::dpc, dahdi_ss7::numchans, dahdi_ss7::pvts, and dahdi_pvt::remotelyblocked.
Referenced by ss7_linkset().
{
int i;
for (i = 0; i < linkset->numchans; i++) {
if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
if (state) {
if (state[i])
linkset->pvts[i]->remotelyblocked = block;
} else
linkset->pvts[i]->remotelyblocked = block;
}
}
}
| static int ss7_find_cic | ( | struct dahdi_ss7 * | linkset, | |
| int | cic, | |||
| unsigned int | dpc | |||
| ) | [static] |
Definition at line 11222 of file chan_dahdi.c.
References dahdi_pvt::cic, dahdi_pvt::dpc, dahdi_ss7::numchans, and dahdi_ss7::pvts.
Referenced by ss7_linkset().
Definition at line 1458 of file chan_dahdi.c.
References ast_mutex_trylock(), AST_PTHREADT_NULL, DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_ss7::lock, and dahdi_ss7::master.
Referenced by dahdi_answer(), dahdi_call(), dahdi_hangup(), and dahdi_indicate().
{
int res;
/* Grab the lock first */
do {
res = ast_mutex_trylock(&pri->lock);
if (res) {
DEADLOCK_AVOIDANCE(&pvt->lock);
}
} while (res);
/* Then break the poll */
if (pri->master != AST_PTHREADT_NULL)
pthread_kill(pri->master, SIGURG);
return 0;
}
| static void ss7_handle_cqm | ( | struct dahdi_ss7 * | linkset, | |
| int | startcic, | |||
| int | endcic, | |||
| unsigned int | dpc | |||
| ) | [static] |
Definition at line 11237 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::cic, dahdi_pvt::dpc, dahdi_pvt::locallyblocked, LOG_WARNING, dahdi_ss7::numchans, dahdi_pvt::outgoing, dahdi_ss7::pvts, dahdi_pvt::remotelyblocked, dahdi_ss7::ss7, dahdi_pvt::ss7call, and status.
Referenced by ss7_linkset().
{
unsigned char status[32];
struct dahdi_pvt *p = NULL;
int i, offset;
for (i = 0; i < linkset->numchans; i++) {
if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
p = linkset->pvts[i];
offset = p->cic - startcic;
status[offset] = 0;
if (p->locallyblocked)
status[offset] |= (1 << 0) | (1 << 4);
if (p->remotelyblocked)
status[offset] |= (1 << 1) | (1 << 5);
if (p->ss7call) {
if (p->outgoing)
status[offset] |= (1 << 3);
else
status[offset] |= (1 << 2);
} else
status[offset] |= 0x3 << 2;
}
}
if (p)
isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
else
ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
}
| static void ss7_hangup_cics | ( | struct dahdi_ss7 * | linkset, | |
| int | startcic, | |||
| int | endcic, | |||
| unsigned int | dpc | |||
| ) | [inline, static] |
Definition at line 11271 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::cic, dahdi_pvt::dpc, dahdi_pvt::lock, dahdi_ss7::numchans, dahdi_pvt::owner, and dahdi_ss7::pvts.
Referenced by ss7_linkset().
{
int i;
for (i = 0; i < linkset->numchans; i++) {
if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
ast_mutex_lock(&linkset->pvts[i]->lock);
if (linkset->pvts[i]->owner)
linkset->pvts[i]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
ast_mutex_unlock(&linkset->pvts[i]->lock);
}
}
}
| static void ss7_inservice | ( | struct dahdi_ss7 * | linkset, | |
| int | startcic, | |||
| int | endcic, | |||
| unsigned int | dpc | |||
| ) | [static] |
Definition at line 11304 of file chan_dahdi.c.
References dahdi_pvt::cic, dahdi_pvt::dpc, dahdi_pvt::inservice, dahdi_ss7::numchans, and dahdi_ss7::pvts.
Referenced by ss7_linkset().
| static void* ss7_linkset | ( | void * | data | ) | [static] |
Definition at line 11514 of file chan_dahdi.c.
References ast_channel::_softhangup, dahdi_pvt::alerting, dahdi_pvt::alreadyhungup, AST_CAUSE_UNALLOCATED, ast_copy_string(), ast_debug, ast_dsp_set_features(), ast_exists_extension(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), ast_tvnow(), ast_verbose(), dahdi_ss7::called_nai, dahdi_ss7::calling_nai, dahdi_pvt::calling_party_cat, dahdi_pvt::callingpres, dahdi_pvt::charge_number, dahdi_pvt::cic, dahdi_pvt::cid_ani, dahdi_pvt::cid_ani2, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_ton, dahdi_pvt::context, dahdi_enable_ec(), dahdi_loopback(), dahdi_queue_frame(), dahdi_pvt::dialing, dahdi_pvt::dnid, dahdi_pvt::dpc, dahdi_pvt::dsp, dahdi_pvt::dsp_features, errno, dahdi_pvt::exten, dahdi_ss7::fds, dahdi_pvt::gen_add_nai, dahdi_pvt::gen_add_num_plan, dahdi_pvt::gen_add_number, dahdi_pvt::gen_add_pres_ind, dahdi_pvt::gen_add_type, dahdi_pvt::gen_dig_number, dahdi_pvt::gen_dig_scheme, dahdi_pvt::gen_dig_type, dahdi_pvt::generic_name, ast_channel::hangupcause, dahdi_pvt::immediate, dahdi_pvt::inalarm, dahdi_pvt::inservice, dahdi_pvt::jip_number, dahdi_ss7::linkstate, LINKSTATE_DOWN, LINKSTATE_INALARM, dahdi_pvt::locallyblocked, dahdi_pvt::lock, dahdi_ss7::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, dahdi_pvt::loopedback, dahdi_subchannel::needanswer, dahdi_subchannel::needringing, dahdi_ss7::numchans, dahdi_ss7::numsigchans, dahdi_pvt::orig_called_num, dahdi_pvt::owner, dahdi_pvt::proceeding, dahdi_pvt::progress, dahdi_ss7::pvts, dahdi_pvt::redirecting_num, dahdi_pvt::remotelyblocked, dahdi_pvt::restartpending, dahdi_pvt::rlt, dahdi_ss7::ss7, ss7_apply_plan_to_number(), ss7_block_cics(), ss7_find_cic(), ss7_handle_cqm(), ss7_hangup_cics(), ss7_inservice(), ss7_pres_scr2cid_pres(), ss7_reset_linkset(), ss7_start_call(), dahdi_pvt::ss7call, dahdi_ss7::state, dahdi_pvt::subs, tv, and dahdi_pvt::use_callerid.
Referenced by setup_dahdi().
{
int res, i;
struct timeval *next = NULL, tv;
struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
struct ss7 *ss7 = linkset->ss7;
ss7_event *e = NULL;
struct dahdi_pvt *p;
int chanpos;
struct pollfd pollers[NUM_DCHANS];
int cic;
unsigned int dpc;
int nextms = 0;
ss7_start(ss7);
while(1) {
ast_mutex_lock(&linkset->lock);
if ((next = ss7_schedule_next(ss7))) {
tv = ast_tvnow();
tv.tv_sec = next->tv_sec - tv.tv_sec;
tv.tv_usec = next->tv_usec - tv.tv_usec;
if (tv.tv_usec < 0) {
tv.tv_usec += 1000000;
tv.tv_sec -= 1;
}
if (tv.tv_sec < 0) {
tv.tv_sec = 0;
tv.tv_usec = 0;
}
nextms = tv.tv_sec * 1000;
nextms += tv.tv_usec / 1000;
}
ast_mutex_unlock(&linkset->lock);
for (i = 0; i < linkset->numsigchans; i++) {
pollers[i].fd = linkset->fds[i];
pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
pollers[i].revents = 0;
}
res = poll(pollers, linkset->numsigchans, nextms);
if ((res < 0) && (errno != EINTR)) {
ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
} else if (!res) {
ast_mutex_lock(&linkset->lock);
ss7_schedule_run(ss7);
ast_mutex_unlock(&linkset->lock);
continue;
}
ast_mutex_lock(&linkset->lock);
for (i = 0; i < linkset->numsigchans; i++) {
if (pollers[i].revents & POLLPRI) {
int x;
if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) {
ast_log(LOG_ERROR, "Error in exception retrieval!\n");
}
switch (x) {
case DAHDI_EVENT_OVERRUN:
ast_debug(1, "Overrun detected!\n");
break;
case DAHDI_EVENT_BADFCS:
ast_debug(1, "Bad FCS\n");
break;
case DAHDI_EVENT_ABORT:
ast_debug(1, "HDLC Abort\n");
break;
case DAHDI_EVENT_ALARM:
ast_log(LOG_ERROR, "Alarm on link!\n");
linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
linkset->linkstate[i] &= ~LINKSTATE_UP;
ss7_link_alarm(ss7, pollers[i].fd);
break;
case DAHDI_EVENT_NOALARM:
ast_log(LOG_ERROR, "Alarm cleared on link\n");
linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
linkset->linkstate[i] |= LINKSTATE_STARTING;
ss7_link_noalarm(ss7, pollers[i].fd);
break;
default:
ast_log(LOG_ERROR, "Got exception %d!\n", x);
break;
}
}
if (pollers[i].revents & POLLIN) {
res = ss7_read(ss7, pollers[i].fd);
}
if (pollers[i].revents & POLLOUT) {
res = ss7_write(ss7, pollers[i].fd);
if (res < 0) {
ast_debug(1, "Error in write %s\n", strerror(errno));
}
}
}
while ((e = ss7_check_event(ss7))) {
switch (e->e) {
case SS7_EVENT_UP:
if (linkset->state != LINKSET_STATE_UP) {
ast_verbose("--- SS7 Up ---\n");
ss7_reset_linkset(linkset);
}
linkset->state = LINKSET_STATE_UP;
break;
case SS7_EVENT_DOWN:
ast_verbose("--- SS7 Down ---\n");
linkset->state = LINKSET_STATE_DOWN;
for (i = 0; i < linkset->numchans; i++) {
struct dahdi_pvt *p = linkset->pvts[i];
if (p)
p->inalarm = 1;
}
break;
case MTP2_LINK_UP:
ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
break;
case MTP2_LINK_DOWN:
ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
break;
case ISUP_EVENT_CPG:
chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
if (chanpos < 0) {
ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
break;
}
p = linkset->pvts[chanpos];
ast_mutex_lock(&p->lock);
switch (e->cpg.event) {
case CPG_EVENT_ALERTING:
p->alerting = 1;
p->subs[SUB_REAL].needringing = 1;
break;
case CPG_EVENT_PROGRESS:
case CPG_EVENT_INBANDINFO:
{
struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
dahdi_queue_frame(p, &f, linkset);
p->progress = 1;
p->dialing = 0;
if (p->dsp && p->dsp_features) {
ast_dsp_set_features(p->dsp, p->dsp_features);
p->dsp_features = 0;
}
}
break;
default:
ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
}
ast_mutex_unlock(&p->lock);
break;
case ISUP_EVENT_RSC:
ast_verbose("Resetting CIC %d\n", e->rsc.cic);
chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
if (chanpos < 0) {
ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
break;
}
p = linkset->pvts[chanpos];
ast_mutex_lock(&p->lock);
p->inservice = 1;
p->remotelyblocked = 0;
dpc = p->dpc;
isup_set_call_dpc(e->rsc.call, dpc);
if (p->ss7call)
p->ss7call = NULL;
if (p->owner)
p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
ast_mutex_unlock(&p->lock);
isup_rlc(ss7, e->rsc.call);
break;
case ISUP_EVENT_GRS:
ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
if (chanpos < 0) {
ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
break;
}
p = linkset->pvts[chanpos];
isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
ss7_hangup_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc);
break;
case ISUP_EVENT_CQM:
ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
break;
case ISUP_EVENT_GRA:
ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
break;
case ISUP_EVENT_IAM:
ast_debug(1, "Got IAM for CIC %d and called number %s, calling number %s\n", e->iam.cic, e->iam.called_party_num, e->iam.calling_party_num);
chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
if (chanpos < 0) {
ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
isup_rel(ss7, e->iam.call, -1);
break;
}
p = linkset->pvts[chanpos];
ast_mutex_lock(&p->lock);
if (p->owner) {
if (p->ss7call == e->iam.call) {
ast_mutex_unlock(&p->lock);
ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
break;
} else {
ast_mutex_unlock(&p->lock);
ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
break;
}
}
dpc = p->dpc;
p->ss7call = e->iam.call;
isup_set_call_dpc(p->ss7call, dpc);
if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
} else
p->cid_num[0] = 0;
if (p->immediate) {
p->exten[0] = 's';
p->exten[1] = '\0';
} else if (!ast_strlen_zero(e->iam.called_party_num)) {
char *st;
ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
st = strchr(p->exten, '#');
if (st)
*st = '\0';
} else
p->exten[0] = '\0';
p->cid_ani[0] = '\0';
if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
else
p->cid_name[0] = '\0';
p->cid_ani2 = e->iam.oli_ani2;
p->cid_ton = 0;
ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
p->gen_add_type = e->iam.gen_add_type;
p->gen_add_nai = e->iam.gen_add_nai;
p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
p->gen_add_num_plan = e->iam.gen_add_num_plan;
ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
p->gen_dig_type = e->iam.gen_dig_type;
p->gen_dig_scheme = e->iam.gen_dig_scheme;
ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
p->calling_party_cat = e->iam.calling_party_cat;
/* Set DNID */
if (!ast_strlen_zero(e->iam.called_party_num))
ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
if (e->iam.cot_check_required) {
dahdi_loopback(p, 1);
} else
ss7_start_call(p, linkset);
} else {
ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
p->alreadyhungup = 1;
isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED);
}
ast_mutex_unlock(&p->lock);
break;
case ISUP_EVENT_COT:
chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
if (chanpos < 0) {
ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
isup_rel(ss7, e->cot.call, -1);
break;
}
p = linkset->pvts[chanpos];
ast_mutex_lock(&p->lock);
if (p->loopedback) {
dahdi_loopback(p, 0);
ss7_start_call(p, linkset);
}
ast_mutex_unlock(&p->lock);
break;
case ISUP_EVENT_CCR:
ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
if (chanpos < 0) {
ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
break;
}
p = linkset->pvts[chanpos];
ast_mutex_lock(&p->lock);
dahdi_loopback(p, 1);
ast_mutex_unlock(&p->lock);
isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
break;
case ISUP_EVENT_CVT:
ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
if (chanpos < 0) {
ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
break;
}
p = linkset->pvts[chanpos];
ast_mutex_lock(&p->lock);
dahdi_loopback(p, 1);
ast_mutex_unlock(&p->lock);
isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
break;
case ISUP_EVENT_REL:
chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
if (chanpos < 0) {
ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
break;
}
p = linkset->pvts[chanpos];
ast_mutex_lock(&p->lock);
if (p->owner) {
p->owner->hangupcause = e->rel.cause;
p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
} else if (!p->restartpending)
ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
/* End the loopback if we have one */
dahdi_loopback(p, 0);
isup_rlc(ss7, e->rel.call);
p->ss7call = NULL;
ast_mutex_unlock(&p->lock);
break;
case ISUP_EVENT_ACM:
chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
if (chanpos < 0) {
ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
isup_rel(ss7, e->acm.call, -1);
break;
} else {
struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
p = linkset->pvts[chanpos];
ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
if (e->acm.call_ref_ident > 0) {
p->rlt = 1; /* Setting it but not using it here*/
}
ast_mutex_lock(&p->lock);
dahdi_queue_frame(p, &f, linkset);
p->proceeding = 1;
p->dialing = 0;
/* Send alerting if subscriber is free */
if (e->acm.called_party_status_ind == 1) {
p->alerting = 1;
p->subs[SUB_REAL].needringing = 1;
}
ast_mutex_unlock(&p->lock);
}
break;
case ISUP_EVENT_CGB:
chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
if (chanpos < 0) {
ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
break;
}
p = linkset->pvts[chanpos];
ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
break;
case ISUP_EVENT_CGU:
chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
if (chanpos < 0) {
ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
break;
}
p = linkset->pvts[chanpos];
ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
break;
case ISUP_EVENT_UCIC:
chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
if (chanpos < 0) {
ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
break;
}
p = linkset->pvts[chanpos];
ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
ast_mutex_lock(&p->lock);
p->remotelyblocked = 1;
p->inservice = 0;
ast_mutex_unlock(&p->lock); //doesn't require a SS7 acknowledgement
break;
case ISUP_EVENT_BLO:
chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
if (chanpos < 0) {
ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
break;
}
p = linkset->pvts[chanpos];
ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
ast_mutex_lock(&p->lock);
p->remotelyblocked = 1;
ast_mutex_unlock(&p->lock);
isup_bla(linkset->ss7, e->blo.cic, p->dpc);
break;
case ISUP_EVENT_BLA:
chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
if (chanpos < 0) {
ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
break;
}
ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
p = linkset->pvts[chanpos];
ast_mutex_lock(&p->lock);
p->locallyblocked = 1;
ast_mutex_unlock(&p->lock);
break;
case ISUP_EVENT_UBL:
chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
if (chanpos < 0) {
ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
break;
}
p = linkset->pvts[chanpos];
ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
ast_mutex_lock(&p->lock);
p->remotelyblocked = 0;
ast_mutex_unlock(&p->lock);
isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
break;
case ISUP_EVENT_UBA:
chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
if (chanpos < 0) {
ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
break;
}
p = linkset->pvts[chanpos];
ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
ast_mutex_lock(&p->lock);
p->locallyblocked = 0;
ast_mutex_unlock(&p->lock);
break;
case ISUP_EVENT_CON:
case ISUP_EVENT_ANM:
if (e->e == ISUP_EVENT_CON)
cic = e->con.cic;
else
cic = e->anm.cic;
chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
if (chanpos < 0) {
ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
break;
} else {
p = linkset->pvts[chanpos];
ast_mutex_lock(&p->lock);
p->subs[SUB_REAL].needanswer = 1;
if (p->dsp && p->dsp_features) {
ast_dsp_set_features(p->dsp, p->dsp_features);
p->dsp_features = 0;
}
dahdi_enable_ec(p);
ast_mutex_unlock(&p->lock);
}
break;
case ISUP_EVENT_RLC:
chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
if (chanpos < 0) {
ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
break;
} else {
p = linkset->pvts[chanpos];
ast_mutex_lock(&p->lock);
if (p->alreadyhungup)
p->ss7call = NULL;
else
ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL. Ignoring.\n");
ast_mutex_unlock(&p->lock);
}
break;
case ISUP_EVENT_FAA:
chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
if (chanpos < 0) {
ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
break;
} else {
p = linkset->pvts[chanpos];
ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
ast_mutex_lock(&p->lock);
if (p->alreadyhungup){
p->ss7call = NULL;
ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR. Ignoring.\n");
}
ast_mutex_unlock(&p->lock);
}
break;
default:
ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
break;
}
}
ast_mutex_unlock(&linkset->lock);
}
return 0;
}
| static int ss7_pres_scr2cid_pres | ( | char | presentation_ind, | |
| char | screening_ind | |||
| ) | [static] |
Definition at line 11507 of file chan_dahdi.c.
Referenced by ss7_linkset().
{
return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
}
| static void ss7_rel | ( | struct dahdi_ss7 * | ss7 | ) | [inline, static] |
Definition at line 1451 of file chan_dahdi.c.
References ast_mutex_unlock(), and dahdi_ss7::lock.
Referenced by dahdi_answer(), dahdi_call(), dahdi_hangup(), and dahdi_indicate().
{
ast_mutex_unlock(&ss7->lock);
}
| static void ss7_reset_linkset | ( | struct dahdi_ss7 * | linkset | ) | [static] |
Definition at line 11316 of file chan_dahdi.c.
References ast_verbose(), dahdi_pvt::cic, dahdi_pvt::dpc, dahdi_ss7::numchans, dahdi_ss7::pvts, and dahdi_ss7::ss7.
Referenced by ss7_linkset().
{
int i, startcic = -1, endcic, dpc;
if (linkset->numchans <= 0)
return;
startcic = linkset->pvts[0]->cic;
/* DB: CIC's DPC fix */
dpc = linkset->pvts[0]->dpc;
for (i = 0; i < linkset->numchans; i++) {
if (linkset->pvts[i+1] && linkset->pvts[i+1]->dpc == dpc && ((linkset->pvts[i+1]->cic - linkset->pvts[i]->cic) == 1) && (linkset->pvts[i]->cic - startcic < 31)) {
continue;
} else {
endcic = linkset->pvts[i]->cic;
ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
isup_grs(linkset->ss7, startcic, endcic, dpc);
/* DB: CIC's DPC fix */
if (linkset->pvts[i+1]) {
startcic = linkset->pvts[i+1]->cic;
dpc = linkset->pvts[i+1]->dpc;
}
}
}
}
| static struct dahdi_ss7* ss7_resolve_linkset | ( | int | linkset | ) | [static, read] |
Definition at line 9987 of file chan_dahdi.c.
References linksets, and NUM_SPANS.
Referenced by linkset_addsigchan(), mkintf(), and process_dahdi().
Definition at line 11360 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RING, ast_strlen_zero(), ast_verb, dahdi_pvt::call_ref_ident, dahdi_pvt::call_ref_pc, dahdi_pvt::calling_party_cat, dahdi_pvt::channel, dahdi_pvt::charge_number, dahdi_pvt::cic, dahdi_enable_ec(), dahdi_new(), dahdi_setlaw(), dahdi_subchannel::dfd, errno, dahdi_pvt::exten, dahdi_ss7::flags, dahdi_pvt::gen_add_number, dahdi_pvt::gen_dig_number, dahdi_pvt::gen_dig_scheme, dahdi_pvt::gen_dig_type, dahdi_pvt::generic_name, dahdi_pvt::jip_number, LINKSET_FLAG_EXPLICITACM, dahdi_pvt::lock, dahdi_ss7::lock, LOG_WARNING, dahdi_pvt::lspi_ident, dahdi_pvt::orig_called_num, pbx_builtin_setvar_helper(), dahdi_pvt::proceeding, dahdi_pvt::redirecting_num, dahdi_ss7::ss7, dahdi_pvt::ss7call, SUB_REAL, dahdi_pvt::subs, and dahdi_ss7::type.
Referenced by ss7_linkset().
{
struct ss7 *ss7 = linkset->ss7;
int res;
int law = 1;
struct ast_channel *c;
char tmp[256];
if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
if (linkset->type == SS7_ITU)
law = DAHDI_LAW_ALAW;
else
law = DAHDI_LAW_MULAW;
res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law);
if (res < 0)
ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
p->proceeding = 1;
isup_acm(ss7, p->ss7call);
}
ast_mutex_unlock(&linkset->lock);
c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
if (!c) {
ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
/* Holding this lock is assumed entering the function */
ast_mutex_lock(&linkset->lock);
return;
} else
ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
dahdi_enable_ec(p);
/* We only reference these variables in the context of the ss7_linkset function
* when receiving either and IAM or a COT message. Since they are only accessed
* from this context, we should be safe to unlock around them */
ast_mutex_unlock(&p->lock);
if (!ast_strlen_zero(p->charge_number)) {
pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
/* Clear this after we set it */
p->charge_number[0] = 0;
}
if (!ast_strlen_zero(p->gen_add_number)) {
pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
/* Clear this after we set it */
p->gen_add_number[0] = 0;
}
if (!ast_strlen_zero(p->jip_number)) {
pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
/* Clear this after we set it */
p->jip_number[0] = 0;
}
if (!ast_strlen_zero(p->gen_dig_number)) {
pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
/* Clear this after we set it */
p->gen_dig_number[0] = 0;
}
if (!ast_strlen_zero(p->orig_called_num)) {
pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
/* Clear this after we set it */
p->orig_called_num[0] = 0;
}
snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
/* Clear this after we set it */
p->gen_dig_type = 0;
snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
/* Clear this after we set it */
p->gen_dig_scheme = 0;
if (!ast_strlen_zero(p->lspi_ident)) {
pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
/* Clear this after we set it */
p->lspi_ident[0] = 0;
}
snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
/* Clear this after we set it */
p->call_ref_ident = 0;
snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
/* Clear this after we set it */
p->call_ref_pc = 0;
snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
/* Clear this after we set it */
p->calling_party_cat = 0;
if (!ast_strlen_zero(p->redirecting_num)) {
pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
/* Clear this after we set it */
p->redirecting_num[0] = 0;
}
if (!ast_strlen_zero(p->generic_name)) {
pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
/* Clear this after we set it */
p->generic_name[0] = 0;
}
ast_mutex_lock(&p->lock);
ast_mutex_lock(&linkset->lock);
}
| static void * ss_thread | ( | void * | data | ) | [static] |
Definition at line 7761 of file chan_dahdi.c.
References ast_channel::_state, alloc_sub(), ARRAY_LEN, ast_bridged_channel(), ast_canmatch_extension(), ast_clear_flag, ast_cond_signal(), 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_shrink_phone_number(), ast_smdi_md_message_destroy(), 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(), ASTOBJ_UNREF, 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, dahdi_pvt::channel, ast_channel::cid, CID_MSGWAITING, ast_callerid::cid_name, dahdi_pvt::cid_name, CID_NOMSGWAITING, 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, CID_START_RING, 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_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, ast_frame::frametype, ast_smdi_md_message::fwd_st, ast_channel::hangupcause, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::hardwaredtmf, dahdi_pvt::hidecallerid, dahdi_pvt::immediate, dahdi_pvt::inalarm, ISTRUNK, ast_channel::language, dahdi_pvt::lastcid_num, len(), dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pvt::mwimonitor_rpas, my_getsigstr(), ast_channel::name, name, NEED_MFDETECT, notify_message(), dahdi_pri::overlapdial, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::polarity, POLARITY_REV, 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, ast_channel::rings, 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_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, ast_frame::subclass, 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(), mwi_thread(), and pri_dchannel().
{
struct ast_channel *chan = data;
struct dahdi_pvt *p = chan->tech_pvt;
char exten[AST_MAX_EXTENSION] = "";
char exten2[AST_MAX_EXTENSION] = "";
unsigned char buf[256];
char dtmfcid[300];
char dtmfbuf[300];
struct callerid_state *cs = NULL;
char *name = NULL, *number = NULL;
int distMatches;
int curRingData[3];
int receivedRingT;
int counter1;
int counter;
int samples = 0;
struct ast_smdi_md_message *smdi_msg = NULL;
int flags = 0;
int i;
int timeout;
int getforward = 0;
char *s1, *s2;
int len = 0;
int res;
int idx;
ast_mutex_lock(&ss_thread_lock);
ss_thread_count++;
ast_mutex_unlock(&ss_thread_lock);
/* in the bizarre case where the channel has become a zombie before we
even get started here, abort safely
*/
if (!p) {
ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
ast_hangup(chan);
goto quit;
}
ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
idx = dahdi_get_index(chan, p, 1);
if (idx < 0) {
ast_log(LOG_WARNING, "Huh?\n");
ast_hangup(chan);
goto quit;
}
if (p->dsp)
ast_dsp_digitreset(p->dsp);
switch (p->sig) {
#ifdef HAVE_PRI
case SIG_PRI:
case SIG_BRI:
case SIG_BRI_PTMP:
/* Now loop looking for an extension */
ast_copy_string(exten, p->exten, sizeof(exten));
len = strlen(exten);
res = 0;
while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
if (len && !ast_ignore_pattern(chan->context, exten))
tone_zone_play_tone(p->subs[idx].dfd, -1);
else
tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
timeout = matchdigittimeout;
else
timeout = gendigittimeout;
res = ast_waitfordigit(chan, timeout);
if (res < 0) {
ast_debug(1, "waitfordigit returned < 0...\n");
ast_hangup(chan);
goto quit;
} else if (res) {
exten[len++] = res;
exten[len] = '\0';
} else
break;
}
/* if no extension was received ('unspecified') on overlap call, use the 's' extension */
if (ast_strlen_zero(exten)) {
ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
exten[0] = 's';
exten[1] = '\0';
}
tone_zone_play_tone(p->subs[idx].dfd, -1);
if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
/* Start the real PBX */
ast_copy_string(chan->exten, exten, sizeof(chan->exten));
if (p->dsp) {
ast_dsp_digitreset(p->dsp);
}
if (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) {
ast_mutex_lock(&p->lock);
if (p->pri->pri) {
if (!pri_grab(p, p->pri)) {
pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0);
p->proceeding = 1;
pri_rel(p->pri);
} else {
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
}
}
ast_mutex_unlock(&p->lock);
}
dahdi_enable_ec(p);
ast_setstate(chan, AST_STATE_RING);
res = ast_pbx_run(chan);
if (res) {
ast_log(LOG_WARNING, "PBX exited non-zero!\n");
}
} else {
ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
chan->hangupcause = AST_CAUSE_UNALLOCATED;
ast_hangup(chan);
p->exten[0] = '\0';
/* Since we send release complete here, we won't get one */
p->call = NULL;
}
goto quit;
break;
#endif
case SIG_FEATD:
case SIG_FEATDMF:
case SIG_FEATDMF_TA:
case SIG_E911:
case SIG_FGC_CAMAMF:
case SIG_FEATB:
case SIG_EMWINK:
case SIG_SF_FEATD:
case SIG_SF_FEATDMF:
case SIG_SF_FEATB:
case SIG_SFWINK:
if (dahdi_wink(p, idx))
goto quit;
/* Fall through */
case SIG_EM:
case SIG_EM_E1:
case SIG_SF:
case SIG_FGC_CAMA:
res = tone_zone_play_tone(p->subs[idx].dfd, -1);
if (p->dsp)
ast_dsp_digitreset(p->dsp);
/* set digit mode appropriately */
if (p->dsp) {
if (NEED_MFDETECT(p))
ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
else
ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
}
memset(dtmfbuf, 0, sizeof(dtmfbuf));
/* Wait for the first digit only if immediate=no */
if (!p->immediate)
/* Wait for the first digit (up to 5 seconds). */
res = ast_waitfordigit(chan, 5000);
else
res = 0;
if (res > 0) {
/* save first char */
dtmfbuf[0] = res;
switch (p->sig) {
case SIG_FEATD:
case SIG_SF_FEATD:
res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
if (res > 0)
res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
break;
case SIG_FEATDMF_TA:
res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
if (dahdi_wink(p, idx)) goto quit;
dtmfbuf[0] = 0;
/* Wait for the first digit (up to 5 seconds). */
res = ast_waitfordigit(chan, 5000);
if (res <= 0) break;
dtmfbuf[0] = res;
/* fall through intentionally */
case SIG_FEATDMF:
case SIG_E911:
case SIG_FGC_CAMAMF:
case SIG_SF_FEATDMF:
res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
/* if international caca, do it again to get real ANO */
if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
{
if (dahdi_wink(p, idx)) goto quit;
dtmfbuf[0] = 0;
/* Wait for the first digit (up to 5 seconds). */
res = ast_waitfordigit(chan, 5000);
if (res <= 0) break;
dtmfbuf[0] = res;
res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
}
if (res > 0) {
/* if E911, take off hook */
if (p->sig == SIG_E911)
dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
}
if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
break;
case SIG_FEATB:
case SIG_SF_FEATB:
res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
break;
case SIG_EMWINK:
/* if we received a '*', we are actually receiving Feature Group D
dial syntax, so use that mode; otherwise, fall through to normal
mode
*/
if (res == '*') {
res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
if (res > 0)
res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
break;
}
default:
/* If we got the first digit, get the rest */
len = 1;
dtmfbuf[len] = '\0';
while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
timeout = matchdigittimeout;
} else {
timeout = gendigittimeout;
}
res = ast_waitfordigit(chan, timeout);
if (res < 0) {
ast_debug(1, "waitfordigit returned < 0...\n");
ast_hangup(chan);
goto quit;
} else if (res) {
dtmfbuf[len++] = res;
dtmfbuf[len] = '\0';
} else {
break;
}
}
break;
}
}
if (res == -1) {
ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
ast_hangup(chan);
goto quit;
} else if (res < 0) {
ast_debug(1, "Got hung up before digits finished\n");
ast_hangup(chan);
goto quit;
}
if (p->sig == SIG_FGC_CAMA) {
char anibuf[100];
if (ast_safe_sleep(chan,1000) == -1) {
ast_hangup(chan);
goto quit;
}
dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
res = my_getsigstr(chan, anibuf, "#", 10000);
if ((res > 0) && (strlen(anibuf) > 2)) {
if (anibuf[strlen(anibuf) - 1] == '#')
anibuf[strlen(anibuf) - 1] = 0;
ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
}
ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
}
ast_copy_string(exten, dtmfbuf, sizeof(exten));
if (ast_strlen_zero(exten))
ast_copy_string(exten, "s", sizeof(exten));
if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
/* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
if (exten[0] == '*') {
char *stringp=NULL;
ast_copy_string(exten2, exten, sizeof(exten2));
/* Parse out extension and callerid */
stringp=exten2 +1;
s1 = strsep(&stringp, "*");
s2 = strsep(&stringp, "*");
if (s2) {
if (!ast_strlen_zero(p->cid_num))
ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
else
ast_set_callerid(chan, s1, NULL, s1);
ast_copy_string(exten, s2, sizeof(exten));
} else
ast_copy_string(exten, s1, sizeof(exten));
} else if (p->sig == SIG_FEATD)
ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
}
if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
if (exten[0] == '*') {
char *stringp=NULL;
ast_copy_string(exten2, exten, sizeof(exten2));
/* Parse out extension and callerid */
stringp=exten2 +1;
s1 = strsep(&stringp, "#");
s2 = strsep(&stringp, "#");
if (s2) {
if (!ast_strlen_zero(p->cid_num))
ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
else
if (*(s1 + 2))
ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
ast_copy_string(exten, s2 + 1, sizeof(exten));
} else
ast_copy_string(exten, s1 + 2, sizeof(exten));
} else
ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
}
if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
if (exten[0] == '*') {
char *stringp=NULL;
ast_copy_string(exten2, exten, sizeof(exten2));
/* Parse out extension and callerid */
stringp=exten2 +1;
s1 = strsep(&stringp, "#");
s2 = strsep(&stringp, "#");
if (s2 && (*(s2 + 1) == '0')) {
if (*(s2 + 2))
ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
}
if (s1) ast_copy_string(exten, s1, sizeof(exten));
else ast_copy_string(exten, "911", sizeof(exten));
} else
ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
}
if (p->sig == SIG_FEATB) {
if (exten[0] == '*') {
char *stringp=NULL;
ast_copy_string(exten2, exten, sizeof(exten2));
/* Parse out extension and callerid */
stringp=exten2 +1;
s1 = strsep(&stringp, "#");
ast_copy_string(exten, exten2 + 1, sizeof(exten));
} else
ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
}
if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
dahdi_wink(p, idx);
/* some switches require a minimum guard time between
the last FGD wink and something that answers
immediately. This ensures it */
if (ast_safe_sleep(chan,100)) goto quit;
}
dahdi_enable_ec(p);
if (NEED_MFDETECT(p)) {
if (p->dsp) {
if (!p->hardwaredtmf)
ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
else {
ast_dsp_free(p->dsp);
p->dsp = NULL;
}
}
}
if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
ast_copy_string(chan->exten, exten, sizeof(chan->exten));
if (p->dsp) ast_dsp_digitreset(p->dsp);
res = ast_pbx_run(chan);
if (res) {
ast_log(LOG_WARNING, "PBX exited non-zero\n");
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
}
goto quit;
} else {
ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
sleep(2);
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
if (res < 0)
ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
else
sleep(1);
res = ast_streamfile(chan, "ss-noservice", chan->language);
if (res >= 0)
ast_waitstream(chan, "");
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
ast_hangup(chan);
goto quit;
}
break;
case SIG_FXOLS:
case SIG_FXOGS:
case SIG_FXOKS:
/* Read the first digit */
timeout = firstdigittimeout;
/* If starting a threeway call, never timeout on the first digit so someone
can use flash-hook as a "hold" feature */
if (p->subs[SUB_THREEWAY].owner)
timeout = 999999;
while (len < AST_MAX_EXTENSION-1) {
/* Read digit unless it's supposed to be immediate, in which case the
only answer is 's' */
if (p->immediate)
res = 's';
else
res = ast_waitfordigit(chan, timeout);
timeout = 0;
if (res < 0) {
ast_debug(1, "waitfordigit returned < 0...\n");
res = tone_zone_play_tone(p->subs[idx].dfd, -1);
ast_hangup(chan);
goto quit;
} else if (res) {
ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
exten[len++]=res;
exten[len] = '\0';
}
if (!ast_ignore_pattern(chan->context, exten))
tone_zone_play_tone(p->subs[idx].dfd, -1);
else
tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
if (getforward) {
/* Record this as the forwarding extension */
ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
if (res)
break;
usleep(500000);
res = tone_zone_play_tone(p->subs[idx].dfd, -1);
sleep(1);
memset(exten, 0, sizeof(exten));
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
len = 0;
getforward = 0;
} else {
res = tone_zone_play_tone(p->subs[idx].dfd, -1);
ast_copy_string(chan->exten, exten, sizeof(chan->exten));
if (!ast_strlen_zero(p->cid_num)) {
if (!p->hidecallerid)
ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
else
ast_set_callerid(chan, NULL, NULL, p->cid_num);
}
if (!ast_strlen_zero(p->cid_name)) {
if (!p->hidecallerid)
ast_set_callerid(chan, NULL, p->cid_name, NULL);
}
ast_setstate(chan, AST_STATE_RING);
dahdi_enable_ec(p);
res = ast_pbx_run(chan);
if (res) {
ast_log(LOG_WARNING, "PBX exited non-zero\n");
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
}
goto quit;
}
} else {
/* It's a match, but they just typed a digit, and there is an ambiguous match,
so just set the timeout to matchdigittimeout and wait some more */
timeout = matchdigittimeout;
}
} else if (res == 0) {
ast_debug(1, "not enough digits (and no ambiguous match)...\n");
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
dahdi_wait_event(p->subs[idx].dfd);
ast_hangup(chan);
goto quit;
} else if (p->callwaiting && !strcmp(exten, "*70")) {
ast_verb(3, "Disabling call waiting on %s\n", chan->name);
/* Disable call waiting if enabled */
p->callwaiting = 0;
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
if (res) {
ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
chan->name, strerror(errno));
}
len = 0;
ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
memset(exten, 0, sizeof(exten));
timeout = firstdigittimeout;
} else if (!strcmp(exten,ast_pickup_ext())) {
/* Scan all channels and see if there are any
* ringing channels that have call groups
* that equal this channels pickup group
*/
if (idx == SUB_REAL) {
/* Switch us from Third call to Call Wait */
if (p->subs[SUB_THREEWAY].owner) {
/* If you make a threeway call and the *8# a call, it should actually
look like a callwait */
alloc_sub(p, SUB_CALLWAIT);
swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
unalloc_sub(p, SUB_THREEWAY);
}
dahdi_enable_ec(p);
if (ast_pickup_call(chan)) {
ast_debug(1, "No call pickup possible...\n");
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
dahdi_wait_event(p->subs[idx].dfd);
}
ast_hangup(chan);
goto quit;
} else {
ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
ast_hangup(chan);
goto quit;
}
} else if (!p->hidecallerid && !strcmp(exten, "*67")) {
ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
/* Disable Caller*ID if enabled */
p->hidecallerid = 1;
if (chan->cid.cid_num)
ast_free(chan->cid.cid_num);
chan->cid.cid_num = NULL;
if (chan->cid.cid_name)
ast_free(chan->cid.cid_name);
chan->cid.cid_name = NULL;
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
if (res) {
ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
chan->name, strerror(errno));
}
len = 0;
memset(exten, 0, sizeof(exten));
timeout = firstdigittimeout;
} else if (p->callreturn && !strcmp(exten, "*69")) {
res = 0;
if (!ast_strlen_zero(p->lastcid_num)) {
res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
}
if (!res)
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
break;
} else if (!strcmp(exten, "*78")) {
dahdi_dnd(p, 1);
/* Do not disturb */
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
getforward = 0;
memset(exten, 0, sizeof(exten));
len = 0;
} else if (!strcmp(exten, "*79")) {
dahdi_dnd(p, 0);
/* Do not disturb */
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
getforward = 0;
memset(exten, 0, sizeof(exten));
len = 0;
} else if (p->cancallforward && !strcmp(exten, "*72")) {
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
getforward = 1;
memset(exten, 0, sizeof(exten));
len = 0;
} else if (p->cancallforward && !strcmp(exten, "*73")) {
ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
memset(p->call_forward, 0, sizeof(p->call_forward));
getforward = 0;
memset(exten, 0, sizeof(exten));
len = 0;
} else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
p->subs[SUB_THREEWAY].owner &&
ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
/* This is a three way call, the main call being a real channel,
and we're parking the first call. */
ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
ast_verb(3, "Parking call to '%s'\n", chan->name);
break;
} else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
res = ast_db_put("blacklist", p->lastcid_num, "1");
if (!res) {
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
memset(exten, 0, sizeof(exten));
len = 0;
}
} else if (p->hidecallerid && !strcmp(exten, "*82")) {
ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
/* Enable Caller*ID if enabled */
p->hidecallerid = 0;
if (chan->cid.cid_num)
ast_free(chan->cid.cid_num);
chan->cid.cid_num = NULL;
if (chan->cid.cid_name)
ast_free(chan->cid.cid_name);
chan->cid.cid_name = NULL;
ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
if (res) {
ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
chan->name, strerror(errno));
}
len = 0;
memset(exten, 0, sizeof(exten));
timeout = firstdigittimeout;
} else if (!strcmp(exten, "*0")) {
struct ast_channel *nbridge =
p->subs[SUB_THREEWAY].owner;
struct dahdi_pvt *pbridge = NULL;
/* set up the private struct of the bridged one, if any */
if (nbridge && ast_bridged_channel(nbridge))
pbridge = ast_bridged_channel(nbridge)->tech_pvt;
if (nbridge && pbridge &&
(nbridge->tech == &dahdi_tech) &&
(ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
ISTRUNK(pbridge)) {
int func = DAHDI_FLASH;
/* Clear out the dial buffer */
p->dop.dialstr[0] = '\0';
/* flash hookswitch */
if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
nbridge->name, strerror(errno));
}
swap_subs(p, SUB_REAL, SUB_THREEWAY);
unalloc_sub(p, SUB_THREEWAY);
p->owner = p->subs[SUB_REAL].owner;
if (ast_bridged_channel(p->subs[SUB_REAL].owner))
ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
ast_hangup(chan);
goto quit;
} else {
tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
dahdi_wait_event(p->subs[idx].dfd);
tone_zone_play_tone(p->subs[idx].dfd, -1);
swap_subs(p, SUB_REAL, SUB_THREEWAY);
unalloc_sub(p, SUB_THREEWAY);
p->owner = p->subs[SUB_REAL].owner;
ast_hangup(chan);
goto quit;
}
} else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
((exten[0] != '*') || (strlen(exten) > 2))) {
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);
break;
}
if (!timeout)
timeout = gendigittimeout;
if (len && !ast_ignore_pattern(chan->context, exten))
tone_zone_play_tone(p->subs[idx].dfd, -1);
}
break;
case SIG_FXSLS:
case SIG_FXSGS:
case SIG_FXSKS:
#ifdef HAVE_PRI
if (p->pri) {
/* This is a GR-303 trunk actually. Wait for the first ring... */
struct ast_frame *f;
int res;
time_t start;
time(&start);
ast_setstate(chan, AST_STATE_RING);
while (time(NULL) < start + 3) {
res = ast_waitfor(chan, 1000);
if (res) {
f = ast_read(chan);
if (!f) {
ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
ast_hangup(chan);
goto quit;
} else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
res = 1;
} else
res = 0;
ast_frfree(f);
if (res) {
ast_debug(1, "Got ring!\n");
res = 0;
break;
}
}
}
}
#endif
/* check for SMDI messages */
if (p->use_smdi && p->smdi_iface) {
smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
if (smdi_msg != NULL) {
ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
if (smdi_msg->type == 'B')
pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
else if (smdi_msg->type == 'N')
pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
ast_debug(1, "Received SMDI message on %s\n", chan->name);
} else {
ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
}
}
if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
number = smdi_msg->calling_st;
/* If we want caller id, we're in a prering state due to a polarity reversal
* and we're set to use a polarity reversal to trigger the start of caller id,
* grab the caller id and wait for ringing to start... */
} else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
/* If set to use DTMF CID signalling, listen for DTMF */
if (p->cid_signalling == CID_SIG_DTMF) {
int k = 0;
cs = NULL;
ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
dahdi_setlinear(p->subs[idx].dfd, 0);
/*
* We are the only party interested in the Rx stream since
* we have not answered yet. We don't need or even want DTMF
* emulation. The DTMF digits can come so fast that emulation
* can drop some of them.
*/
ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
res = 4000;/* This is a typical OFF time between rings. */
for (;;) {
struct ast_frame *f;
res = ast_waitfor(chan, res);
if (res <= 0) {
/*
* We do not need to restore the dahdi_setlinear()
* or AST_FLAG_END_DTMF_ONLY flag settings since we
* are hanging up the channel.
*/
ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
"Exiting simple switch\n");
ast_hangup(chan);
goto quit;
}
f = ast_read(chan);
if (!f)
break;
if (f->frametype == AST_FRAME_DTMF) {
if (k < ARRAY_LEN(dtmfbuf) - 1) {
dtmfbuf[k++] = f->subclass;
}
ast_debug(1, "CID got digit '%c'\n", f->subclass);
res = 4000;/* This is a typical OFF time between rings. */
}
ast_frfree(f);
if (chan->_state == AST_STATE_RING ||
chan->_state == AST_STATE_RINGING)
break; /* Got ring */
}
ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
dtmfbuf[k] = '\0';
dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
/* Got cid and ring. */
ast_debug(1, "CID got string '%s'\n", dtmfbuf);
callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
/* If first byte is NULL, we have no cid */
if (!ast_strlen_zero(dtmfcid))
number = dtmfcid;
else
number = NULL;
/* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
} else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
cs = callerid_new(p->cid_signalling);
if (cs) {
samples = 0;
#if 1
bump_gains(p);
#endif
/* Take out of linear mode for Caller*ID processing */
dahdi_setlinear(p->subs[idx].dfd, 0);
/* First we wait and listen for the Caller*ID */
for (;;) {
i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
callerid_free(cs);
ast_hangup(chan);
goto quit;
}
if (i & DAHDI_IOMUX_SIGEVENT) {
res = dahdi_get_event(p->subs[idx].dfd);
ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
if (res == DAHDI_EVENT_NOALARM) {
p->inalarm = 0;
}
if (p->cid_signalling == CID_SIG_V23_JP) {
if (res == DAHDI_EVENT_RINGBEGIN) {
res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
usleep(1);
}
} else {
res = 0;
break;
}
} else if (i & DAHDI_IOMUX_READ) {
res = read(p->subs[idx].dfd, buf, sizeof(buf));
if (res < 0) {
if (errno != ELAST) {
ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
callerid_free(cs);
ast_hangup(chan);
goto quit;
}
break;
}
samples += res;
if (p->cid_signalling == CID_SIG_V23_JP) {
res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
} else {
res = callerid_feed(cs, buf, res, AST_LAW(p));
}
if (res < 0) {
/*
* The previous diagnostic message output likely
* explains why it failed.
*/
ast_log(LOG_WARNING,
"Failed to decode CallerID on channel '%s'\n",
chan->name);
break;
} else if (res)
break;
else if (samples > (8000 * 10))
break;
}
}
if (res == 1) {
callerid_get(cs, &name, &number, &flags);
ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
}
if (p->cid_signalling == CID_SIG_V23_JP) {
res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
usleep(1);
}
/* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
res = 4000;/* This is a typical OFF time between rings. */
for (;;) {
struct ast_frame *f;
res = ast_waitfor(chan, res);
if (res <= 0) {
ast_log(LOG_WARNING, "CID timed out waiting for ring. "
"Exiting simple switch\n");
ast_hangup(chan);
goto quit;
}
if (!(f = ast_read(chan))) {
ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
ast_hangup(chan);
goto quit;
}
ast_frfree(f);
if (chan->_state == AST_STATE_RING ||
chan->_state == AST_STATE_RINGING)
break; /* Got ring */
}
/* We must have a ring by now, so, if configured, lets try to listen for
* distinctive ringing */
if (p->usedistinctiveringdetection) {
len = 0;
distMatches = 0;
/* Clear the current ring data array so we dont have old data in it. */
for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
curRingData[receivedRingT] = 0;
receivedRingT = 0;
counter = 0;
counter1 = 0;
/* Check to see if context is what it should be, if not set to be. */
if (strcmp(p->context,p->defcontext) != 0) {
ast_copy_string(p->context, p->defcontext, sizeof(p->context));
ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
}
for (;;) {
i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
callerid_free(cs);
ast_hangup(chan);
goto quit;
}
if (i & DAHDI_IOMUX_SIGEVENT) {
res = dahdi_get_event(p->subs[idx].dfd);
ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
if (res == DAHDI_EVENT_NOALARM) {
p->inalarm = 0;
}
res = 0;
/* Let us detect distinctive ring */
curRingData[receivedRingT] = p->ringt;
if (p->ringt < p->ringt_base/2)
break;
/* Increment the ringT counter so we can match it against
values in chan_dahdi.conf for distinctive ring */
if (++receivedRingT == ARRAY_LEN(curRingData))
break;
} else if (i & DAHDI_IOMUX_READ) {
res = read(p->subs[idx].dfd, buf, sizeof(buf));
if (res < 0) {
if (errno != ELAST) {
ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
callerid_free(cs);
ast_hangup(chan);
goto quit;
}
break;
}
if (p->ringt)
p->ringt--;
if (p->ringt == 1) {
res = -1;
break;
}
}
}
/* this only shows up if you have n of the dring patterns filled in */
ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
for (counter = 0; counter < 3; counter++) {
/* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
channel */
distMatches = 0;
for (counter1 = 0; counter1 < 3; counter1++) {
ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
if (p->drings.ringnum[counter].ring[counter1] == -1) {
ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
curRingData[counter1]);
distMatches++;
} else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
ast_verb(3, "Ring pattern matched in range: %d to %d\n",
(p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
(p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
distMatches++;
}
}
if (distMatches == 3) {
/* The ring matches, set the context to whatever is for distinctive ring.. */
ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
break;
}
}
}
/* Restore linear mode (if appropriate) for Caller*ID processing */
dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
#if 1
restore_gains(p);
#endif
} else
ast_log(LOG_WARNING, "Unable to get caller ID space\n");
} else {
ast_log(LOG_WARNING, "Channel %s in prering "
"state, but I have nothing to do. "
"Terminating simple switch, should be "
"restarted by the actual ring.\n",
chan->name);
ast_hangup(chan);
goto quit;
}
} else if (p->use_callerid && p->cid_start == CID_START_RING) {
if (p->cid_signalling == CID_SIG_DTMF) {
int k = 0;
cs = NULL;
dahdi_setlinear(p->subs[idx].dfd, 0);
res = 2000;
for (;;) {
struct ast_frame *f;
res = ast_waitfor(chan, res);
if (res <= 0) {
ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
"Exiting simple switch\n");
ast_hangup(chan);
return NULL;
}
f = ast_read(chan);
if (f->frametype == AST_FRAME_DTMF) {
dtmfbuf[k++] = f->subclass;
ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
res = 2000;
}
ast_frfree(f);
if (p->ringt_base == p->ringt)
break;
}
dtmfbuf[k] = '\0';
dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
/* Got cid and ring. */
callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
dtmfcid, flags);
/* If first byte is NULL, we have no cid */
if (!ast_strlen_zero(dtmfcid))
number = dtmfcid;
else
number = NULL;
/* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
} else {
/* FSK Bell202 callerID */
cs = callerid_new(p->cid_signalling);
if (cs) {
#if 1
bump_gains(p);
#endif
samples = 0;
len = 0;
distMatches = 0;
/* Clear the current ring data array so we dont have old data in it. */
for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
curRingData[receivedRingT] = 0;
receivedRingT = 0;
counter = 0;
counter1 = 0;
/* Check to see if context is what it should be, if not set to be. */
if (strcmp(p->context,p->defcontext) != 0) {
ast_copy_string(p->context, p->defcontext, sizeof(p->context));
ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
}
/* Take out of linear mode for Caller*ID processing */
dahdi_setlinear(p->subs[idx].dfd, 0);
for (;;) {
i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
callerid_free(cs);
ast_hangup(chan);
goto quit;
}
if (i & DAHDI_IOMUX_SIGEVENT) {
res = dahdi_get_event(p->subs[idx].dfd);
ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
if (res == DAHDI_EVENT_NOALARM) {
p->inalarm = 0;
}
/* If we get a PR event, they hung up while processing calerid */
if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
p->polarity = POLARITY_IDLE;
callerid_free(cs);
ast_hangup(chan);
goto quit;
}
res = 0;
/* Let us detect callerid when the telco uses distinctive ring */
curRingData[receivedRingT] = p->ringt;
if (p->ringt < p->ringt_base/2)
break;
/* Increment the ringT counter so we can match it against
values in chan_dahdi.conf for distinctive ring */
if (++receivedRingT == ARRAY_LEN(curRingData))
break;
} else if (i & DAHDI_IOMUX_READ) {
res = read(p->subs[idx].dfd, buf, sizeof(buf));
if (res < 0) {
if (errno != ELAST) {
ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
callerid_free(cs);
ast_hangup(chan);
goto quit;
}
break;
}
if (p->ringt)
p->ringt--;
if (p->ringt == 1) {
res = -1;
break;
}
samples += res;
res = callerid_feed(cs, buf, res, AST_LAW(p));
if (res < 0) {
/*
* The previous diagnostic message output likely
* explains why it failed.
*/
ast_log(LOG_WARNING,
"Failed to decode CallerID on channel '%s'\n",
chan->name);
break;
} else if (res)
break;
else if (samples > (8000 * 10))
break;
}
}
if (res == 1) {
callerid_get(cs, &name, &number, &flags);
ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
}
if (distinctiveringaftercid == 1) {
/* Clear the current ring data array so we dont have old data in it. */
for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
curRingData[receivedRingT] = 0;
}
receivedRingT = 0;
ast_verb(3, "Detecting post-CID distinctive ring\n");
for (;;) {
i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
callerid_free(cs);
ast_hangup(chan);
goto quit;
}
if (i & DAHDI_IOMUX_SIGEVENT) {
res = dahdi_get_event(p->subs[idx].dfd);
ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
if (res == DAHDI_EVENT_NOALARM) {
p->inalarm = 0;
}
res = 0;
/* Let us detect callerid when the telco uses distinctive ring */
curRingData[receivedRingT] = p->ringt;
if (p->ringt < p->ringt_base/2)
break;
/* Increment the ringT counter so we can match it against
values in chan_dahdi.conf for distinctive ring */
if (++receivedRingT == ARRAY_LEN(curRingData))
break;
} else if (i & DAHDI_IOMUX_READ) {
res = read(p->subs[idx].dfd, buf, sizeof(buf));
if (res < 0) {
if (errno != ELAST) {
ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
callerid_free(cs);
ast_hangup(chan);
goto quit;
}
break;
}
if (p->ringt)
p->ringt--;
if (p->ringt == 1) {
res = -1;
break;
}
}
}
}
if (p->usedistinctiveringdetection) {
/* this only shows up if you have n of the dring patterns filled in */
ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
for (counter = 0; counter < 3; counter++) {
/* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
channel */
/* this only shows up if you have n of the dring patterns filled in */
ast_verb(3, "Checking %d,%d,%d\n",
p->drings.ringnum[counter].ring[0],
p->drings.ringnum[counter].ring[1],
p->drings.ringnum[counter].ring[2]);
distMatches = 0;
for (counter1 = 0; counter1 < 3; counter1++) {
ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
if (p->drings.ringnum[counter].ring[counter1] == -1) {
ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
curRingData[counter1]);
distMatches++;
}
else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
ast_verb(3, "Ring pattern matched in range: %d to %d\n",
(p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
(p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
distMatches++;
}
}
if (distMatches == 3) {
/* The ring matches, set the context to whatever is for distinctive ring.. */
ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
break;
}
}
}
/* Restore linear mode (if appropriate) for Caller*ID processing */
dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
#if 1
restore_gains(p);
#endif
if (res < 0) {
ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
}
} else
ast_log(LOG_WARNING, "Unable to get caller ID space\n");
}
} else
cs = NULL;
if (number)
ast_shrink_phone_number(number);
ast_set_callerid(chan, number, name, number);
if (smdi_msg)
ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
if (cs)
callerid_free(cs);
/* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
if (flags & CID_MSGWAITING) {
ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
notify_message(p->mailbox, 1);
/* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
if (p->mwimonitor_rpas) {
ast_hangup(chan);
return NULL;
}
} else if (flags & CID_NOMSGWAITING) {
ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
notify_message(p->mailbox, 0);
/* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
if (p->mwimonitor_rpas) {
ast_hangup(chan);
return NULL;
}
}
ast_setstate(chan, AST_STATE_RING);
chan->rings = 1;
p->ringt = p->ringt_base;
res = ast_pbx_run(chan);
if (res) {
ast_hangup(chan);
ast_log(LOG_WARNING, "PBX exited non-zero\n");
}
goto quit;
default:
ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
if (res < 0)
ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
}
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
if (res < 0)
ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
ast_hangup(chan);
quit:
ast_mutex_lock(&ss_thread_lock);
ss_thread_count--;
ast_cond_signal(&ss_thread_complete);
ast_mutex_unlock(&ss_thread_lock);
return NULL;
}
| static int start_pri | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 13662 of file chan_dahdi.c.
References ast_log(), ast_pthread_create_background, DAHDI_CHAN_MAPPING_LOGICAL, dahdi_close_pri_fd(), DAHDI_OVERLAPDIAL_OUTGOING, dahdi_pri::dchanavail, dahdi_pri::dchannels, dahdi_pri::dchans, DEFAULT_PRI_DEBUG, errno, dahdi_pri::fds, dahdi_pri::inbanddisconnect, LOG_ERROR, dahdi_pri::master, dahdi_pri::nodetype, dahdi_pri::nsf, dahdi_pri::overlapdial, dahdi_pri::pri, pri_dchannel(), dahdi_pri::qsigchannelmapping, dahdi_pri::resetpos, dahdi_pri::sig, SIG_BRI, SIG_BRI_PTMP, and dahdi_pri::switchtype.
Referenced by setup_dahdi().
{
int res, x;
struct dahdi_params p;
struct dahdi_bufferinfo bi;
struct dahdi_spaninfo si;
int i;
for (i = 0; i < NUM_DCHANS; i++) {
if (!pri->dchannels[i])
break;
pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
x = pri->dchannels[i];
if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
return -1;
}
memset(&p, 0, sizeof(p));
res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
if (res) {
dahdi_close_pri_fd(pri, i);
ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
return -1;
}
if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
dahdi_close_pri_fd(pri, i);
ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
return -1;
}
memset(&si, 0, sizeof(si));
res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
if (res) {
dahdi_close_pri_fd(pri, i);
ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
}
if (!si.alarms)
pri->dchanavail[i] |= DCHAN_NOTINALARM;
else
pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
memset(&bi, 0, sizeof(bi));
bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
bi.numbufs = 32;
bi.bufsize = 1024;
if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
dahdi_close_pri_fd(pri, i);
return -1;
}
switch (pri->sig) {
case SIG_BRI:
pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
break;
case SIG_BRI_PTMP:
pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
break;
default:
pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
break;
}
/* Force overlap dial if we're doing GR-303! */
if (pri->switchtype == PRI_SWITCH_GR303_TMC)
pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
#ifdef HAVE_PRI_PROG_W_CAUSE
pri_set_chan_mapping_logical(pri->dchans[i], pri->qsigchannelmapping == DAHDI_CHAN_MAPPING_LOGICAL);
#endif
#ifdef HAVE_PRI_INBANDDISCONNECT
pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
#endif
/* Enslave to master if appropriate */
if (i)
pri_enslave(pri->dchans[0], pri->dchans[i]);
if (!pri->dchans[i]) {
dahdi_close_pri_fd(pri, i);
ast_log(LOG_ERROR, "Unable to create PRI structure\n");
return -1;
}
pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
pri_set_nsf(pri->dchans[i], pri->nsf);
#ifdef PRI_GETSET_TIMERS
for (x = 0; x < PRI_MAX_TIMERS; x++) {
if (pritimers[x] != 0)
pri_set_timer(pri->dchans[i], x, pritimers[x]);
}
#endif
}
/* Assume primary is the one we use */
pri->pri = pri->dchans[0];
pri->resetpos = -1;
if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
for (i = 0; i < NUM_DCHANS; i++) {
if (!pri->dchannels[i])
break;
dahdi_close_pri_fd(pri, i);
}
ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
return -1;
}
return 0;
}
| static void swap_subs | ( | struct dahdi_pvt * | p, | |
| int | a, | |||
| int | b | |||
| ) | [static] |
Definition at line 2064 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(), and ss_thread().
{
int tchan;
int tinthreeway;
struct ast_channel *towner;
ast_debug(1, "Swapping %d and %d\n", a, b);
tchan = p->subs[a].chan;
towner = p->subs[a].owner;
tinthreeway = p->subs[a].inthreeway;
p->subs[a].chan = p->subs[b].chan;
p->subs[a].owner = p->subs[b].owner;
p->subs[a].inthreeway = p->subs[b].inthreeway;
p->subs[b].chan = tchan;
p->subs[b].owner = towner;
p->subs[b].inthreeway = tinthreeway;
if (p->subs[a].owner)
ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
if (p->subs[b].owner)
ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
wakeup_sub(p, a, NULL);
wakeup_sub(p, b, NULL);
}
| static int unalloc_sub | ( | struct dahdi_pvt * | p, | |
| int | x | |||
| ) | [static] |
Definition at line 2214 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, and dahdi_pvt::subs.
Referenced by attempt_transfer(), dahdi_handle_event(), dahdi_hangup(), and ss_thread().
{
if (!x) {
ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
return -1;
}
ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
dahdi_close_sub(p, x);
p->subs[x].linear = 0;
p->subs[x].chan = 0;
p->subs[x].owner = NULL;
p->subs[x].inthreeway = 0;
p->polarity = POLARITY_IDLE;
memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
return 0;
}
| static int unload_module | ( | void | ) | [static] |
Definition at line 16058 of file chan_dahdi.c.
References __unload_module(), ast_mutex_destroy(), linksets, lock, and pris.
{
#if defined(HAVE_PRI) || defined(HAVE_SS7)
int y;
#endif
#ifdef HAVE_PRI
for (y = 0; y < NUM_SPANS; y++)
ast_mutex_destroy(&pris[y].lock);
#endif
#ifdef HAVE_SS7
for (y = 0; y < NUM_SPANS; y++)
ast_mutex_destroy(&linksets[y].lock);
#endif /* HAVE_SS7 */
return __unload_module();
}
| static int update_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2606 of file chan_dahdi.c.
References ast_debug, dahdi_pvt::channel, conf_add(), conf_del(), dahdi_pvt::confno, dahdi_subchannel::dfd, GET_CHANNEL, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, isslavenative(), dahdi_pvt::master, dahdi_pvt::slaves, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), dahdi_bridge(), dahdi_fixup(), dahdi_handle_event(), dahdi_hangup(), dahdi_unlink(), and mkintf().
{
int needconf = 0;
int x;
int useslavenative;
struct dahdi_pvt *slave = NULL;
useslavenative = isslavenative(p, &slave);
/* Start with the obvious, general stuff */
for (x = 0; x < 3; x++) {
/* Look for three way calls */
if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
conf_add(p, &p->subs[x], x, 0);
needconf++;
} else {
conf_del(p, &p->subs[x], x);
}
}
/* If we have a slave, add him to our conference now. or DAX
if this is slave native */
for (x = 0; x < MAX_SLAVES; x++) {
if (p->slaves[x]) {
if (useslavenative)
conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
else {
conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
needconf++;
}
}
}
/* If we're supposed to be in there, do so now */
if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
if (useslavenative)
conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
else {
conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
needconf++;
}
}
/* If we have a master, add ourselves to his conference */
if (p->master) {
if (isslavenative(p->master, NULL)) {
conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
} else {
conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
}
}
if (!needconf) {
/* Nobody is left (or should be left) in our conference.
Kill it. */
p->confno = -1;
}
ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
return 0;
}
Definition at line 1522 of file chan_dahdi.c.
References ast_channel_trylock, ast_channel_unlock, ast_mutex_lock(), 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 pri_fixup_principle(), and swap_subs().
{
#ifdef HAVE_PRI
if (pri)
ast_mutex_unlock(&pri->lock);
#endif
for (;;) {
if (p->subs[a].owner) {
if (ast_channel_trylock(p->subs[a].owner)) {
DEADLOCK_AVOIDANCE(&p->lock);
} else {
ast_queue_frame(p->subs[a].owner, &ast_null_frame);
ast_channel_unlock(p->subs[a].owner);
break;
}
} else
break;
}
#ifdef HAVE_PRI
if (pri)
ast_mutex_lock(&pri->lock);
#endif
}
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = tdesc , .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 = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 17601 of file chan_dahdi.c.
| int alarm |
Definition at line 2369 of file chan_dahdi.c.
struct { ... } alarms[] [static] |
Referenced by alarm2str().
struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}} [static] |
Definition at line 1497 of file chan_dahdi.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 17601 of file chan_dahdi.c.
struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static] |
Definition at line 1478 of file chan_dahdi.c.
int cidrings[NUM_CADENCE_MAX] [static] |
cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on.
Definition at line 1489 of file chan_dahdi.c.
const char config[] = "chan_dahdi.conf" [static] |
Definition at line 238 of file chan_dahdi.c.
int cur_adjpointcode = -1 [static] |
Definition at line 456 of file chan_dahdi.c.
int cur_cicbeginswith = -1 [static] |
Definition at line 455 of file chan_dahdi.c.
int cur_defaultdpc = -1 [static] |
Definition at line 458 of file chan_dahdi.c.
int cur_linkset = -1 [static] |
Definition at line 453 of file chan_dahdi.c.
int cur_networkindicator = -1 [static] |
Definition at line 457 of file chan_dahdi.c.
int cur_pointcode = -1 [static] |
Definition at line 454 of file chan_dahdi.c.
int cur_ss7type = -1 [static] |
Definition at line 452 of file chan_dahdi.c.
struct ast_cli_entry dahdi_cli[] [static] |
Definition at line 15295 of file chan_dahdi.c.
struct ast_cli_entry dahdi_pri_cli[] [static] |
Definition at line 14068 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static] |
Definition at line 3971 of file chan_dahdi.c.
struct ast_cli_entry dahdi_ss7_cli[] [static] |
Definition at line 15964 of file chan_dahdi.c.
struct ast_channel_tech dahdi_tech [static] |
Definition at line 1402 of file chan_dahdi.c.
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 173 of file chan_dahdi.c.
char defaultcic[64] = "" [static] |
Definition at line 296 of file chan_dahdi.c.
char defaultozz[64] = "" [static] |
Definition at line 297 of file chan_dahdi.c.
int distinctiveringaftercid = 0 [static] |
Definition at line 310 of file chan_dahdi.c.
char* events[] [static] |
Definition at line 2346 of file chan_dahdi.c.
int firstdigittimeout = 16000 [static] |
Wait up to 16 seconds for first digit (FXO logic).
Definition at line 326 of file chan_dahdi.c.
Referenced by disa_exec().
int gendigittimeout = 8000 [static] |
How long to wait for following digits (FXO logic).
Definition at line 329 of file chan_dahdi.c.
struct ast_jb_conf global_jbconf [static] |
Definition at line 181 of file chan_dahdi.c.
Referenced by dahdi_new(), process_dahdi(), and setup_dahdi().
int ifcount = 0 [static] |
Definition at line 342 of file chan_dahdi.c.
Referenced by __unload_module(), action_dahdishowchannels(), 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(), duplicate_pseudo(), find_channel(), load_module(), mkintf(), and phone_request().
ast_mutex_t iflock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Protect the interface list (of dahdi_pvt's).
Definition at line 335 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(), and setup_dahdi().
struct ast_channel inuse [static] |
Definition at line 317 of file chan_dahdi.c.
Referenced by ast_jb_do_usecheck(), chanavail_exec(), load_module(), pri_assign_bearer(), pri_dchannel(), and update_call_counter().
const char* lbostr[] [static] |
Definition at line 161 of file chan_dahdi.c.
Definition at line 450 of file chan_dahdi.c.
Referenced by __unload_module(), dahdi_restart(), dahdi_ss7_error(), dahdi_ss7_message(), handle_ss7_block_cic(), handle_ss7_block_linkset(), handle_ss7_debug(), handle_ss7_show_linkset(), handle_ss7_unblock_cic(), handle_ss7_unblock_linkset(), load_module(), setup_dahdi(), ss7_resolve_linkset(), and unload_module().
int matchdigittimeout = 3000 [static] |
How long to wait for an extra digit, if there is an ambiguous match.
Definition at line 332 of file chan_dahdi.c.
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 354 of file chan_dahdi.c.
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 350 of file chan_dahdi.c.
Referenced by __unload_module(), dahdi_restart(), and restart_monitor().
int mwilevel = 512 [static] |
Definition at line 314 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 302 of file chan_dahdi.c.
int mwisend_rpas = 0 [static] |
Definition at line 304 of file chan_dahdi.c.
| char* name |
Definition at line 2370 of file chan_dahdi.c.
int num_cadence = 4 [static] |
Definition at line 1475 of file chan_dahdi.c.
int num_restart_pending = 0 [static] |
Definition at line 359 of file chan_dahdi.c.
int numbufs = 4 [static] |
Definition at line 312 of file chan_dahdi.c.
char parkinglot[AST_MAX_EXTENSION] = "" [static] |
Default parking lot for this channel
Definition at line 299 of file chan_dahdi.c.
Referenced by __find_callno(), ast_iax2_new(), build_peer(), build_user(), check_access(), check_peer_ok(), create_addr_from_peer(), func_channel_write(), gtalk_load_config(), gtalk_new(), set_pvt_defaults(), sip_alloc(), sip_new(), sip_park(), skinny_new(), and store_config_core().
int pridebugfd = -1 [static] |
Definition at line 321 of file chan_dahdi.c.
ast_mutex_t pridebugfdlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 345 of file chan_dahdi.c.
Referenced by dahdi_pri_error(), dahdi_pri_message(), handle_pri_debug(), handle_pri_set_debug_file(), and handle_pri_show_debug().
char pridebugfilename[1024] = "" [static] |
Definition at line 322 of file chan_dahdi.c.
Definition at line 561 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_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 307 of file chan_dahdi.c.
ast_mutex_t restart_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 357 of file chan_dahdi.c.
Referenced by dahdi_restart().
int ringt_base = DEFAULT_RINGT [static] |
Configured ring timeout base.
Definition at line 414 of file chan_dahdi.c.
| struct dahdi_pvt* round_robin[32] |
Definition at line 1430 of file chan_dahdi.c.
ast_cond_t ss_thread_complete [static] |
Definition at line 355 of file chan_dahdi.c.
int ss_thread_count = 0 [static] |
Definition at line 358 of file chan_dahdi.c.
ast_mutex_t ss_thread_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 356 of file chan_dahdi.c.
Referenced by dahdi_restart(), and ss_thread().
char* subnames[] [static] |
{
"Real",
"Callwait",
"Threeway"
}
Definition at line 600 of file chan_dahdi.c.
const char tdesc[] = " & SS7" [static] |
Definition at line 215 of file chan_dahdi.c.
int usedistinctiveringdetection = 0 [static] |
Definition at line 309 of file chan_dahdi.c.
int user_has_defined_cadences = 0 [static] |
Definition at line 1476 of file chan_dahdi.c.
1.7.1