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"
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 | ringContextData |
Defines | |
| #define | ASCII_BYTES_PER_CHAR 80 |
| #define | AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW) |
| #define | CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING) |
| #define | CALLPROGRESS_FAX_INCOMING 4 |
| #define | CALLPROGRESS_FAX_OUTGOING 2 |
| #define | CALLPROGRESS_PROGRESS 1 |
| #define | CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) |
| #define | CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) |
| #define | CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
| #define | CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
| #define | CHAN_PSEUDO -2 |
| #define | CHANNEL_PSEUDO -12 |
| #define | CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) |
| #define | CONF_USER_REAL (1 << 0) |
| #define | CONF_USER_THIRDCALL (1 << 1) |
| #define | DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING) |
| #define | DAHDI_OVERLAPDIAL_INCOMING 2 |
| #define | DAHDI_OVERLAPDIAL_NONE 0 |
| #define | DAHDI_OVERLAPDIAL_OUTGOING 1 |
| #define | DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP) |
| #define | DCHAN_NOTINALARM (1 << 1) |
| #define | DCHAN_PROVISIONED (1 << 0) |
| #define | DCHAN_UP (1 << 2) |
| #define | DEFAULT_CIDRINGS 1 |
| Typically, how many rings before we should send Caller*ID. | |
| #define | DEFAULT_PRI_DEBUG 0 |
| #define | DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) |
| #define | END_SILENCE_LEN 400 |
| #define | FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n" |
| #define | FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" |
| #define | FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n" |
| #define | FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" |
| #define | GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel) |
| #define | HANGUP 1 |
| #define | HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) |
| #define | HEADER_MS 50 |
| #define | ISTRUNK(p) |
| #define | 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_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 | tdesc "DAHDI Telephony w/PRI & SS7" |
| #define | TRAILER_MS 5 |
| #define | TRANSFER 0 |
Enumerations | |
| enum | mwisend_states { MWI_SEND_SA, MWI_SEND_SA_WAIT, MWI_SEND_PAUSE, MWI_SEND_SPILL, MWI_SEND_CLEANUP, MWI_SEND_DONE } |
Functions | |
| static struct ast_frame * | __dahdi_exception (struct ast_channel *ast) |
| static void | __reg_module (void) |
| static int | __unload_module (void) |
| static void | __unreg_module (void) |
| static int | action_dahdidialoffhook (struct mansession *s, const struct message *m) |
| static int | action_dahdidndoff (struct mansession *s, const struct message *m) |
| static int | action_dahdidndon (struct mansession *s, const struct message *m) |
| static int | action_dahdirestart (struct mansession *s, const struct message *m) |
| static int | action_dahdishowchannels (struct mansession *s, const struct message *m) |
| static int | action_transfer (struct mansession *s, const struct message *m) |
| static int | action_transferhangup (struct mansession *s, const struct message *m) |
| static char * | alarm2str (int alm) |
| static int | alloc_sub (struct dahdi_pvt *p, int x) |
| static void | apply_plan_to_number (char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan) |
| static int | attempt_transfer (struct dahdi_pvt *p) |
| static int | available (struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched) |
| static int | build_channels (struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo) |
| static void | build_status (char *s, size_t len, int status, int active) |
| static int | bump_gains (struct dahdi_pvt *p) |
| static int | calc_energy (const unsigned char *buf, int len, int law) |
| static struct dahdi_pvt * | chandup (struct dahdi_pvt *src) |
| static int | check_for_conference (struct dahdi_pvt *p) |
| static 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_5 (const char *line, const char *word, int pos, int state) |
| static char * | complete_span_helper (const char *line, const char *word, int pos, int state, int rpos) |
| static int | conf_add (struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel) |
| static int | conf_del (struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx) |
| static int | dahdi_answer (struct ast_channel *ast) |
| static enum ast_bridge_result | dahdi_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms) |
| static int | dahdi_call (struct ast_channel *ast, char *rdest, int timeout) |
| static int | dahdi_callwait (struct ast_channel *ast) |
| static struct dahdi_chan_conf | dahdi_chan_conf_default (void) |
| static void | dahdi_close (int fd) |
| static void | dahdi_close_pri_fd (struct dahdi_pri *pri, int fd_num) |
| static void | dahdi_close_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_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 void | enable_dtmf_detect (struct dahdi_pvt *p) |
| static char * | event2str (int event) |
| static void | fill_rxgain (struct dahdi_gains *g, float gain, int law) |
| static void | fill_txgain (struct dahdi_gains *g, float gain, int law) |
| static struct dahdi_pvt * | find_channel (int channel) |
| static int | get_alarms (struct dahdi_pvt *p) |
| static void | handle_alarms (struct dahdi_pvt *p, int alms) |
| static char * | handle_dahdi_show_cadences (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static int | handle_init_event (struct dahdi_pvt *i, int event) |
| static char * | handle_pri_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_pri_no_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_pri_really_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_pri_set_debug_file (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_pri_show_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_pri_show_span (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_pri_show_spans (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_pri_unset_debug_file (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_pri_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static 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_no_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 void * | mwi_send_thread (void *data) |
| static void * | mwi_thread (void *data) |
| static int | my_dahdi_write (struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear) |
| static int | my_getsigstr (struct ast_channel *chan, char *str, const char *term, int ms) |
| static void | notify_message (char *mailbox_full, int thereornot) |
| Send MWI state change. | |
| static 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_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 = "DAHDI Telephony w/PRI & SS7" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } |
| struct { | |
| int alarm | |
| char * name | |
| } | alarms [] |
| static struct dahdi_ring_cadence | AS_RP_cadence = {{250, 10000}} |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct dahdi_ring_cadence | cadences [NUM_CADENCE_MAX] |
| static int | cidrings [NUM_CADENCE_MAX] |
| cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on. | |
| static const char | config [] = "chan_dahdi.conf" |
| static 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 char * | dahdi_send_keypad_facility_descrip |
| static char * | dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI" |
| 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 ast_cond_t | mwi_thread_complete |
| static int | mwi_thread_count = 0 |
| static ast_mutex_t | mwi_thread_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
| static int | mwilevel = 512 |
| static char | mwimonitornotify [PATH_MAX] = "" |
| static int | mwisend_rpas = 0 |
| static int | num_cadence = 4 |
| static int | num_restart_pending = 0 |
| static int | numbufs = 4 |
| static char | parkinglot [AST_MAX_EXTENSION] = "" |
| static int | pridebugfd = -1 |
| static ast_mutex_t | pridebugfdlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
| static char | pridebugfilename [1024] = "" |
| static struct dahdi_pri | pris [NUM_SPANS] |
| static char | progzone [10] = "" |
| static ast_mutex_t | restart_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
| static int | ringt_base = DEFAULT_RINGT |
| Configured ring timeout base. | |
| 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 [] |
| 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 153 of file chan_dahdi.c.
Referenced by dahdi_call(), dahdi_callwait(), dahdi_sendtext(), do_monitor(), mwi_send_thread(), mwi_thread(), send_cwcidspill(), and ss_thread().
| #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING) |
Definition at line 224 of file chan_dahdi.c.
Referenced by dahdi_handle_dtmfup(), and process_dahdi().
| #define CALLPROGRESS_FAX_INCOMING 4 |
Definition at line 223 of file chan_dahdi.c.
Referenced by dahdi_new(), and process_dahdi().
| #define CALLPROGRESS_FAX_OUTGOING 2 |
Definition at line 222 of file chan_dahdi.c.
Referenced by dahdi_new(), and process_dahdi().
| #define CALLPROGRESS_PROGRESS 1 |
Definition at line 221 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_new(), and process_dahdi().
| #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) |
| #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) |
300 ms
Definition at line 329 of file chan_dahdi.c.
| #define CANBUSYDETECT | ( | p | ) | (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
Definition at line 1294 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 1295 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), and dahdi_new().
| #define CHAN_PSEUDO -2 |
Definition at line 206 of file chan_dahdi.c.
Referenced by build_channels(), dahdi_new(), dahdi_request(), enable_dtmf_detect(), mkintf(), and process_dahdi().
| #define CHANNEL_PSEUDO -12 |
Definition at line 151 of file chan_dahdi.c.
| #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) |
| #define CONF_USER_REAL (1 << 0) |
Definition at line 511 of file chan_dahdi.c.
| #define CONF_USER_THIRDCALL (1 << 1) |
Definition at line 512 of file chan_dahdi.c.
| #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING) |
Definition at line 218 of file chan_dahdi.c.
Referenced by process_dahdi(), and start_pri().
| #define DAHDI_OVERLAPDIAL_INCOMING 2 |
Definition at line 217 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_read(), handle_pri_show_span(), pri_dchannel(), and process_dahdi().
| #define DAHDI_OVERLAPDIAL_NONE 0 |
Definition at line 215 of file chan_dahdi.c.
Referenced by process_dahdi().
| #define DAHDI_OVERLAPDIAL_OUTGOING 1 |
Definition at line 216 of file chan_dahdi.c.
Referenced by dahdi_read(), process_dahdi(), and start_pri().
| #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP) |
Definition at line 212 of file chan_dahdi.c.
Referenced by pri_find_dchan(), and pri_is_up().
| #define DCHAN_NOTINALARM (1 << 1) |
Definition at line 209 of file chan_dahdi.c.
Referenced by build_status(), pri_dchannel(), and start_pri().
| #define DCHAN_PROVISIONED (1 << 0) |
Definition at line 208 of file chan_dahdi.c.
Referenced by build_status(), pri_create_trunkgroup(), and pri_resolve_span().
| #define DCHAN_UP (1 << 2) |
Definition at line 210 of file chan_dahdi.c.
Referenced by build_status(), and pri_dchannel().
| #define DEFAULT_CIDRINGS 1 |
Typically, how many rings before we should send Caller*ID.
Definition at line 149 of file chan_dahdi.c.
Referenced by dahdi_chan_conf_default().
| #define DEFAULT_PRI_DEBUG 0 |
Definition at line 452 of file chan_dahdi.c.
Referenced by start_pri().
| #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) |
8,000 ms
Definition at line 333 of file chan_dahdi.c.
| #define END_SILENCE_LEN 400 |
Referenced by dahdi_sendtext().
| #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n" |
| #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" |
| #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n" |
| #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" |
| #define GET_CHANNEL | ( | p | ) | ((p)->bearer ? (p)->bearer->channel : p->channel) |
Definition at line 1219 of file chan_dahdi.c.
Referenced by update_conf().
| #define HANGUP 1 |
Definition at line 13323 of file chan_dahdi.c.
Referenced by action_transferhangup(), and dahdi_fake_event().
| #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) |
Referenced by build_alerting(), build_connect(), build_connect_acknowledge(), build_disconnect(), build_facility(), build_hold(), build_hold_acknowledge(), build_hold_reject(), build_information(), build_notify(), build_proceeding(), build_progress(), build_release(), build_release_complete(), build_restart(), build_resume(), build_resume_acknowledge(), build_resume_reject(), build_retrieve(), build_retrieve_acknowledge(), build_retrieve_reject(), build_setup(), build_setup_acknowledge(), build_status(), build_status_enquiry(), build_suspend(), build_suspend_acknowledge(), build_suspend_reject(), build_timeout(), build_user_information(), dahdi_sendtext(), parse_alerting(), parse_connect(), parse_disconnect(), parse_facility(), parse_information(), parse_proceeding(), parse_progress(), parse_release(), parse_release_complete(), parse_restart(), parse_setup(), parse_setup_acknowledge(), and parse_status().
| #define HEADER_MS 50 |
Referenced by dahdi_sendtext().
| #define ISTRUNK | ( | p | ) |
Definition at line 1291 of file chan_dahdi.c.
Referenced by dahdi_indicate(), and ss_thread().
| #define LINKSET_FLAG_EXPLICITACM (1 << 0) |
Definition at line 352 of file chan_dahdi.c.
Referenced by process_dahdi(), and ss7_start_call().
| #define LINKSTATE_DOWN (1 << 3) |
Definition at line 348 of file chan_dahdi.c.
Referenced by linkset_addsigchan(), and ss7_linkset().
| #define LINKSTATE_INALARM (1 << 0) |
Definition at line 345 of file chan_dahdi.c.
Referenced by linkset_addsigchan(), and ss7_linkset().
| #define LINKSTATE_STARTING (1 << 1) |
Definition at line 346 of file chan_dahdi.c.
Referenced by ss7_linkset().
| #define LINKSTATE_UP (1 << 2) |
Definition at line 347 of file chan_dahdi.c.
Referenced by ss7_linkset().
| #define MASK_AVAIL (1 << 0) |
Channel available for PRI use
Definition at line 326 of file chan_dahdi.c.
| #define MASK_INUSE (1 << 1) |
Channel currently in use
Definition at line 327 of file chan_dahdi.c.
| #define MAX_CHANLIST_LEN 80 |
The length of the parameters list of 'dahdichan'.
Definition at line 14182 of file chan_dahdi.c.
Referenced by process_dahdi().
| #define MAX_CHANNELS 672 |
No more than a DS3 per trunk group
Definition at line 204 of file chan_dahdi.c.
Referenced by mkintf().
| #define MAX_SLAVES 4 |
Definition at line 514 of file chan_dahdi.c.
Referenced by dahdi_link(), dahdi_show_channel(), dahdi_unlink(), isslavenative(), and update_conf().
| #define MIN_MS_SINCE_FLASH ( (2000) ) |
| #define NEED_MFDETECT | ( | p | ) | (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB)) |
Signaling types that need to use MF detection should be placed in this macro.
Definition at line 157 of file chan_dahdi.c.
Referenced by dahdi_new(), and ss_thread().
| #define NUM_CADENCE_MAX 25 |
Definition at line 1266 of file chan_dahdi.c.
Referenced by process_dahdi().
| #define NUM_DCHANS 4 |
No more than 4 d-channels
Definition at line 203 of file chan_dahdi.c.
Referenced by dahdi_pri_error(), dahdi_pri_message(), mkintf(), pri_active_dchan_fd(), pri_create_trunkgroup(), pri_find_dchan(), and pri_is_up().
| #define NUM_SPANS 32 |
Definition at line 201 of file chan_dahdi.c.
Referenced by __unload_module(), build_channels(), complete_span_helper(), dahdi_pri_error(), dahdi_pri_message(), dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), dahdi_ss7_error(), dahdi_ss7_message(), handle_pri_debug(), handle_pri_no_debug(), handle_pri_really_debug(), handle_pri_show_debug(), handle_pri_show_span(), handle_pri_show_spans(), handle_ss7_block_cic(), handle_ss7_block_linkset(), handle_ss7_debug(), handle_ss7_no_debug(), handle_ss7_show_linkset(), handle_ss7_unblock_cic(), handle_ss7_unblock_linkset(), linkset_addsigchan(), load_module(), mkintf(), pri_create_trunkgroup(), pri_resolve_span(), process_dahdi(), setup_dahdi(), ss7_resolve_linkset(), and unload_module().
| #define POLARITY_IDLE 0 |
Definition at line 470 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_hangup(), ss_thread(), and unalloc_sub().
| #define POLARITY_REV 1 |
Definition at line 471 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), handle_init_event(), and ss_thread().
| #define PRI_CHANNEL | ( | p | ) | ((p) & 0xff) |
Definition at line 391 of file chan_dahdi.c.
Referenced by pri_dchannel(), and pri_find_principle().
| #define PRI_EXPLICIT | ( | p | ) | (((p) >> 16) & 0x01) |
Definition at line 393 of file chan_dahdi.c.
Referenced by pri_find_principle().
| #define PRI_SPAN | ( | p | ) | (((p) >> 8) & 0xff) |
Definition at line 392 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 14236 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 14238 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 390 of file chan_dahdi.c.
Referenced by dahdi_call(), dahdi_indicate(), dahdi_write(), pri_check_restart(), and pri_dchannel().
| #define READ_SIZE 160 |
Chunk size to read -- we use 20ms chunks to make things happy.
Definition at line 324 of file chan_dahdi.c.
Referenced by dahdi_callwait(), dahdi_open(), dahdi_read(), dahdi_sendtext(), dahdi_setoption(), my_dahdi_write(), process_dahdi(), and send_cwcidspill().
| #define sig2str dahdi_sig2str |
Definition at line 1820 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 186 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_queue_frame(), dahdi_read(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), ss_thread(), and start_pri().
| #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR) |
Definition at line 187 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_queue_frame(), dahdi_read(), dahdi_sig2str(), handle_init_event(), mkintf(), pri_dchannel(), process_dahdi(), ss_thread(), and start_pri().
| #define SIG_E911 (0x1000000 | DAHDI_SIG_EM) |
Definition at line 175 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_EM DAHDI_SIG_EM |
Definition at line 170 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_EM_E1 DAHDI_SIG_EM_E1 |
Definition at line 194 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM) |
Definition at line 171 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM) |
Definition at line 174 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM) |
Definition at line 172 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM) |
Definition at line 173 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM) |
Definition at line 176 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM) |
Definition at line 177 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM) |
Definition at line 178 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FXOGS DAHDI_SIG_FXOGS |
Definition at line 183 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FXOKS DAHDI_SIG_FXOKS |
Definition at line 184 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FXOLS DAHDI_SIG_FXOLS |
Definition at line 182 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FXSGS DAHDI_SIG_FXSGS |
Definition at line 180 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
| #define SIG_FXSKS DAHDI_SIG_FXSKS |
Definition at line 181 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_request(), dahdi_sig2str(), handle_init_event(), mkintf(), pri_dchannel(), process_dahdi(), and ss_thread().
| #define SIG_FXSLS DAHDI_SIG_FXSLS |
Definition at line 179 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS) |
Definition at line 195 of file chan_dahdi.c.
Referenced by dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS) |
Definition at line 196 of file chan_dahdi.c.
Referenced by dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_PRI DAHDI_SIG_CLEAR |
Definition at line 185 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_queue_frame(), dahdi_read(), dahdi_sig2str(), dahdi_write(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_SF DAHDI_SIG_SF |
Definition at line 189 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF) |
Definition at line 193 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF) |
Definition at line 191 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF) |
Definition at line 192 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF) |
Definition at line 190 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR) |
Definition at line 188 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_queue_frame(), dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().
| #define SMDI_MD_WAIT_TIMEOUT 1500 |
Definition at line 104 of file chan_dahdi.c.
Referenced by ss_thread().
| #define SS7_NAI_DYNAMIC -1 |
Definition at line 350 of file chan_dahdi.c.
Referenced by dahdi_call(), and process_dahdi().
| #define SUB_CALLWAIT 1 |
Call-Waiting call on hold
Definition at line 466 of file chan_dahdi.c.
Referenced by available(), dahdi_bridge(), dahdi_call(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_read(), dahdi_request(), dahdi_show_channel(), and ss_thread().
| #define SUB_REAL 0 |
Active call
Definition at line 465 of file chan_dahdi.c.
Referenced by __dahdi_exception(), attempt_transfer(), available(), build_device(), bump_gains(), chandup(), check_for_conference(), close_call(), close_client(), dahdi_answer(), dahdi_bridge(), dahdi_call(), dahdi_confmute(), dahdi_destroy_channel_bynum(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_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(), enable_dtmf_detect(), find_subchannel_by_name(), get_alarms(), handle_init_event(), HandleCallIncoming(), HandleCallOutgoing(), key_call(), key_dial_page(), mkintf(), mwi_send_thread(), mwi_thread(), pri_assign_bearer(), pri_dchannel(), pri_fixup_principle(), process_request(), rcv_mac_addr(), reset_conf(), restore_conference(), restore_gains(), save_conference(), send_callerid(), ss7_linkset(), ss7_start_call(), ss_thread(), TransferCallStep1(), unistim_do_senddigit(), unistim_hangup(), unistim_senddigit_end(), and update_conf().
| #define SUB_THREEWAY 2 |
Three-way call
Definition at line 467 of file chan_dahdi.c.
Referenced by attempt_transfer(), available(), close_call(), dahdi_answer(), dahdi_bridge(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_show_channel(), HandleCallOutgoing(), ss_thread(), TransferCallStep1(), unistim_answer(), and unistim_hangup().
| #define tdesc "DAHDI Telephony w/PRI & SS7" |
Definition at line 15472 of file chan_dahdi.c.
| #define TRAILER_MS 5 |
Referenced by dahdi_sendtext().
| #define TRANSFER 0 |
Definition at line 13322 of file chan_dahdi.c.
Referenced by action_transfer(), dahdi_fake_event(), send_agent_complete(), and try_calling().
| enum mwisend_states |
| MWI_SEND_SA | |
| MWI_SEND_SA_WAIT | |
| MWI_SEND_PAUSE | |
| MWI_SEND_SPILL | |
| MWI_SEND_CLEANUP | |
| MWI_SEND_DONE |
Definition at line 7904 of file chan_dahdi.c.
07904 { 07905 MWI_SEND_SA, 07906 MWI_SEND_SA_WAIT, 07907 MWI_SEND_PAUSE, 07908 MWI_SEND_SPILL, 07909 MWI_SEND_CLEANUP, 07910 MWI_SEND_DONE 07911 };
| static struct ast_frame* __dahdi_exception | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 5544 of file chan_dahdi.c.
References ast_channel::_state, ast_bridged_channel(), AST_CONTROL_UNHOLD, ast_debug, AST_FRAME_NULL, ast_log(), ast_queue_control(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_tv(), ast_tvnow(), ast_verb, dahdi_pvt::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, f, dahdi_pvt::fake_event, ast_channel::fds, dahdi_pvt::flashtime, ast_frame::frametype, LOG_WARNING, ast_frame::mallocd, 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().
05545 { 05546 struct dahdi_pvt *p = ast->tech_pvt; 05547 int res; 05548 int usedindex=-1; 05549 int idx; 05550 struct ast_frame *f; 05551 05552 05553 idx = dahdi_get_index(ast, p, 1); 05554 05555 p->subs[idx].f.frametype = AST_FRAME_NULL; 05556 p->subs[idx].f.datalen = 0; 05557 p->subs[idx].f.samples = 0; 05558 p->subs[idx].f.mallocd = 0; 05559 p->subs[idx].f.offset = 0; 05560 p->subs[idx].f.subclass = 0; 05561 p->subs[idx].f.delivery = ast_tv(0,0); 05562 p->subs[idx].f.src = "dahdi_exception"; 05563 p->subs[idx].f.data.ptr = NULL; 05564 05565 05566 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) { 05567 /* If nobody owns us, absorb the event appropriately, otherwise 05568 we loop indefinitely. This occurs when, during call waiting, the 05569 other end hangs up our channel so that it no longer exists, but we 05570 have neither FLASH'd nor ONHOOK'd to signify our desire to 05571 change to the other channel. */ 05572 if (p->fake_event) { 05573 res = p->fake_event; 05574 p->fake_event = 0; 05575 } else 05576 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 05577 /* Switch to real if there is one and this isn't something really silly... */ 05578 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) && 05579 (res != DAHDI_EVENT_HOOKCOMPLETE)) { 05580 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res); 05581 p->owner = p->subs[SUB_REAL].owner; 05582 if (p->owner && ast_bridged_channel(p->owner)) 05583 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05584 p->subs[SUB_REAL].needunhold = 1; 05585 } 05586 switch (res) { 05587 case DAHDI_EVENT_ONHOOK: 05588 dahdi_disable_ec(p); 05589 if (p->owner) { 05590 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name); 05591 dahdi_ring_phone(p); 05592 p->callwaitingrepeat = 0; 05593 p->cidcwexpire = 0; 05594 } else 05595 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 05596 update_conf(p); 05597 break; 05598 case DAHDI_EVENT_RINGOFFHOOK: 05599 dahdi_enable_ec(p); 05600 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 05601 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) { 05602 p->subs[SUB_REAL].needanswer = 1; 05603 p->dialing = 0; 05604 } 05605 break; 05606 case DAHDI_EVENT_HOOKCOMPLETE: 05607 case DAHDI_EVENT_RINGERON: 05608 case DAHDI_EVENT_RINGEROFF: 05609 /* Do nothing */ 05610 break; 05611 case DAHDI_EVENT_WINKFLASH: 05612 p->flashtime = ast_tvnow(); 05613 if (p->owner) { 05614 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name); 05615 if (p->owner->_state != AST_STATE_UP) { 05616 /* Answer if necessary */ 05617 usedindex = dahdi_get_index(p->owner, p, 0); 05618 if (usedindex > -1) { 05619 p->subs[usedindex].needanswer = 1; 05620 } 05621 ast_setstate(p->owner, AST_STATE_UP); 05622 } 05623 p->callwaitingrepeat = 0; 05624 p->cidcwexpire = 0; 05625 if (ast_bridged_channel(p->owner)) 05626 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05627 p->subs[SUB_REAL].needunhold = 1; 05628 } else 05629 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 05630 update_conf(p); 05631 break; 05632 default: 05633 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res)); 05634 } 05635 f = &p->subs[idx].f; 05636 return f; 05637 } 05638 if (!(p->radio || (p->oprmode < 0))) 05639 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel); 05640 /* If it's not us, return NULL immediately */ 05641 if (ast != p->owner) { 05642 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name); 05643 f = &p->subs[idx].f; 05644 return f; 05645 } 05646 f = dahdi_handle_event(ast); 05647 return f; 05648 }
| static void __reg_module | ( | void | ) | [static] |
Definition at line 15488 of file chan_dahdi.c.
| static int __unload_module | ( | void | ) | [static] |
Definition at line 13999 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, NUM_SPANS, dahdi_pvt::owner, and pris.
Referenced by load_module(), and unload_module().
14000 { 14001 struct dahdi_pvt *p; 14002 #if defined(HAVE_PRI) || defined(HAVE_SS7) 14003 int i, j; 14004 #endif 14005 14006 #ifdef HAVE_PRI 14007 for (i = 0; i < NUM_SPANS; i++) { 14008 if (pris[i].master != AST_PTHREADT_NULL) 14009 pthread_cancel(pris[i].master); 14010 } 14011 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 14012 ast_unregister_application(dahdi_send_keypad_facility_app); 14013 #endif 14014 #if defined(HAVE_SS7) 14015 for (i = 0; i < NUM_SPANS; i++) { 14016 if (linksets[i].master != AST_PTHREADT_NULL) 14017 pthread_cancel(linksets[i].master); 14018 } 14019 ast_cli_unregister_multiple(dahdi_ss7_cli, sizeof(dahdi_ss7_cli) / sizeof(struct ast_cli_entry)); 14020 #endif 14021 14022 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 14023 ast_manager_unregister( "DAHDIDialOffhook" ); 14024 ast_manager_unregister( "DAHDIHangup" ); 14025 ast_manager_unregister( "DAHDITransfer" ); 14026 ast_manager_unregister( "DAHDIDNDoff" ); 14027 ast_manager_unregister( "DAHDIDNDon" ); 14028 ast_manager_unregister("DAHDIShowChannels"); 14029 ast_manager_unregister("DAHDIRestart"); 14030 ast_channel_unregister(&dahdi_tech); 14031 ast_mutex_lock(&iflock); 14032 /* Hangup all interfaces if they have an owner */ 14033 p = iflist; 14034 while (p) { 14035 if (p->owner) 14036 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 14037 p = p->next; 14038 } 14039 ast_mutex_unlock(&iflock); 14040 ast_mutex_lock(&monlock); 14041 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 14042 pthread_cancel(monitor_thread); 14043 pthread_kill(monitor_thread, SIGURG); 14044 pthread_join(monitor_thread, NULL); 14045 } 14046 monitor_thread = AST_PTHREADT_STOP; 14047 ast_mutex_unlock(&monlock); 14048 14049 destroy_all_channels(); 14050 14051 #if defined(HAVE_PRI) 14052 for (i = 0; i < NUM_SPANS; i++) { 14053 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) 14054 pthread_join(pris[i].master, NULL); 14055 for (j = 0; j < NUM_DCHANS; j++) { 14056 dahdi_close_pri_fd(&(pris[i]), j); 14057 } 14058 } 14059 #endif 14060 14061 #if defined(HAVE_SS7) 14062 for (i = 0; i < NUM_SPANS; i++) { 14063 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) 14064 pthread_join(linksets[i].master, NULL); 14065 for (j = 0; j < NUM_DCHANS; j++) { 14066 dahdi_close_ss7_fd(&(linksets[i]), j); 14067 } 14068 } 14069 #endif 14070 14071 ast_cond_destroy(&mwi_thread_complete); 14072 ast_cond_destroy(&ss_thread_complete); 14073 return 0; 14074 }
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 15488 of file chan_dahdi.c.
| static int action_dahdidialoffhook | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 13429 of file chan_dahdi.c.
References AST_FRAME_DTMF, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_queue_frame(), find_channel(), and dahdi_pvt::owner.
Referenced by load_module().
13430 { 13431 struct dahdi_pvt *p = NULL; 13432 const char *channel = astman_get_header(m, "DAHDIChannel"); 13433 const char *number = astman_get_header(m, "Number"); 13434 int i; 13435 13436 if (ast_strlen_zero(channel)) { 13437 astman_send_error(s, m, "No channel specified"); 13438 return 0; 13439 } 13440 if (ast_strlen_zero(number)) { 13441 astman_send_error(s, m, "No number specified"); 13442 return 0; 13443 } 13444 p = find_channel(atoi(channel)); 13445 if (!p) { 13446 astman_send_error(s, m, "No such channel"); 13447 return 0; 13448 } 13449 if (!p->owner) { 13450 astman_send_error(s, m, "Channel does not have it's owner"); 13451 return 0; 13452 } 13453 for (i = 0; i < strlen(number); i++) { 13454 struct ast_frame f = { AST_FRAME_DTMF, number[i] }; 13455 dahdi_queue_frame(p, &f, NULL); 13456 } 13457 astman_send_ack(s, m, "DAHDIDialOffhook"); 13458 return 0; 13459 }
| static int action_dahdidndoff | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 13372 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().
13373 { 13374 struct dahdi_pvt *p = NULL; 13375 const char *channel = astman_get_header(m, "DAHDIChannel"); 13376 13377 if (ast_strlen_zero(channel)) { 13378 astman_send_error(s, m, "No channel specified"); 13379 return 0; 13380 } 13381 p = find_channel(atoi(channel)); 13382 if (!p) { 13383 astman_send_error(s, m, "No such channel"); 13384 return 0; 13385 } 13386 p->dnd = 0; 13387 astman_send_ack(s, m, "DND Disabled"); 13388 return 0; 13389 }
| static int action_dahdidndon | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 13353 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().
13354 { 13355 struct dahdi_pvt *p = NULL; 13356 const char *channel = astman_get_header(m, "DAHDIChannel"); 13357 13358 if (ast_strlen_zero(channel)) { 13359 astman_send_error(s, m, "No channel specified"); 13360 return 0; 13361 } 13362 p = find_channel(atoi(channel)); 13363 if (!p) { 13364 astman_send_error(s, m, "No such channel"); 13365 return 0; 13366 } 13367 p->dnd = 1; 13368 astman_send_ack(s, m, "DND Enabled"); 13369 return 0; 13370 }
| static int action_dahdirestart | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 12646 of file chan_dahdi.c.
References astman_send_ack(), astman_send_error(), and dahdi_restart().
Referenced by load_module().
12647 { 12648 if (dahdi_restart() != 0) { 12649 astman_send_error(s, m, "Failed rereading DAHDI configuration"); 12650 return 1; 12651 } 12652 astman_send_ack(s, m, "DAHDIRestart: Success"); 12653 return 0; 12654 }
| static int action_dahdishowchannels | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 13461 of file chan_dahdi.c.
References alarm2str(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_ack(), dahdi_pvt::channel, channels, dahdi_pvt::context, dahdi_pvt::dnd, get_alarms(), iflist, iflock, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::sig, and sig2str.
Referenced by load_module().
13462 { 13463 struct dahdi_pvt *tmp = NULL; 13464 const char *id = astman_get_header(m, "ActionID"); 13465 const char *dahdichannel = astman_get_header(m, "DAHDIChannel"); 13466 char idText[256] = ""; 13467 int channels = 0; 13468 int dahdichanquery = -1; 13469 if (!ast_strlen_zero(dahdichannel)) { 13470 dahdichanquery = atoi(dahdichannel); 13471 } 13472 13473 astman_send_ack(s, m, "DAHDI channel status will follow"); 13474 if (!ast_strlen_zero(id)) 13475 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 13476 13477 ast_mutex_lock(&iflock); 13478 13479 tmp = iflist; 13480 while (tmp) { 13481 if (tmp->channel > 0) { 13482 int alm = get_alarms(tmp); 13483 13484 /* If a specific channel is queried for, only deliver status for that channel */ 13485 if (dahdichanquery > 0 && tmp->channel != dahdichanquery) 13486 continue; 13487 13488 channels++; 13489 if (tmp->owner) { 13490 /* Add data if we have a current call */ 13491 astman_append(s, 13492 "Event: DAHDIShowChannels\r\n" 13493 "DAHDIChannel: %d\r\n" 13494 "Channel: %s\r\n" 13495 "Uniqueid: %s\r\n" 13496 "AccountCode: %s\r\n" 13497 "Signalling: %s\r\n" 13498 "SignallingCode: %d\r\n" 13499 "Context: %s\r\n" 13500 "DND: %s\r\n" 13501 "Alarm: %s\r\n" 13502 "%s" 13503 "\r\n", 13504 tmp->channel, 13505 tmp->owner->name, 13506 tmp->owner->uniqueid, 13507 tmp->owner->accountcode, 13508 sig2str(tmp->sig), 13509 tmp->sig, 13510 tmp->context, 13511 tmp->dnd ? "Enabled" : "Disabled", 13512 alarm2str(alm), idText); 13513 } else { 13514 astman_append(s, 13515 "Event: DAHDIShowChannels\r\n" 13516 "DAHDIChannel: %d\r\n" 13517 "Signalling: %s\r\n" 13518 "SignallingCode: %d\r\n" 13519 "Context: %s\r\n" 13520 "DND: %s\r\n" 13521 "Alarm: %s\r\n" 13522 "%s" 13523 "\r\n", 13524 tmp->channel, sig2str(tmp->sig), tmp->sig, 13525 tmp->context, 13526 tmp->dnd ? "Enabled" : "Disabled", 13527 alarm2str(alm), idText); 13528 } 13529 } 13530 13531 tmp = tmp->next; 13532 } 13533 13534 ast_mutex_unlock(&iflock); 13535 13536 astman_append(s, 13537 "Event: DAHDIShowChannelsComplete\r\n" 13538 "%s" 13539 "Items: %d\r\n" 13540 "\r\n", 13541 idText, 13542 channels); 13543 return 0; 13544 }
| static int action_transfer | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 13391 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().
13392 { 13393 struct dahdi_pvt *p = NULL; 13394 const char *channel = astman_get_header(m, "DAHDIChannel"); 13395 13396 if (ast_strlen_zero(channel)) { 13397 astman_send_error(s, m, "No channel specified"); 13398 return 0; 13399 } 13400 p = find_channel(atoi(channel)); 13401 if (!p) { 13402 astman_send_error(s, m, "No such channel"); 13403 return 0; 13404 } 13405 dahdi_fake_event(p,TRANSFER); 13406 astman_send_ack(s, m, "DAHDITransfer"); 13407 return 0; 13408 }
| static int action_transferhangup | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 13410 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().
13411 { 13412 struct dahdi_pvt *p = NULL; 13413 const char *channel = astman_get_header(m, "DAHDIChannel"); 13414 13415 if (ast_strlen_zero(channel)) { 13416 astman_send_error(s, m, "No channel specified"); 13417 return 0; 13418 } 13419 p = find_channel(atoi(channel)); 13420 if (!p) { 13421 astman_send_error(s, m, "No such channel"); 13422 return 0; 13423 } 13424 dahdi_fake_event(p,HANGUP); 13425 astman_send_ack(s, m, "DAHDIHangup"); 13426 return 0; 13427 }
| static char* alarm2str | ( | int | alm | ) | [static] |
Definition at line 1725 of file chan_dahdi.c.
References alarm, 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 1521 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().
01522 { 01523 struct dahdi_bufferinfo bi; 01524 int res; 01525 if (p->subs[x].dfd >= 0) { 01526 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel); 01527 return -1; 01528 } 01529 01530 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo"); 01531 if (p->subs[x].dfd <= -1) { 01532 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 01533 return -1; 01534 } 01535 01536 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi); 01537 if (!res) { 01538 bi.txbufpolicy = p->buf_policy; 01539 bi.rxbufpolicy = p->buf_policy; 01540 bi.numbufs = p->buf_no; 01541 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi); 01542 if (res < 0) { 01543 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno)); 01544 } 01545 } else 01546 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno)); 01547 01548 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) { 01549 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno)); 01550 dahdi_close_sub(p, x); 01551 p->subs[x].dfd = -1; 01552 return -1; 01553 } 01554 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan); 01555 return 0; 01556 }
| 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 10834 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().
10835 { 10836 if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */ 10837 snprintf(buf, size, "%s", number); 10838 return; 10839 } 10840 if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */ 10841 if (size) { 10842 *buf = '\0'; 10843 } 10844 return; 10845 } 10846 switch (plan) { 10847 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */ 10848 snprintf(buf, size, "%s%s", pri->internationalprefix, number); 10849 break; 10850 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */ 10851 snprintf(buf, size, "%s%s", pri->nationalprefix, number); 10852 break; 10853 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */ 10854 snprintf(buf, size, "%s%s", pri->localprefix, number); 10855 break; 10856 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */ 10857 snprintf(buf, size, "%s%s", pri->privateprefix, number); 10858 break; 10859 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */ 10860 snprintf(buf, size, "%s%s", pri->unknownprefix, number); 10861 break; 10862 default: /* other Q.931 dialplan => don't twiddle with callingnum */ 10863 snprintf(buf, size, "%s", number); 10864 break; 10865 } 10866 }
| static int attempt_transfer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4491 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, ast_bridged_channel(), ast_channel_masquerade(), ast_channel_unlock, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_debug, ast_indicate(), ast_log(), ast_queue_control(), AST_SOFTHANGUP_DEV, AST_STATE_RING, AST_STATE_RINGING, dahdi_subchannel::dfd, LOG_WARNING, dahdi_subchannel::owner, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and unalloc_sub().
Referenced by dahdi_handle_event().
04492 { 04493 /* In order to transfer, we need at least one of the channels to 04494 actually be in a call bridge. We can't conference two applications 04495 together (but then, why would we want to?) */ 04496 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 04497 /* The three-way person we're about to transfer to could still be in MOH, so 04498 stop if now if appropriate */ 04499 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) 04500 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD); 04501 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) { 04502 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING); 04503 } 04504 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) { 04505 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 04506 } 04507 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { 04508 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 04509 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name); 04510 return -1; 04511 } 04512 /* Orphan the channel after releasing the lock */ 04513 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04514 unalloc_sub(p, SUB_THREEWAY); 04515 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 04516 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 04517 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) { 04518 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING); 04519 } 04520 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) { 04521 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04522 } 04523 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { 04524 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 04525 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); 04526 return -1; 04527 } 04528 /* Three-way is now the REAL */ 04529 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04530 ast_channel_unlock(p->subs[SUB_REAL].owner); 04531 unalloc_sub(p, SUB_THREEWAY); 04532 /* Tell the caller not to hangup */ 04533 return 1; 04534 } else { 04535 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n", 04536 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name); 04537 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04538 return -1; 04539 } 04540 return 0; 04541 }
| static int available | ( | struct dahdi_pvt * | p, | |
| int | channelmatch, | |||
| ast_group_t | groupmatch, | |||
| int * | busy, | |||
| int * | channelmatched, | |||
| int * | groupmatched | |||
| ) | [inline, static] |
Definition at line 9268 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 __ast_string_field_ptr_build_va(), and dahdi_request().
09269 { 09270 int res; 09271 struct dahdi_params par; 09272 09273 /* First, check group matching */ 09274 if (groupmatch) { 09275 if ((p->group & groupmatch) != groupmatch) 09276 return 0; 09277 *groupmatched = 1; 09278 } 09279 /* Check to see if we have a channel match */ 09280 if (channelmatch != -1) { 09281 if (p->channel != channelmatch) 09282 return 0; 09283 *channelmatched = 1; 09284 } 09285 /* We're at least busy at this point */ 09286 if (busy) { 09287 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS)) 09288 *busy = 1; 09289 } 09290 /* If do not disturb, definitely not */ 09291 if (p->dnd) 09292 return 0; 09293 /* If guard time, definitely not */ 09294 if (p->guardtime && (time(NULL) < p->guardtime)) 09295 return 0; 09296 09297 if (p->locallyblocked || p->remotelyblocked) 09298 return 0; 09299 09300 /* If no owner definitely available */ 09301 if (!p->owner) { 09302 #ifdef HAVE_PRI 09303 /* Trust PRI */ 09304 if (p->pri) { 09305 if (p->resetting || p->call) 09306 return 0; 09307 else 09308 return 1; 09309 } 09310 #endif 09311 #ifdef HAVE_SS7 09312 /* Trust SS7 */ 09313 if (p->ss7) { 09314 if (p->ss7call) 09315 return 0; 09316 else 09317 return 1; 09318 } 09319 #endif 09320 if (!(p->radio || (p->oprmode < 0))) 09321 { 09322 if (!p->sig || (p->sig == SIG_FXSLS)) 09323 return 1; 09324 /* Check hook state */ 09325 if (p->subs[SUB_REAL].dfd > -1) { 09326 memset(&par, 0, sizeof(par)); 09327 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 09328 } else { 09329 /* Assume not off hook on CVRS */ 09330 res = 0; 09331 par.rxisoffhook = 0; 09332 } 09333 if (res) { 09334 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno)); 09335 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) { 09336 /* When "onhook" that means no battery on the line, and thus 09337 it is out of service..., if it's on a TDM card... If it's a channel 09338 bank, there is no telling... */ 09339 if (par.rxbits > -1) 09340 return 1; 09341 if (par.rxisoffhook) 09342 return 1; 09343 else 09344 return 0; 09345 } else if (par.rxisoffhook) { 09346 ast_debug(1, "Channel %d off hook, can't use\n", p->channel); 09347 /* Not available when the other end is off hook */ 09348 #ifdef DAHDI_CHECK_HOOKSTATE 09349 return 0; 09350 #else 09351 return 1; 09352 #endif 09353 } 09354 } 09355 return 1; 09356 } 09357 09358 /* If it's not an FXO, forget about call wait */ 09359 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 09360 return 0; 09361 09362 if (!p->callwaiting) { 09363 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */ 09364 return 0; 09365 } 09366 09367 if (p->subs[SUB_CALLWAIT].dfd > -1) { 09368 /* If there is already a call waiting call, then we can't take a second one */ 09369 return 0; 09370 } 09371 09372 if ((p->owner->_state != AST_STATE_UP) && 09373 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) { 09374 /* If the current call is not up, then don't allow the call */ 09375 return 0; 09376 } 09377 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) { 09378 /* Can't take a call wait when the three way calling hasn't been merged yet. */ 09379 return 0; 09380 } 09381 /* We're cool */ 09382 return 1; 09383 }
| 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 14092 of file chan_dahdi.c.
References ast_log(), ast_strdupa, ast_verb, dahdi_chan_conf::chan, chan, CHAN_PSEUDO, dahdi_chan_conf::is_sig_auto, LOG_ERROR, LOG_WARNING, mkintf(), NUM_SPANS, pris, dahdi_pvt::sig, sig2str, strsep(), and dahdi_pri::trunkgroup.
Referenced by process_dahdi().
14093 { 14094 char *c, *chan; 14095 int x, start, finish; 14096 struct dahdi_pvt *tmp; 14097 #ifdef HAVE_PRI 14098 struct dahdi_pri *pri; 14099 int trunkgroup, y; 14100 #endif 14101 14102 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) { 14103 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); 14104 return -1; 14105 } 14106 14107 c = ast_strdupa(value); 14108 14109 #ifdef HAVE_PRI 14110 pri = NULL; 14111 if (iscrv) { 14112 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) { 14113 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno); 14114 return -1; 14115 } 14116 if (trunkgroup < 1) { 14117 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno); 14118 return -1; 14119 } 14120 c += y; 14121 for (y = 0; y < NUM_SPANS; y++) { 14122 if (pris[y].trunkgroup == trunkgroup) { 14123 pri = pris + y; 14124 break; 14125 } 14126 } 14127 if (!pri) { 14128 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno); 14129 return -1; 14130 } 14131 } 14132 #endif 14133 14134 while ((chan = strsep(&c, ","))) { 14135 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) { 14136 /* Range */ 14137 } else if (sscanf(chan, "%30d", &start)) { 14138 /* Just one */ 14139 finish = start; 14140 } else if (!strcasecmp(chan, "pseudo")) { 14141 finish = start = CHAN_PSEUDO; 14142 if (found_pseudo) 14143 *found_pseudo = 1; 14144 } else { 14145 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan); 14146 return -1; 14147 } 14148 if (finish < start) { 14149 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); 14150 x = finish; 14151 finish = start; 14152 start = x; 14153 } 14154 14155 for (x = start; x <= finish; x++) { 14156 #ifdef HAVE_PRI 14157 tmp = mkintf(x, conf, pri, reload); 14158 #else 14159 tmp = mkintf(x, conf, NULL, reload); 14160 #endif 14161 14162 if (tmp) { 14163 #ifdef HAVE_PRI 14164 if (pri) 14165 ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig)); 14166 else 14167 #endif 14168 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig)); 14169 } else { 14170 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n", 14171 (reload == 1) ? "reconfigure" : "register", value); 14172 return -1; 14173 } 14174 } 14175 } 14176 14177 return 0; 14178 }
| static void build_status | ( | char * | s, | |
| size_t | len, | |||
| int | status, | |||
| int | active | |||
| ) | [static] |
Definition at line 12277 of file chan_dahdi.c.
References DCHAN_NOTINALARM, DCHAN_PROVISIONED, and DCHAN_UP.
Referenced by handle_pri_show_span(), and handle_pri_show_spans().
12278 { 12279 if (!s || len < 1) { 12280 return; 12281 } 12282 s[0] = '\0'; 12283 if (status & DCHAN_PROVISIONED) 12284 strncat(s, "Provisioned, ", len - strlen(s) - 1); 12285 if (!(status & DCHAN_NOTINALARM)) 12286 strncat(s, "In Alarm, ", len - strlen(s) - 1); 12287 if (status & DCHAN_UP) 12288 strncat(s, "Up", len - strlen(s) - 1); 12289 else 12290 strncat(s, "Down", len - strlen(s) - 1); 12291 if (active) 12292 strncat(s, ", Active", len - strlen(s) - 1); 12293 else 12294 strncat(s, ", Standby", len - strlen(s) - 1); 12295 s[len - 1] = '\0'; 12296 }
| static int bump_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2180 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().
02181 { 02182 int res; 02183 02184 /* Bump receive gain by value stored in cid_rxgain */ 02185 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law); 02186 if (res) { 02187 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno)); 02188 return -1; 02189 } 02190 02191 return 0; 02192 }
| static int calc_energy | ( | const unsigned char * | buf, | |
| int | len, | |||
| int | law | |||
| ) | [static] |
Definition at line 7756 of file chan_dahdi.c.
References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.
Referenced by do_monitor(), and mwi_thread().
Definition at line 9385 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().
09386 { 09387 struct dahdi_pvt *p; 09388 struct dahdi_bufferinfo bi; 09389 int res; 09390 09391 if ((p = ast_malloc(sizeof(*p)))) { 09392 memcpy(p, src, sizeof(struct dahdi_pvt)); 09393 ast_mutex_init(&p->lock); 09394 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo"); 09395 /* Allocate a dahdi structure */ 09396 if (p->subs[SUB_REAL].dfd < 0) { 09397 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno)); 09398 destroy_dahdi_pvt(&p); 09399 return NULL; 09400 } 09401 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 09402 if (!res) { 09403 bi.txbufpolicy = src->buf_policy; 09404 bi.rxbufpolicy = src->buf_policy; 09405 bi.numbufs = src->buf_no; 09406 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 09407 if (res < 0) { 09408 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno)); 09409 } 09410 } else 09411 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno)); 09412 } 09413 p->destroy = 1; 09414 p->next = iflist; 09415 p->prev = NULL; 09416 iflist = p; 09417 if (iflist->next) 09418 iflist->next->prev = p; 09419 return p; 09420 }
| static int check_for_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4543 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().
04544 { 04545 struct dahdi_confinfo ci; 04546 /* Fine if we already have a master, etc */ 04547 if (p->master || (p->confno > -1)) 04548 return 0; 04549 memset(&ci, 0, sizeof(ci)); 04550 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 04551 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno)); 04552 return 0; 04553 } 04554 /* If we have no master and don't have a confno, then 04555 if we're in a conference, it's probably a MeetMe room or 04556 some such, so don't let us 3-way out! */ 04557 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) { 04558 ast_verb(3, "Avoiding 3-way call when in an external conference\n"); 04559 return 1; 04560 } 04561 return 0; 04562 }
| static unsigned char cid_pres2ss7pres | ( | int | cid_pres | ) | [static] |
Definition at line 2432 of file chan_dahdi.c.
Referenced by dahdi_call().
| static unsigned char cid_pres2ss7screen | ( | int | cid_pres | ) | [static] |
Definition at line 2437 of file chan_dahdi.c.
Referenced by dahdi_call().
| static char* complete_span_4 | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Definition at line 12102 of file chan_dahdi.c.
References complete_span_helper().
Referenced by handle_pri_debug(), and handle_pri_show_span().
12103 { 12104 return complete_span_helper(line,word,pos,state,3); 12105 }
| static char* complete_span_5 | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Definition at line 12107 of file chan_dahdi.c.
References complete_span_helper().
Referenced by handle_pri_no_debug(), and handle_pri_really_debug().
12108 { 12109 return complete_span_helper(line,word,pos,state,4); 12110 }
| static char* complete_span_helper | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state, | |||
| int | rpos | |||
| ) | [static] |
Definition at line 12083 of file chan_dahdi.c.
References asprintf, ast_log(), errno, LOG_WARNING, NUM_SPANS, and pris.
Referenced by complete_span_4(), and complete_span_5().
12084 { 12085 int which, span; 12086 char *ret = NULL; 12087 12088 if (pos != rpos) 12089 return ret; 12090 12091 for (which = span = 0; span < NUM_SPANS; span++) { 12092 if (pris[span].pri && ++which > state) { 12093 if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */ 12094 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 12095 } 12096 break; 12097 } 12098 } 12099 return ret; 12100 }
| static int conf_add | ( | struct dahdi_pvt * | p, | |
| struct dahdi_subchannel * | c, | |||
| int | idx, | |||
| int | slavechannel | |||
| ) | [static] |
Definition at line 1822 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().
01823 { 01824 /* If the conference already exists, and we're already in it 01825 don't bother doing anything */ 01826 struct dahdi_confinfo zi; 01827 01828 memset(&zi, 0, sizeof(zi)); 01829 zi.chan = 0; 01830 01831 if (slavechannel > 0) { 01832 /* If we have only one slave, do a digital mon */ 01833 zi.confmode = DAHDI_CONF_DIGITALMON; 01834 zi.confno = slavechannel; 01835 } else { 01836 if (!idx) { 01837 /* Real-side and pseudo-side both participate in conference */ 01838 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER | 01839 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 01840 } else 01841 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 01842 zi.confno = p->confno; 01843 } 01844 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode)) 01845 return 0; 01846 if (c->dfd < 0) 01847 return 0; 01848 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 01849 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno)); 01850 return -1; 01851 } 01852 if (slavechannel < 1) { 01853 p->confno = zi.confno; 01854 } 01855 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 01856 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 01857 return 0; 01858 }
| static int conf_del | ( | struct dahdi_pvt * | p, | |
| struct dahdi_subchannel * | c, | |||
| int | idx | |||
| ) | [static] |
Definition at line 1871 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().
01872 { 01873 struct dahdi_confinfo zi; 01874 if (/* Can't delete if there's no dfd */ 01875 (c->dfd < 0) || 01876 /* Don't delete from the conference if it's not our conference */ 01877 !isourconf(p, c) 01878 /* Don't delete if we don't think it's conferenced at all (implied) */ 01879 ) return 0; 01880 memset(&zi, 0, sizeof(zi)); 01881 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 01882 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno)); 01883 return -1; 01884 } 01885 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 01886 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 01887 return 0; 01888 }
| static int dahdi_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3731 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_WARNING, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::polaritydelaytv, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, dahdi_pvt::radio, dahdi_pvt::ringt, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, dahdi_pvt::span, 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.
03732 { 03733 struct dahdi_pvt *p = ast->tech_pvt; 03734 int res = 0; 03735 int idx; 03736 int oldstate = ast->_state; 03737 ast_setstate(ast, AST_STATE_UP); 03738 ast_mutex_lock(&p->lock); 03739 idx = dahdi_get_index(ast, p, 0); 03740 if (idx < 0) 03741 idx = SUB_REAL; 03742 /* nothing to do if a radio channel */ 03743 if ((p->radio || (p->oprmode < 0))) { 03744 ast_mutex_unlock(&p->lock); 03745 return 0; 03746 } 03747 switch (p->sig) { 03748 case SIG_FXSLS: 03749 case SIG_FXSGS: 03750 case SIG_FXSKS: 03751 p->ringt = 0; 03752 /* Fall through */ 03753 case SIG_EM: 03754 case SIG_EM_E1: 03755 case SIG_EMWINK: 03756 case SIG_FEATD: 03757 case SIG_FEATDMF: 03758 case SIG_FEATDMF_TA: 03759 case SIG_E911: 03760 case SIG_FGC_CAMA: 03761 case SIG_FGC_CAMAMF: 03762 case SIG_FEATB: 03763 case SIG_SF: 03764 case SIG_SFWINK: 03765 case SIG_SF_FEATD: 03766 case SIG_SF_FEATDMF: 03767 case SIG_SF_FEATB: 03768 case SIG_FXOLS: 03769 case SIG_FXOGS: 03770 case SIG_FXOKS: 03771 /* Pick up the line */ 03772 ast_debug(1, "Took %s off hook\n", ast->name); 03773 if (p->hanguponpolarityswitch) { 03774 p->polaritydelaytv = ast_tvnow(); 03775 } 03776 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 03777 tone_zone_play_tone(p->subs[idx].dfd, -1); 03778 p->dialing = 0; 03779 if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) { 03780 if (oldstate == AST_STATE_RINGING) { 03781 ast_debug(1, "Finally swapping real and threeway\n"); 03782 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1); 03783 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03784 p->owner = p->subs[SUB_REAL].owner; 03785 } 03786 } 03787 if (p->sig & __DAHDI_SIG_FXS) { 03788 dahdi_enable_ec(p); 03789 dahdi_train_ec(p); 03790 } 03791 break; 03792 #ifdef HAVE_PRI 03793 case SIG_BRI: 03794 case SIG_BRI_PTMP: 03795 case SIG_PRI: 03796 /* Send a pri acknowledge */ 03797 if (!pri_grab(p, p->pri)) { 03798 p->proceeding = 1; 03799 p->dialing = 0; 03800 res = pri_answer(p->pri->pri, p->call, 0, !p->digital); 03801 pri_rel(p->pri); 03802 } else { 03803 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 03804 res = -1; 03805 } 03806 break; 03807 #endif 03808 #ifdef HAVE_SS7 03809 case SIG_SS7: 03810 if (!ss7_grab(p, p->ss7)) { 03811 p->proceeding = 1; 03812 res = isup_anm(p->ss7->ss7, p->ss7call); 03813 ss7_rel(p->ss7); 03814 } else { 03815 ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span); 03816 res = -1; 03817 } 03818 break; 03819 #endif 03820 case 0: 03821 ast_mutex_unlock(&p->lock); 03822 return 0; 03823 default: 03824 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel); 03825 res = -1; 03826 } 03827 ast_mutex_unlock(&p->lock); 03828 return res; 03829 }
| 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 4143 of file chan_dahdi.c.
References ast_channel::_state, AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_RETRY, ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_read(), AST_STATE_RINGING, ast_verb, ast_waitfor_n(), ast_write(), dahdi_pvt::call, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_link(), dahdi_unlink(), dahdi_subchannel::dfd, disable_dtmf_detect(), dahdi_pvt::echocanbridged, enable_dtmf_detect(), f, ast_channel::fds, ast_frame::frametype, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, master, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pulsedial, dahdi_pvt::sig, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, ast_channel::tech_pvt, dahdi_pvt::transfer, and update_conf().
04144 { 04145 struct ast_channel *who; 04146 struct dahdi_pvt *p0, *p1, *op0, *op1; 04147 struct dahdi_pvt *master = NULL, *slave = NULL; 04148 struct ast_frame *f; 04149 int inconf = 0; 04150 int nothingok = 1; 04151 int ofd0, ofd1; 04152 int oi0, oi1, i0 = -1, i1 = -1, t0, t1; 04153 int os0 = -1, os1 = -1; 04154 int priority = 0; 04155 struct ast_channel *oc0, *oc1; 04156 enum ast_bridge_result res; 04157 04158 #ifdef PRI_2BCT 04159 int triedtopribridge = 0; 04160 q931_call *q931c0 = NULL, *q931c1 = NULL; 04161 #endif 04162 04163 /* For now, don't attempt to native bridge if either channel needs DTMF detection. 04164 There is code below to handle it properly until DTMF is actually seen, 04165 but due to currently unresolved issues it's ignored... 04166 */ 04167 04168 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 04169 return AST_BRIDGE_FAILED_NOWARN; 04170 04171 ast_channel_lock(c0); 04172 while (ast_channel_trylock(c1)) { 04173 CHANNEL_DEADLOCK_AVOIDANCE(c0); 04174 } 04175 04176 p0 = c0->tech_pvt; 04177 p1 = c1->tech_pvt; 04178 /* cant do pseudo-channels here */ 04179 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) { 04180 ast_channel_unlock(c0); 04181 ast_channel_unlock(c1); 04182 return AST_BRIDGE_FAILED_NOWARN; 04183 } 04184 04185 oi0 = dahdi_get_index(c0, p0, 0); 04186 oi1 = dahdi_get_index(c1, p1, 0); 04187 if ((oi0 < 0) || (oi1 < 0)) { 04188 ast_channel_unlock(c0); 04189 ast_channel_unlock(c1); 04190 return AST_BRIDGE_FAILED; 04191 } 04192 04193 op0 = p0 = c0->tech_pvt; 04194 op1 = p1 = c1->tech_pvt; 04195 ofd0 = c0->fds[0]; 04196 ofd1 = c1->fds[0]; 04197 oc0 = p0->owner; 04198 oc1 = p1->owner; 04199 04200 if (ast_mutex_trylock(&p0->lock)) { 04201 /* Don't block, due to potential for deadlock */ 04202 ast_channel_unlock(c0); 04203 ast_channel_unlock(c1); 04204 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 04205 return AST_BRIDGE_RETRY; 04206 } 04207 if (ast_mutex_trylock(&p1->lock)) { 04208 /* Don't block, due to potential for deadlock */ 04209 ast_mutex_unlock(&p0->lock); 04210 ast_channel_unlock(c0); 04211 ast_channel_unlock(c1); 04212 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 04213 return AST_BRIDGE_RETRY; 04214 } 04215 04216 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 04217 if (p0->owner && p1->owner) { 04218 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */ 04219 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) { 04220 master = p0; 04221 slave = p1; 04222 inconf = 1; 04223 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) { 04224 master = p1; 04225 slave = p0; 04226 inconf = 1; 04227 } else { 04228 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n"); 04229 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n", 04230 p0->channel, 04231 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 04232 p0->subs[SUB_REAL].inthreeway, p0->channel, 04233 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 04234 p1->subs[SUB_REAL].inthreeway); 04235 } 04236 nothingok = 0; 04237 } 04238 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) { 04239 if (p1->subs[SUB_THREEWAY].inthreeway) { 04240 master = p1; 04241 slave = p0; 04242 nothingok = 0; 04243 } 04244 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) { 04245 if (p0->subs[SUB_THREEWAY].inthreeway) { 04246 master = p0; 04247 slave = p1; 04248 nothingok = 0; 04249 } 04250 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) { 04251 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise, 04252 don't put us in anything */ 04253 if (p1->subs[SUB_CALLWAIT].inthreeway) { 04254 master = p1; 04255 slave = p0; 04256 nothingok = 0; 04257 } 04258 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) { 04259 /* Same as previous */ 04260 if (p0->subs[SUB_CALLWAIT].inthreeway) { 04261 master = p0; 04262 slave = p1; 04263 nothingok = 0; 04264 } 04265 } 04266 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n", 04267 master ? master->channel : 0, slave ? slave->channel : 0, nothingok); 04268 if (master && slave) { 04269 /* Stop any tones, or play ringtone as appropriate. If they're bridged 04270 in an active threeway call with a channel that is ringing, we should 04271 indicate ringing. */ 04272 if ((oi1 == SUB_THREEWAY) && 04273 p1->subs[SUB_THREEWAY].inthreeway && 04274 p1->subs[SUB_REAL].owner && 04275 p1->subs[SUB_REAL].inthreeway && 04276 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 04277 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name); 04278 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE); 04279 os1 = p1->subs[SUB_REAL].owner->_state; 04280 } else { 04281 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1); 04282 tone_zone_play_tone(p0->subs[oi0].dfd, -1); 04283 } 04284 if ((oi0 == SUB_THREEWAY) && 04285 p0->subs[SUB_THREEWAY].inthreeway && 04286 p0->subs[SUB_REAL].owner && 04287 p0->subs[SUB_REAL].inthreeway && 04288 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 04289 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name); 04290 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE); 04291 os0 = p0->subs[SUB_REAL].owner->_state; 04292 } else { 04293 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0); 04294 tone_zone_play_tone(p1->subs[oi0].dfd, -1); 04295 } 04296 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 04297 if (!p0->echocanbridged || !p1->echocanbridged) { 04298 /* Disable echo cancellation if appropriate */ 04299 dahdi_disable_ec(p0); 04300 dahdi_disable_ec(p1); 04301 } 04302 } 04303 dahdi_link(slave, master); 04304 master->inconference = inconf; 04305 } else if (!nothingok) 04306 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]); 04307 04308 update_conf(p0); 04309 update_conf(p1); 04310 t0 = p0->subs[SUB_REAL].inthreeway; 04311 t1 = p1->subs[SUB_REAL].inthreeway; 04312 04313 ast_mutex_unlock(&p0->lock); 04314 ast_mutex_unlock(&p1->lock); 04315 04316 ast_channel_unlock(c0); 04317 ast_channel_unlock(c1); 04318 04319 /* Native bridge failed */ 04320 if ((!master || !slave) && !nothingok) { 04321 dahdi_enable_ec(p0); 04322 dahdi_enable_ec(p1); 04323 return AST_BRIDGE_FAILED; 04324 } 04325 04326 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name); 04327 04328 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 04329 disable_dtmf_detect(op0); 04330 04331 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 04332 disable_dtmf_detect(op1); 04333 04334 for (;;) { 04335 struct ast_channel *c0_priority[2] = {c0, c1}; 04336 struct ast_channel *c1_priority[2] = {c1, c0}; 04337 04338 /* Here's our main loop... Start by locking things, looking for private parts, 04339 and then balking if anything is wrong */ 04340 04341 ast_channel_lock(c0); 04342 while (ast_channel_trylock(c1)) { 04343 CHANNEL_DEADLOCK_AVOIDANCE(c0); 04344 } 04345 04346 p0 = c0->tech_pvt; 04347 p1 = c1->tech_pvt; 04348 04349 if (op0 == p0) 04350 i0 = dahdi_get_index(c0, p0, 1); 04351 if (op1 == p1) 04352 i1 = dahdi_get_index(c1, p1, 1); 04353 04354 ast_channel_unlock(c0); 04355 ast_channel_unlock(c1); 04356 04357 if (!timeoutms || 04358 (op0 != p0) || 04359 (op1 != p1) || 04360 (ofd0 != c0->fds[0]) || 04361 (ofd1 != c1->fds[0]) || 04362 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 04363 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 04364 (oc0 != p0->owner) || 04365 (oc1 != p1->owner) || 04366 (t0 != p0->subs[SUB_REAL].inthreeway) || 04367 (t1 != p1->subs[SUB_REAL].inthreeway) || 04368 (oi0 != i0) || 04369 (oi1 != i1)) { 04370 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n", 04371 op0->channel, oi0, op1->channel, oi1); 04372 res = AST_BRIDGE_RETRY; 04373 goto return_from_bridge; 04374 } 04375 04376 #ifdef PRI_2BCT 04377 q931c0 = p0->call; 04378 q931c1 = p1->call; 04379 if (p0->transfer && p1->transfer 04380 && q931c0 && q931c1 04381 && !triedtopribridge) { 04382 pri_channel_bridge(q931c0, q931c1); 04383 triedtopribridge = 1; 04384 } 04385 #endif 04386 04387 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms); 04388 if (!who) { 04389 ast_debug(1, "Ooh, empty read...\n"); 04390 continue; 04391 } 04392 f = ast_read(who); 04393 if (!f || (f->frametype == AST_FRAME_CONTROL)) { 04394 *fo = f; 04395 *rc = who; 04396 res = AST_BRIDGE_COMPLETE; 04397 goto return_from_bridge; 04398 } 04399 if (f->frametype == AST_FRAME_DTMF) { 04400 if ((who == c0) && p0->pulsedial) { 04401 ast_write(c1, f); 04402 } else if ((who == c1) && p1->pulsedial) { 04403 ast_write(c0, f); 04404 } else { 04405 *fo = f; 04406 *rc = who; 04407 res = AST_BRIDGE_COMPLETE; 04408 goto return_from_bridge; 04409 } 04410 } 04411 ast_frfree(f); 04412 04413 /* Swap who gets priority */ 04414 priority = !priority; 04415 } 04416 04417 return_from_bridge: 04418 if (op0 == p0) 04419 dahdi_enable_ec(p0); 04420 04421 if (op1 == p1) 04422 dahdi_enable_ec(p1); 04423 04424 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 04425 enable_dtmf_detect(op0); 04426 04427 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 04428 enable_dtmf_detect(op1); 04429 04430 dahdi_unlink(slave, master, 1); 04431 04432 return res; 04433 }
| static int dahdi_call | ( | struct ast_channel * | ast, | |
| char * | rdest, | |||
| int | timeout | |||
| ) | [static] |
Definition at line 2443 of file chan_dahdi.c.
References ast_channel::_state, dahdi_pvt::answeronpolarityswitch, ast_callerid_generate(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_debug, ast_free, AST_LAW, ast_log(), ast_malloc, ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, AST_STATE_UP, ast_strlen_zero(), ast_transfercapability2str(), ast_tvnow(), ast_verb, dahdi_pvt::bearer, 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, 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::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_ERROR, LOG_WARNING, dahdi_pvt::logicalspan, dahdi_pvt::lspi_ident, MAX_CALLERID_SIZE, 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_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, and dahdi_pvt::whichwink.
02444 { 02445 struct dahdi_pvt *p = ast->tech_pvt; 02446 int x, res, idx,mysig; 02447 char *c, *n, *l; 02448 #ifdef HAVE_PRI 02449 char *s = NULL; 02450 #endif 02451 char dest[256]; /* must be same length as p->dialdest */ 02452 ast_mutex_lock(&p->lock); 02453 ast_copy_string(dest, rdest, sizeof(dest)); 02454 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest)); 02455 if ((ast->_state == AST_STATE_BUSY)) { 02456 p->subs[SUB_REAL].needbusy = 1; 02457 ast_mutex_unlock(&p->lock); 02458 return 0; 02459 } 02460 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 02461 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name); 02462 ast_mutex_unlock(&p->lock); 02463 return -1; 02464 } 02465 p->dialednone = 0; 02466 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ 02467 { 02468 /* Special pseudo -- automatically up */ 02469 ast_setstate(ast, AST_STATE_UP); 02470 ast_mutex_unlock(&p->lock); 02471 return 0; 02472 } 02473 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE; 02474 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 02475 if (res) 02476 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno)); 02477 p->outgoing = 1; 02478 02479 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02480 02481 mysig = p->sig; 02482 if (p->outsigmod > -1) 02483 mysig = p->outsigmod; 02484 02485 switch (mysig) { 02486 case SIG_FXOLS: 02487 case SIG_FXOGS: 02488 case SIG_FXOKS: 02489 if (p->owner == ast) { 02490 /* Normal ring, on hook */ 02491 02492 /* Don't send audio while on hook, until the call is answered */ 02493 p->dialing = 1; 02494 if (p->use_callerid) { 02495 /* Generate the Caller-ID spill if desired */ 02496 if (p->cidspill) { 02497 ast_log(LOG_WARNING, "cidspill already exists??\n"); 02498 ast_free(p->cidspill); 02499 } 02500 p->callwaitcas = 0; 02501 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) { 02502 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p)); 02503 p->cidpos = 0; 02504 send_callerid(p); 02505 } 02506 } 02507 /* Choose proper cadence */ 02508 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { 02509 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) 02510 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); 02511 p->cidrings = cidrings[p->distinctivering - 1]; 02512 } else { 02513 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) 02514 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); 02515 p->cidrings = p->sendcalleridafter; 02516 } 02517 02518 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */ 02519 c = strchr(dest, '/'); 02520 if (c) 02521 c++; 02522 if (c && (strlen(c) < p->stripmsd)) { 02523 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02524 c = NULL; 02525 } 02526 if (c) { 02527 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02528 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c); 02529 ast_debug(1, "FXO: setup deferred dialstring: %s\n", c); 02530 } else { 02531 p->dop.dialstr[0] = '\0'; 02532 } 02533 x = DAHDI_RING; 02534 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) { 02535 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno)); 02536 ast_mutex_unlock(&p->lock); 02537 return -1; 02538 } 02539 p->dialing = 1; 02540 } else { 02541 /* Call waiting call */ 02542 p->callwaitrings = 0; 02543 if (ast->cid.cid_num) 02544 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num)); 02545 else 02546 p->callwait_num[0] = '\0'; 02547 if (ast->cid.cid_name) 02548 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name)); 02549 else 02550 p->callwait_name[0] = '\0'; 02551 /* Call waiting tone instead */ 02552 if (dahdi_callwait(ast)) { 02553 ast_mutex_unlock(&p->lock); 02554 return -1; 02555 } 02556 /* Make ring-back */ 02557 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE)) 02558 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name); 02559 02560 } 02561 n = ast->cid.cid_name; 02562 l = ast->cid.cid_num; 02563 if (l) 02564 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num)); 02565 else 02566 p->lastcid_num[0] = '\0'; 02567 if (n) 02568 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name)); 02569 else 02570 p->lastcid_name[0] = '\0'; 02571 ast_setstate(ast, AST_STATE_RINGING); 02572 idx = dahdi_get_index(ast, p, 0); 02573 if (idx > -1) { 02574 p->subs[idx].needringing = 1; 02575 } 02576 break; 02577 case SIG_FXSLS: 02578 case SIG_FXSGS: 02579 case SIG_FXSKS: 02580 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) { 02581 ast_debug(1, "Ignore possible polarity reversal on line seizure\n"); 02582 p->polaritydelaytv = ast_tvnow(); 02583 } 02584 /* fall through */ 02585 case SIG_EMWINK: 02586 case SIG_EM: 02587 case SIG_EM_E1: 02588 case SIG_FEATD: 02589 case SIG_FEATDMF: 02590 case SIG_E911: 02591 case SIG_FGC_CAMA: 02592 case SIG_FGC_CAMAMF: 02593 case SIG_FEATB: 02594 case SIG_SFWINK: 02595 case SIG_SF: 02596 case SIG_SF_FEATD: 02597 case SIG_SF_FEATDMF: 02598 case SIG_FEATDMF_TA: 02599 case SIG_SF_FEATB: 02600 c = strchr(dest, '/'); 02601 if (c) 02602 c++; 02603 else 02604 c = ""; 02605 if (strlen(c) < p->stripmsd) { 02606 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02607 ast_mutex_unlock(&p->lock); 02608 return -1; 02609 } 02610 #ifdef HAVE_PRI 02611 /* Start the trunk, if not GR-303 */ 02612 if (!p->pri) { 02613 #endif 02614 x = DAHDI_START; 02615 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02616 if (res < 0) { 02617 if (errno != EINPROGRESS) { 02618 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 02619 ast_mutex_unlock(&p->lock); 02620 return -1; 02621 } 02622 } 02623 #ifdef HAVE_PRI 02624 } 02625 #endif 02626 ast_debug(1, "Dialing '%s'\n", c); 02627 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02628 02629 c += p->stripmsd; 02630 02631 switch (mysig) { 02632 case SIG_FEATD: 02633 l = ast->cid.cid_num; 02634 if (l) 02635 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c); 02636 else 02637 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c); 02638 break; 02639 case SIG_FEATDMF: 02640 l = ast->cid.cid_num; 02641 if (l) 02642 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c); 02643 else 02644 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c); 02645 break; 02646 case SIG_FEATDMF_TA: 02647 { 02648 const char *cic, *ozz; 02649 02650 /* If you have to go through a Tandem Access point you need to use this */ 02651 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ"); 02652 if (!ozz) 02653 ozz = defaultozz; 02654 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC"); 02655 if (!cic) 02656 cic = defaultcic; 02657 if (!ozz || !cic) { 02658 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n"); 02659 ast_mutex_unlock(&p->lock); 02660 return -1; 02661 } 02662 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic); 02663 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c); 02664 p->whichwink = 0; 02665 } 02666 break; 02667 case SIG_E911: 02668 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr)); 02669 break; 02670 case SIG_FGC_CAMA: 02671 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c); 02672 break; 02673 case SIG_FGC_CAMAMF: 02674 case SIG_FEATB: 02675 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c); 02676 break; 02677 default: 02678 if (p->pulse) 02679 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c); 02680 else 02681 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c); 02682 break; 02683 } 02684 02685 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) { 02686 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 02687 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 02688 p->echorest[sizeof(p->echorest) - 1] = '\0'; 02689 p->echobreak = 1; 02690 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 02691 } else 02692 p->echobreak = 0; 02693 if (!res) { 02694 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 02695 int saveerr = errno; 02696 02697 x = DAHDI_ONHOOK; 02698 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02699 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 02700 ast_mutex_unlock(&p->lock); 02701 return -1; 02702 } 02703 } else 02704 ast_debug(1, "Deferring dialing...\n"); 02705 02706 p->dialing = 1; 02707 if (ast_strlen_zero(c)) 02708 p->dialednone = 1; 02709 ast_setstate(ast, AST_STATE_DIALING); 02710 break; 02711 case 0: 02712 /* Special pseudo -- automatically up*/ 02713 ast_setstate(ast, AST_STATE_UP); 02714 break; 02715 case SIG_PRI: 02716 case SIG_BRI: 02717 case SIG_BRI_PTMP: 02718 case SIG_SS7: 02719 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */ 02720 p->dialdest[0] = '\0'; 02721 p->dialing = 1; 02722 break; 02723 default: 02724 ast_debug(1, "not yet implemented\n"); 02725 ast_mutex_unlock(&p->lock); 02726 return -1; 02727 } 02728 #ifdef HAVE_SS7 02729 if (p->ss7) { 02730 char ss7_called_nai; 02731 int called_nai_strip; 02732 char ss7_calling_nai; 02733 int calling_nai_strip; 02734 const char *charge_str = NULL; 02735 const char *gen_address = NULL; 02736 const char *gen_digits = NULL; 02737 const char *gen_dig_type = NULL; 02738 const char *gen_dig_scheme = NULL; 02739 const char *gen_name = NULL; 02740 const char *jip_digits = NULL; 02741 const char *lspi_ident = NULL; 02742 const char *rlt_flag = NULL; 02743 const char *call_ref_id = NULL; 02744 const char *call_ref_pc = NULL; 02745 const char *send_far = NULL; 02746 02747 c = strchr(dest, '/'); 02748 if (c) { 02749 c++; 02750 } else { 02751 c = ""; 02752 } 02753 if (strlen(c) < p->stripmsd) { 02754 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02755 ast_mutex_unlock(&p->lock); 02756 return -1; 02757 } 02758 02759 if (!p->hidecallerid) { 02760 l = ast->cid.cid_num; 02761 } else { 02762 l = NULL; 02763 } 02764 02765 if (ss7_grab(p, p->ss7)) { 02766 ast_log(LOG_WARNING, "Failed to grab SS7!\n"); 02767 ast_mutex_unlock(&p->lock); 02768 return -1; 02769 } 02770 p->digital = IS_DIGITAL(ast->transfercapability); 02771 p->ss7call = isup_new_call(p->ss7->ss7); 02772 02773 if (!p->ss7call) { 02774 ss7_rel(p->ss7); 02775 ast_mutex_unlock(&p->lock); 02776 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n"); 02777 return -1; 02778 } 02779 02780 called_nai_strip = 0; 02781 ss7_called_nai = p->ss7->called_nai; 02782 if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */ 02783 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) { 02784 called_nai_strip = strlen(p->ss7->internationalprefix); 02785 ss7_called_nai = SS7_NAI_INTERNATIONAL; 02786 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) { 02787 called_nai_strip = strlen(p->ss7->nationalprefix); 02788 ss7_called_nai = SS7_NAI_NATIONAL; 02789 } else { 02790 ss7_called_nai = SS7_NAI_SUBSCRIBER; 02791 } 02792 } 02793 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7); 02794 02795 calling_nai_strip = 0; 02796 ss7_calling_nai = p->ss7->calling_nai; 02797 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */ 02798 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) { 02799 calling_nai_strip = strlen(p->ss7->internationalprefix); 02800 ss7_calling_nai = SS7_NAI_INTERNATIONAL; 02801 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) { 02802 calling_nai_strip = strlen(p->ss7->nationalprefix); 02803 ss7_calling_nai = SS7_NAI_NATIONAL; 02804 } else { 02805 ss7_calling_nai = SS7_NAI_SUBSCRIBER; 02806 } 02807 } 02808 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai, 02809 p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED), 02810 p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED ); 02811 02812 isup_set_oli(p->ss7call, ast->cid.cid_ani2); 02813 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc); 02814 02815 ast_channel_lock(ast); 02816 /* Set the charge number if it is set */ 02817 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER"); 02818 if (charge_str) 02819 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10); 02820 02821 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS"); 02822 if (gen_address) 02823 isup_set_gen_address(p->ss7call, gen_address, p->gen_add_nai,p->gen_add_pres_ind, p->gen_add_num_plan,p->gen_add_type); /* need to add some types here for NAI,PRES,TYPE */ 02824 02825 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS"); 02826 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE"); 02827 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME"); 02828 if (gen_digits) 02829 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme)); 02830 02831 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME"); 02832 if (gen_name) 02833 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED); 02834 02835 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP"); 02836 if (jip_digits) 02837 isup_set_jip_digits(p->ss7call, jip_digits); 02838 02839 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT"); 02840 if (lspi_ident) 02841 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00); 02842 02843 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON"); 02844 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) { 02845 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */ 02846 } 02847 02848 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT"); 02849 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC"); 02850 if (call_ref_id && call_ref_pc) { 02851 isup_set_callref(p->ss7call, atoi(call_ref_id), 02852 call_ref_pc ? atoi(call_ref_pc) : 0); 02853 } 02854 02855 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR"); 02856 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 )) 02857 (isup_far(p->ss7->ss7, p->ss7call)); 02858 02859 ast_channel_unlock(ast); 02860 02861 isup_iam(p->ss7->ss7, p->ss7call); 02862 ast_setstate(ast, AST_STATE_DIALING); 02863 ss7_rel(p->ss7); 02864 } 02865 #endif /* HAVE_SS7 */ 02866 #ifdef HAVE_PRI 02867 if (p->pri) { 02868 struct pri_sr *sr; 02869 #ifdef SUPPORT_USERUSER 02870 const char *useruser; 02871 #endif 02872 int pridialplan; 02873 int dp_strip; 02874 int prilocaldialplan; 02875 int ldp_strip; 02876 int exclusive; 02877 const char *rr_str; 02878 int redirect_reason; 02879 02880 c = strchr(dest, '/'); 02881 if (c) { 02882 c++; 02883 } else { 02884 c = ""; 02885 } 02886 02887 l = NULL; 02888 n = NULL; 02889 if (!p->hidecallerid) { 02890 l = ast->cid.cid_num; 02891 if (!p->hidecalleridname) { 02892 n = ast->cid.cid_name; 02893 } 02894 } 02895 02896 if (strlen(c) < p->stripmsd) { 02897 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02898 ast_mutex_unlock(&p->lock); 02899 return -1; 02900 } 02901 if (mysig != SIG_FXSKS) { 02902 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02903 s = strchr(c + p->stripmsd, 'w'); 02904 if (s) { 02905 if (strlen(s) > 1) 02906 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s); 02907 else 02908 p->dop.dialstr[0] = '\0'; 02909 *s = '\0'; 02910 } else { 02911 p->dop.dialstr[0] = '\0'; 02912 } 02913 } 02914 if (pri_grab(p, p->pri)) { 02915 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 02916 ast_mutex_unlock(&p->lock); 02917 return -1; 02918 } 02919 if (!(p->call = pri_new_call(p->pri->pri))) { 02920 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel); 02921 pri_rel(p->pri); 02922 ast_mutex_unlock(&p->lock); 02923 return -1; 02924 } 02925 if (!(sr = pri_sr_new())) { 02926 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel); 02927 pri_rel(p->pri); 02928 ast_mutex_unlock(&p->lock); 02929 } 02930 if (p->bearer || (mysig == SIG_FXSKS)) { 02931 if (p->bearer) { 02932 ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel); 02933 p->bearer->call = p->call; 02934 } else 02935 ast_debug(1, "I'm being setup with no bearer right now...\n"); 02936 02937 pri_set_crv(p->pri->pri, p->call, p->channel, 0); 02938 } 02939 p->digital = IS_DIGITAL(ast->transfercapability); 02940 02941 /* Should the picked channel be used exclusively? */ 02942 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) { 02943 exclusive = 1; 02944 } else { 02945 exclusive = 0; 02946 } 02947 02948 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1); 02949 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 02950 (p->digital ? -1 : 02951 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW))); 02952 if (p->pri->facilityenable) 02953 pri_facility_enable(p->pri->pri); 02954 02955 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability)); 02956 dp_strip = 0; 02957 pridialplan = p->pri->dialplan - 1; 02958 if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */ 02959 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 02960 if (pridialplan == -2) { 02961 dp_strip = strlen(p->pri->internationalprefix); 02962 } 02963 pridialplan = PRI_INTERNATIONAL_ISDN; 02964 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 02965 if (pridialplan == -2) { 02966 dp_strip = strlen(p->pri->nationalprefix); 02967 } 02968 pridialplan = PRI_NATIONAL_ISDN; 02969 } else { 02970 pridialplan = PRI_LOCAL_ISDN; 02971 } 02972 } 02973 while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') { 02974 switch (c[p->stripmsd]) { 02975 case 'U': 02976 pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf); 02977 break; 02978 case 'I': 02979 pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf); 02980 break; 02981 case 'N': 02982 pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf); 02983 break; 02984 case 'L': 02985 pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf); 02986 break; 02987 case 'S': 02988 pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf); 02989 break; 02990 case 'V': 02991 pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf); 02992 break; 02993 case 'R': 02994 pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf); 02995 break; 02996 case 'u': 02997 pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0); 02998 break; 02999 case 'e': 03000 pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0); 03001 break; 03002 case 'x': 03003 pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0); 03004 break; 03005 case 'f': 03006 pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0); 03007 break; 03008 case 'n': 03009 pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0); 03010 break; 03011 case 'p': 03012 pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0); 03013 break; 03014 case 'r': 03015 pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0); 03016 break; 03017 default: 03018 if (isalpha(c[p->stripmsd])) { 03019 ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n", 03020 c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]); 03021 } 03022 break; 03023 } 03024 c++; 03025 } 03026 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0); 03027 03028 ldp_strip = 0; 03029 prilocaldialplan = p->pri->localdialplan - 1; 03030 if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */ 03031 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 03032 if (prilocaldialplan == -2) { 03033 ldp_strip = strlen(p->pri->internationalprefix); 03034 } 03035 prilocaldialplan = PRI_INTERNATIONAL_ISDN; 03036 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 03037 if (prilocaldialplan == -2) { 03038 ldp_strip = strlen(p->pri->nationalprefix); 03039 } 03040 prilocaldialplan = PRI_NATIONAL_ISDN; 03041 } else { 03042 prilocaldialplan = PRI_LOCAL_ISDN; 03043 } 03044 } 03045 if (l != NULL) { 03046 while (*l > '9' && *l != '*' && *l != '#') { 03047 switch (*l) { 03048 case 'U': 03049 prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf); 03050 break; 03051 case 'I': 03052 prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf); 03053 break; 03054 case 'N': 03055 prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf); 03056 break; 03057 case 'L': 03058 prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf); 03059 break; 03060 case 'S': 03061 prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf); 03062 break; 03063 case 'V': 03064 prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf); 03065 break; 03066 case 'R': 03067 prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf); 03068 break; 03069 case 'u': 03070 prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0); 03071 break; 03072 case 'e': 03073 prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0); 03074 break; 03075 case 'x': 03076 prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0); 03077 break; 03078 case 'f': 03079 prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0); 03080 break; 03081 case 'n': 03082 prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0); 03083 break; 03084 case 'p': 03085 prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0); 03086 break; 03087 case 'r': 03088 prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0); 03089 break; 03090 default: 03091 if (isalpha(*l)) { 03092 ast_log(LOG_WARNING, 03093 "Unrecognized prilocaldialplan %s modifier: %c\n", 03094 *l > 'Z' ? "NPI" : "TON", *l); 03095 } 03096 break; 03097 } 03098 l++; 03099 } 03100 } 03101 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan, 03102 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE)); 03103 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) { 03104 if (!strcasecmp(rr_str, "UNKNOWN")) 03105 redirect_reason = 0; 03106 else if (!strcasecmp(rr_str, "BUSY")) 03107 redirect_reason = 1; 03108 else if (!strcasecmp(rr_str, "NO_REPLY")) 03109 redirect_reason = 2; 03110 else if (!strcasecmp(rr_str, "UNCONDITIONAL")) 03111 redirect_reason = 15; 03112 else 03113 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03114 } else 03115 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03116 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason); 03117 03118 #ifdef SUPPORT_USERUSER 03119 /* User-user info */ 03120 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO"); 03121 03122 if (useruser) 03123 pri_sr_set_useruser(sr, useruser); 03124 #endif 03125 03126 if (pri_setup(p->pri->pri, p->call, sr)) { 03127 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 03128 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan)); 03129 pri_rel(p->pri); 03130 ast_mutex_unlock(&p->lock); 03131 pri_sr_free(sr); 03132 return -1; 03133 } 03134 pri_sr_free(sr); 03135 ast_setstate(ast, AST_STATE_DIALING); 03136 pri_rel(p->pri); 03137 } 03138 #endif 03139 ast_mutex_unlock(&p->lock); 03140 return 0; 03141 }
| static int dahdi_callwait | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 2403 of file chan_dahdi.c.
References ast_free, ast_gen_cas(), AST_LAW, ast_log(), ast_malloc, dahdi_pvt::callwaitcas, CALLWAITING_REPEAT_SAMPLES, dahdi_pvt::callwaitingcallerid, dahdi_pvt::callwaitingrepeat, dahdi_pvt::callwaitrings, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, LOG_WARNING, READ_SIZE, save_conference(), send_callerid(), and ast_channel::tech_pvt.
Referenced by dahdi_call(), and dahdi_read().
02404 { 02405 struct dahdi_pvt *p = ast->tech_pvt; 02406 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 02407 if (p->cidspill) { 02408 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 02409 ast_free(p->cidspill); 02410 } 02411 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 02412 return -1; 02413 save_conference(p); 02414 /* Silence */ 02415 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 02416 if (!p->callwaitrings && p->callwaitingcallerid) { 02417 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 02418 p->callwaitcas = 1; 02419 p->cidlen = 2400 + 680 + READ_SIZE * 4; 02420 } else { 02421 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 02422 p->callwaitcas = 0; 02423 p->cidlen = 2400 + READ_SIZE * 4; 02424 } 02425 p->cidpos = 0; 02426 send_callerid(p); 02427 02428 return 0; 02429 }
| 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 1093 of file chan_dahdi.c.
References CID_SIG_BELL, CID_START_RING, DEFAULT_CIDRINGS, dahdi_pri::nsf, and dahdi_chan_conf::pri.
Referenced by process_dahdi(), and setup_dahdi().
01093 { 01094 /* recall that if a field is not included here it is initialized 01095 * to 0 or equivalent 01096 */ 01097 struct dahdi_chan_conf conf = { 01098 #ifdef HAVE_PRI 01099 .pri = { 01100 .nsf = PRI_NSF_NONE, 01101 .switchtype = PRI_SWITCH_NI2, 01102 .dialplan = PRI_UNKNOWN + 1, 01103 .localdialplan = PRI_NATIONAL_ISDN + 1, 01104 .nodetype = PRI_CPE, 01105 01106 .minunused = 2, 01107 .idleext = "", 01108 .idledial = "", 01109 .internationalprefix = "", 01110 .nationalprefix = "", 01111 .localprefix = "", 01112 .privateprefix = "", 01113 .unknownprefix = "", 01114 .resetinterval = -1, 01115 }, 01116 #endif 01117 #ifdef HAVE_SS7 01118 .ss7 = { 01119 .called_nai = SS7_NAI_NATIONAL, 01120 .calling_nai = SS7_NAI_NATIONAL, 01121 .internationalprefix = "", 01122 .nationalprefix = "", 01123 .subscriberprefix = "", 01124 .unknownprefix = "" 01125 }, 01126 #endif 01127 .chan = { 01128 .context = "default", 01129 .cid_num = "", 01130 .cid_name = "", 01131 .mohinterpret = "default", 01132 .mohsuggest = "", 01133 .parkinglot = "", 01134 .transfertobusy = 1, 01135 01136 .cid_signalling = CID_SIG_BELL, 01137 .cid_start = CID_START_RING, 01138 .dahditrcallerid = 0, 01139 .use_callerid = 1, 01140 .sig = -1, 01141 .outsigmod = -1, 01142 01143 .cid_rxgain = +5.0, 01144 01145 .tonezone = -1, 01146 01147 .echocancel.head.tap_length = 1, 01148 01149 .busycount = 3, 01150 01151 .accountcode = "", 01152 01153 .mailbox = "", 01154 01155 01156 .polarityonanswerdelay = 600, 01157 01158 .sendcalleridafter = DEFAULT_CIDRINGS, 01159 01160 .buf_policy = DAHDI_POLICY_IMMEDIATE, 01161 .buf_no = numbufs 01162 }, 01163 .timing = { 01164 .prewinktime = -1, 01165 .preflashtime = -1, 01166 .winktime = -1, 01167 .flashtime = -1, 01168 .starttime = -1, 01169 .rxwinktime = -1, 01170 .rxflashtime = -1, 01171 .debouncetime = -1 01172 }, 01173 .is_sig_auto = 1, 01174 .smdi_port = "/dev/ttyS0", 01175 }; 01176 01177 return conf; 01178 }
| static void dahdi_close | ( | int | fd | ) | [static] |
Definition at line 1483 of file chan_dahdi.c.
Referenced by dahdi_close_pri_fd(), dahdi_close_ss7_fd(), and dahdi_close_sub().
| static void dahdi_close_pri_fd | ( | struct dahdi_pri * | pri, | |
| int | fd_num | |||
| ) | [static] |
Definition at line 1496 of file chan_dahdi.c.
References dahdi_close(), and dahdi_pri::fds.
Referenced by __unload_module(), dahdi_restart(), and start_pri().
01497 { 01498 dahdi_close(pri->fds[fd_num]); 01499 pri->fds[fd_num] = -1; 01500 }
| static void dahdi_close_ss7_fd | ( | struct dahdi_ss7 * | ss7, | |
| int | fd_num | |||
| ) | [static] |
Definition at line 1504 of file chan_dahdi.c.
References dahdi_close(), and dahdi_ss7::fds.
Referenced by __unload_module(), dahdi_restart(), and linkset_addsigchan().
01505 { 01506 dahdi_close(ss7->fds[fd_num]); 01507 ss7->fds[fd_num] = -1; 01508 }
| static void dahdi_close_sub | ( | struct dahdi_pvt * | chan_pvt, | |
| int | sub_num | |||
| ) | [static] |
Definition at line 1489 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().
01490 { 01491 dahdi_close(chan_pvt->subs[sub_num].dfd); 01492 chan_pvt->subs[sub_num].dfd = -1; 01493 }
| static int dahdi_confmute | ( | struct dahdi_pvt * | p, | |
| int | muted | |||
| ) | [inline, static] |
Definition at line 2224 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().
02225 { 02226 int x, y, res; 02227 x = muted; 02228 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 02229 y = 1; 02230 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y); 02231 if (res) 02232 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno)); 02233 } 02234 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x); 02235 if (res < 0) 02236 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno)); 02237 return res; 02238 }
| static char* dahdi_destroy_channel | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12454 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_destroy_channel_bynum(), RESULT_SUCCESS, and ast_cli_entry::usage.
12455 { 12456 int channel; 12457 int ret; 12458 switch (cmd) { 12459 case CLI_INIT: 12460 e->command = "dahdi destroy channel"; 12461 e->usage = 12462 "Usage: dahdi destroy channel <chan num>\n" 12463 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n"; 12464 return NULL; 12465 case CLI_GENERATE: 12466 return NULL; 12467 } 12468 if (a->argc != 4) 12469 return CLI_SHOWUSAGE; 12470 12471 channel = atoi(a->argv[3]); 12472 ret = dahdi_destroy_channel_bynum(channel); 12473 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE; 12474 }
| static int dahdi_destroy_channel_bynum | ( | int | channel | ) | [static] |
Definition at line 8066 of file chan_dahdi.c.
References ast_module_unref(), dahdi_pvt::channel, destroy_channel(), dahdi_subchannel::dfd, iflist, dahdi_pvt::next, dahdi_pvt::prev, RESULT_FAILURE, RESULT_SUCCESS, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_destroy_channel(), and handle_init_event().
08067 { 08068 struct dahdi_pvt *tmp = NULL; 08069 struct dahdi_pvt *prev = NULL; 08070 08071 tmp = iflist; 08072 while (tmp) { 08073 if (tmp->channel == channel) { 08074 int x = DAHDI_FLASH; 08075 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 */ 08076 destroy_channel(prev, tmp, 1); 08077 ast_module_unref(ast_module_info->self); 08078 return RESULT_SUCCESS; 08079 } 08080 prev = tmp; 08081 tmp = tmp->next; 08082 } 08083 return RESULT_FAILURE; 08084 }
| static int dahdi_digit_begin | ( | struct ast_channel * | ast, | |
| char | digit | |||
| ) | [static] |
Definition at line 1591 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.
01592 { 01593 struct dahdi_pvt *pvt; 01594 int idx; 01595 int dtmf = -1; 01596 01597 pvt = chan->tech_pvt; 01598 01599 ast_mutex_lock(&pvt->lock); 01600 01601 idx = dahdi_get_index(chan, pvt, 0); 01602 01603 if ((idx != SUB_REAL) || !pvt->owner) 01604 goto out; 01605 01606 #ifdef HAVE_PRI 01607 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP)) 01608 && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) { 01609 if (pvt->setup_ack) { 01610 if (!pri_grab(pvt, pvt->pri)) { 01611 pri_information(pvt->pri->pri, pvt->call, digit); 01612 pri_rel(pvt->pri); 01613 } else 01614 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span); 01615 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) { 01616 int res; 01617 ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit); 01618 res = strlen(pvt->dialdest); 01619 pvt->dialdest[res++] = digit; 01620 pvt->dialdest[res] = '\0'; 01621 } 01622 goto out; 01623 } 01624 #endif 01625 if ((dtmf = digit_to_dtmfindex(digit)) == -1) 01626 goto out; 01627 01628 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) { 01629 int res; 01630 struct dahdi_dialoperation zo = { 01631 .op = DAHDI_DIAL_OP_APPEND, 01632 }; 01633 01634 zo.dialstr[0] = 'T'; 01635 zo.dialstr[1] = digit; 01636 zo.dialstr[2] = '\0'; 01637 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo))) 01638 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno)); 01639 else 01640 pvt->dialing = 1; 01641 } else { 01642 ast_debug(1, "Started VLDTMF digit '%c'\n", digit); 01643 pvt->dialing = 1; 01644 pvt->begindigit = digit; 01645 } 01646 01647 out: 01648 ast_mutex_unlock(&pvt->lock); 01649 01650 return 0; 01651 }
| static int dahdi_digit_end | ( | struct ast_channel * | ast, | |
| char | digit, | |||
| unsigned int | duration | |||
| ) | [static] |
Definition at line 1653 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.
01654 { 01655 struct dahdi_pvt *pvt; 01656 int res = 0; 01657 int idx; 01658 int x; 01659 01660 pvt = chan->tech_pvt; 01661 01662 ast_mutex_lock(&pvt->lock); 01663 01664 idx = dahdi_get_index(chan, pvt, 0); 01665 01666 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse) 01667 goto out; 01668 01669 #ifdef HAVE_PRI 01670 /* This means that the digit was already sent via PRI signalling */ 01671 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP)) 01672 && !pvt->begindigit) 01673 goto out; 01674 #endif 01675 01676 if (pvt->begindigit) { 01677 x = -1; 01678 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit); 01679 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x); 01680 pvt->dialing = 0; 01681 pvt->begindigit = 0; 01682 } 01683 01684 out: 01685 ast_mutex_unlock(&pvt->lock); 01686 01687 return res; 01688 }
| static void dahdi_disable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2053 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().
02054 { 02055 int res; 02056 02057 if (p->echocanon) { 02058 struct dahdi_echocanparams ecp = { .tap_length = 0 }; 02059 02060 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp); 02061 02062 if (res) 02063 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno)); 02064 else 02065 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel); 02066 } 02067 02068 p->echocanon = 0; 02069 }
| 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 6529 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().
06530 { 06531 /* Do not disturb */ 06532 dahdichan->dnd = on; 06533 ast_verb(3, "%s DND on channel %d\n", 06534 on? "Enabled" : "Disabled", 06535 dahdichan->channel); 06536 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 06537 "Channel: DAHDI/%d\r\n" 06538 "Status: %s\r\n", dahdichan->channel, 06539 on? "enabled" : "disabled"); 06540 }
| static void dahdi_enable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2004 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().
02005 { 02006 int x; 02007 int res; 02008 if (!p) 02009 return; 02010 if (p->echocanon) { 02011 ast_debug(1, "Echo cancellation already on\n"); 02012 return; 02013 } 02014 if (p->digital) { 02015 ast_debug(1, "Echo cancellation isn't required on digital connection\n"); 02016 return; 02017 } 02018 if (p->echocancel.head.tap_length) { 02019 if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) { 02020 x = 1; 02021 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x); 02022 if (res) 02023 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno)); 02024 } 02025 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel); 02026 if (res) { 02027 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno)); 02028 } else { 02029 p->echocanon = 1; 02030 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel); 02031 } 02032 } else 02033 ast_debug(1, "No echo cancellation requested\n"); 02034 }
| static struct ast_frame * dahdi_exception | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 5650 of file chan_dahdi.c.
References __dahdi_exception(), ast_mutex_lock(), ast_mutex_unlock(), f, dahdi_pvt::lock, and ast_channel::tech_pvt.
05651 { 05652 struct dahdi_pvt *p = ast->tech_pvt; 05653 struct ast_frame *f; 05654 ast_mutex_lock(&p->lock); 05655 f = __dahdi_exception(ast); 05656 ast_mutex_unlock(&p->lock); 05657 return f; 05658 }
| static int dahdi_fake_event | ( | struct dahdi_pvt * | p, | |
| int | mode | |||
| ) | [static] |
Definition at line 13325 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::fake_event, HANGUP, LOG_WARNING, dahdi_pvt::owner, and TRANSFER.
Referenced by action_transfer(), and action_transferhangup().
13326 { 13327 if (p) { 13328 switch (mode) { 13329 case TRANSFER: 13330 p->fake_event = DAHDI_EVENT_WINKFLASH; 13331 break; 13332 case HANGUP: 13333 p->fake_event = DAHDI_EVENT_ONHOOK; 13334 break; 13335 default: 13336 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name); 13337 } 13338 } 13339 return 0; 13340 }
| static int dahdi_fixup | ( | struct ast_channel * | oldchan, | |
| struct ast_channel * | newchan | |||
| ) | [static] |
Definition at line 4435 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, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::subs, ast_channel::tech_pvt, and update_conf().
04436 { 04437 struct dahdi_pvt *p = newchan->tech_pvt; 04438 int x; 04439 ast_mutex_lock(&p->lock); 04440 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name); 04441 if (p->owner == oldchan) { 04442 p->owner = newchan; 04443 } 04444 for (x = 0; x < 3; x++) 04445 if (p->subs[x].owner == oldchan) { 04446 if (!x) 04447 dahdi_unlink(NULL, p, 0); 04448 p->subs[x].owner = newchan; 04449 } 04450 if (newchan->_state == AST_STATE_RINGING) 04451 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0); 04452 update_conf(p); 04453 ast_mutex_unlock(&p->lock); 04454 return 0; 04455 }
| static int dahdi_func_read | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 4012 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.
04013 { 04014 struct dahdi_pvt *p = chan->tech_pvt; 04015 04016 if (!strcasecmp(data, "rxgain")) { 04017 ast_mutex_lock(&p->lock); 04018 snprintf(buf, len, "%f", p->rxgain); 04019 ast_mutex_unlock(&p->lock); 04020 } else if (!strcasecmp(data, "txgain")) { 04021 ast_mutex_lock(&p->lock); 04022 snprintf(buf, len, "%f", p->txgain); 04023 ast_mutex_unlock(&p->lock); 04024 } else { 04025 ast_copy_string(buf, "", len); 04026 } 04027 return 0; 04028 }
| static int dahdi_get_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition at line 303 of file chan_dahdi.c.
Referenced by __dahdi_exception(), dahdi_handle_event(), do_monitor(), mwi_send_thread(), mwi_thread(), and ss_thread().
| static int dahdi_get_index | ( | struct ast_channel * | ast, | |
| struct dahdi_pvt * | p, | |||
| int | nullok | |||
| ) | [static] |
Definition at line 1297 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().
01298 { 01299 int res; 01300 if (p->subs[SUB_REAL].owner == ast) 01301 res = 0; 01302 else if (p->subs[SUB_CALLWAIT].owner == ast) 01303 res = 1; 01304 else if (p->subs[SUB_THREEWAY].owner == ast) 01305 res = 2; 01306 else { 01307 res = -1; 01308 if (!nullok) 01309 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n"); 01310 } 01311 return res; 01312 }
| static void dahdi_handle_dtmfup | ( | struct ast_channel * | ast, | |
| int | idx, | |||
| struct ast_frame ** | dest | |||
| ) | [static] |
Definition at line 4596 of file chan_dahdi.c.
References ast_async_goto(), ast_channel_lock, ast_channel_unlock, AST_CONTROL_ANSWER, ast_debug, ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_NULL, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verb, dahdi_pvt::callprogress, CALLPROGRESS_FAX, dahdi_pvt::callwaitcas, ast_channel::cid, ast_callerid::cid_num, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, ast_channel::context, dahdi_confmute(), ast_channel::exten, dahdi_subchannel::f, f, dahdi_pvt::faxhandled, ast_frame::frametype, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, pbx_builtin_setvar_helper(), S_OR, send_cwcidspill(), ast_frame::subclass, dahdi_pvt::subs, and ast_channel::tech_pvt.
Referenced by dahdi_handle_event(), and dahdi_read().
04597 { 04598 struct dahdi_pvt *p = ast->tech_pvt; 04599 struct ast_frame *f = *dest; 04600 04601 ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name); 04602 04603 if (p->confirmanswer) { 04604 ast_debug(1, "Confirm answer on %s!\n", ast->name); 04605 /* Upon receiving a DTMF digit, consider this an answer confirmation instead 04606 of a DTMF digit */ 04607 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04608 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 04609 *dest = &p->subs[idx].f; 04610 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */ 04611 p->confirmanswer = 0; 04612 } else if (p->callwaitcas) { 04613 if ((f->subclass == 'A') || (f->subclass == 'D')) { 04614 ast_debug(1, "Got some DTMF, but it's for the CAS\n"); 04615 if (p->cidspill) 04616 ast_free(p->cidspill); 04617 send_cwcidspill(p); 04618 } 04619 p->callwaitcas = 0; 04620 p->subs[idx].f.frametype = AST_FRAME_NULL; 04621 p->subs[idx].f.subclass = 0; 04622 *dest = &p->subs[idx].f; 04623 } else if (f->subclass == 'f') { 04624 /* Fax tone -- Handle and return NULL */ 04625 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) { 04626 p->faxhandled = 1; 04627 if (strcmp(ast->exten, "fax")) { 04628 const char *target_context = S_OR(ast->macrocontext, ast->context); 04629 04630 /* We need to unlock 'ast' here because ast_exists_extension has the 04631 * potential to start autoservice on the channel. Such action is prone 04632 * to deadlock. 04633 */ 04634 ast_mutex_unlock(&p->lock); 04635 ast_channel_unlock(ast); 04636 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) { 04637 ast_channel_lock(ast); 04638 ast_mutex_lock(&p->lock); 04639 ast_verb(3, "Redirecting %s to fax extension\n", ast->name); 04640 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 04641 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 04642 if (ast_async_goto(ast, target_context, "fax", 1)) 04643 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 04644 } else { 04645 ast_channel_lock(ast); 04646 ast_mutex_lock(&p->lock); 04647 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 04648 } 04649 } else { 04650 ast_debug(1, "Already in a fax extension, not redirecting\n"); 04651 } 04652 } else { 04653 ast_debug(1, "Fax already handled\n"); 04654 } 04655 dahdi_confmute(p, 0); 04656 p->subs[idx].f.frametype = AST_FRAME_NULL; 04657 p->subs[idx].f.subclass = 0; 04658 *dest = &p->subs[idx].f; 04659 } 04660 }
| 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 4673 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, alloc_sub(), dahdi_pvt::answeronpolarityswitch, ast_bridged_channel(), AST_CAUSE_NO_ANSWER, ast_channel_trylock, ast_channel_unlock, AST_CONTROL_ANSWER, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_free, ast_hangup(), ast_log(), ast_pthread_create_detached, ast_queue_control(), ast_queue_control_data(), ast_queue_hangup_with_cause(), ast_setstate(), ast_softhangup(), AST_SOFTHANGUP_DEV, AST_SOFTHANGUP_EXPLICIT, AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DIALING_OFFHOOK, AST_STATE_DOWN, AST_STATE_OFFHOOK, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strdup, ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, attempt_transfer(), dahdi_pvt::bearer, dahdi_pvt::call, dahdi_pvt::callprogress, CALLPROGRESS_PROGRESS, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitingrepeat, CANPROGRESSDETECT, ast_channel::cdr, chan, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, check_for_conference(), ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_ani2, dahdi_pvt::cid_name, ast_callerid::cid_name, cid_name, dahdi_pvt::cid_num, ast_callerid::cid_num, cid_num, dahdi_pvt::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, f, dahdi_pvt::fake_event, dahdi_pvt::finaldial, dahdi_pvt::flashtime, ast_frame::frametype, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::inalarm, dahdi_subchannel::inthreeway, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, manager_event, MIN_MS_SINCE_FLASH, dahdi_pvt::mohsuggest, dahdi_pvt::msgstate, 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, POLARITY_IDLE, POLARITY_REV, dahdi_pvt::polaritydelaytv, dahdi_pvt::polarityonanswerdelay, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, ast_frame::ptr, dahdi_pvt::pulsedial, dahdi_pvt::radio, restore_conference(), ast_channel::rings, dahdi_pvt::ringt, dahdi_pvt::ringt_base, S_OR, ast_frame::samples, save_conference(), dahdi_pvt::sig, sig2str, SIG_BRI, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, ast_frame::src, ss_thread(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, ast_frame::subclass, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, dahdi_pvt::threewaycalling, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, unalloc_sub(), update_conf(), and dahdi_pvt::whichwink.
Referenced by __dahdi_exception().
04674 { 04675 int res, x; 04676 int idx, mysig; 04677 char *c; 04678 struct dahdi_pvt *p = ast->tech_pvt; 04679 pthread_t threadid; 04680 struct ast_channel *chan; 04681 struct ast_frame *f; 04682 04683 idx = dahdi_get_index(ast, p, 0); 04684 mysig = p->sig; 04685 if (p->outsigmod > -1) 04686 mysig = p->outsigmod; 04687 p->subs[idx].f.frametype = AST_FRAME_NULL; 04688 p->subs[idx].f.subclass = 0; 04689 p->subs[idx].f.datalen = 0; 04690 p->subs[idx].f.samples = 0; 04691 p->subs[idx].f.mallocd = 0; 04692 p->subs[idx].f.offset = 0; 04693 p->subs[idx].f.src = "dahdi_handle_event"; 04694 p->subs[idx].f.data.ptr = NULL; 04695 f = &p->subs[idx].f; 04696 04697 if (idx < 0) 04698 return &p->subs[idx].f; 04699 if (p->fake_event) { 04700 res = p->fake_event; 04701 p->fake_event = 0; 04702 } else 04703 res = dahdi_get_event(p->subs[idx].dfd); 04704 04705 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx); 04706 04707 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) { 04708 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0; 04709 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff); 04710 #ifdef HAVE_PRI 04711 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 04712 /* absorb event */ 04713 } else { 04714 #endif 04715 dahdi_confmute(p, 0); 04716 p->subs[idx].f.frametype = AST_FRAME_DTMF_END; 04717 p->subs[idx].f.subclass = res & 0xff; 04718 #ifdef HAVE_PRI 04719 } 04720 #endif 04721 dahdi_handle_dtmfup(ast, idx, &f); 04722 return f; 04723 } 04724 04725 if (res & DAHDI_EVENT_DTMFDOWN) { 04726 ast_debug(1, "DTMF Down '%c'\n", res & 0xff); 04727 /* Mute conference */ 04728 dahdi_confmute(p, 1); 04729 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN; 04730 p->subs[idx].f.subclass = res & 0xff; 04731 return &p->subs[idx].f; 04732 } 04733 04734 switch (res) { 04735 case DAHDI_EVENT_EC_DISABLED: 04736 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel); 04737 p->echocanon = 0; 04738 break; 04739 case DAHDI_EVENT_BITSCHANGED: 04740 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig)); 04741 case DAHDI_EVENT_PULSE_START: 04742 /* Stop tone if there's a pulse start and the PBX isn't started */ 04743 if (!ast->pbx) 04744 tone_zone_play_tone(p->subs[idx].dfd, -1); 04745 break; 04746 case DAHDI_EVENT_DIALCOMPLETE: 04747 if (p->inalarm) break; 04748 if ((p->radio || (p->oprmode < 0))) break; 04749 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) { 04750 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno)); 04751 return NULL; 04752 } 04753 if (!x) { /* if not still dialing in driver */ 04754 dahdi_enable_ec(p); 04755 if (p->echobreak) { 04756 dahdi_train_ec(p); 04757 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); 04758 p->dop.op = DAHDI_DIAL_OP_REPLACE; 04759 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 04760 p->echobreak = 0; 04761 } else { 04762 p->dialing = 0; 04763 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) { 04764 /* if thru with dialing after offhook */ 04765 if (ast->_state == AST_STATE_DIALING_OFFHOOK) { 04766 ast_setstate(ast, AST_STATE_UP); 04767 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04768 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 04769 break; 04770 } else { /* if to state wait for offhook to dial rest */ 04771 /* we now wait for off hook */ 04772 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK); 04773 } 04774 } 04775 if (ast->_state == AST_STATE_DIALING) { 04776 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 04777 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n"); 04778 } 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)))) { 04779 ast_setstate(ast, AST_STATE_RINGING); 04780 } else if (!p->answeronpolarityswitch) { 04781 ast_setstate(ast, AST_STATE_UP); 04782 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04783 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 04784 /* If aops=0 and hops=1, this is necessary */ 04785 p->polarity = POLARITY_REV; 04786 } else { 04787 /* Start clean, so we can catch the change to REV polarity when party answers */ 04788 p->polarity = POLARITY_IDLE; 04789 } 04790 } 04791 } 04792 } 04793 break; 04794 case DAHDI_EVENT_ALARM: 04795 #ifdef HAVE_PRI 04796 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 04797 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) { 04798 /* T309 is not enabled : hangup calls when alarm occurs */ 04799 if (p->call) { 04800 if (p->pri && p->pri->pri) { 04801 if (!pri_grab(p, p->pri)) { 04802 pri_hangup(p->pri->pri, p->call, -1); 04803 pri_destroycall(p->pri->pri, p->call); 04804 p->call = NULL; 04805 pri_rel(p->pri); 04806 } else 04807 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 04808 } else 04809 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n"); 04810 } 04811 if (p->owner) 04812 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 04813 } 04814 } 04815 if (p->bearer) 04816 p->bearer->inalarm = 1; 04817 else 04818 #endif 04819 p->inalarm = 1; 04820 res = get_alarms(p); 04821 handle_alarms(p, res); 04822 #ifdef HAVE_PRI 04823 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 04824 /* fall through intentionally */ 04825 } else { 04826 break; 04827 } 04828 #endif 04829 #ifdef HAVE_SS7 04830 if (p->sig == SIG_SS7) 04831 break; 04832 #endif 04833 case DAHDI_EVENT_ONHOOK: 04834 if (p->radio) { 04835 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04836 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY; 04837 break; 04838 } 04839 if (p->oprmode < 0) 04840 { 04841 if (p->oprmode != -1) break; 04842 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 04843 { 04844 /* Make sure it starts ringing */ 04845 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 04846 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING); 04847 save_conference(p->oprpeer); 04848 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04849 } 04850 break; 04851 } 04852 switch (p->sig) { 04853 case SIG_FXOLS: 04854 case SIG_FXOGS: 04855 case SIG_FXOKS: 04856 p->onhooktime = time(NULL); 04857 p->msgstate = -1; 04858 /* Check for some special conditions regarding call waiting */ 04859 if (idx == SUB_REAL) { 04860 /* The normal line was hung up */ 04861 if (p->subs[SUB_CALLWAIT].owner) { 04862 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */ 04863 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 04864 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel); 04865 unalloc_sub(p, SUB_CALLWAIT); 04866 #if 0 04867 p->subs[idx].needanswer = 0; 04868 p->subs[idx].needringing = 0; 04869 #endif 04870 p->callwaitingrepeat = 0; 04871 p->cidcwexpire = 0; 04872 p->owner = NULL; 04873 /* Don't start streaming audio yet if the incoming call isn't up yet */ 04874 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP) 04875 p->dialing = 1; 04876 dahdi_ring_phone(p); 04877 } else if (p->subs[SUB_THREEWAY].owner) { 04878 unsigned int mssinceflash; 04879 /* Here we have to retain the lock on both the main channel, the 3-way channel, and 04880 the private structure -- not especially easy or clean */ 04881 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) { 04882 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */ 04883 DLA_UNLOCK(&p->lock); 04884 CHANNEL_DEADLOCK_AVOIDANCE(ast); 04885 /* We can grab ast and p in that order, without worry. We should make sure 04886 nothing seriously bad has happened though like some sort of bizarre double 04887 masquerade! */ 04888 DLA_LOCK(&p->lock); 04889 if (p->owner != ast) { 04890 ast_log(LOG_WARNING, "This isn't good...\n"); 04891 return NULL; 04892 } 04893 } 04894 if (!p->subs[SUB_THREEWAY].owner) { 04895 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n"); 04896 return NULL; 04897 } 04898 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime); 04899 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash); 04900 if (mssinceflash < MIN_MS_SINCE_FLASH) { 04901 /* It hasn't been long enough since the last flashook. This is probably a bounce on 04902 hanging up. Hangup both channels now */ 04903 if (p->subs[SUB_THREEWAY].owner) 04904 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER); 04905 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04906 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel); 04907 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04908 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) { 04909 if (p->transfer) { 04910 /* In any case this isn't a threeway call anymore */ 04911 p->subs[SUB_REAL].inthreeway = 0; 04912 p->subs[SUB_THREEWAY].inthreeway = 0; 04913 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */ 04914 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) { 04915 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04916 /* Swap subs and dis-own channel */ 04917 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04918 p->owner = NULL; 04919 /* Ring the phone */ 04920 dahdi_ring_phone(p); 04921 } else { 04922 if ((res = attempt_transfer(p)) < 0) { 04923 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04924 if (p->subs[SUB_THREEWAY].owner) 04925 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04926 } else if (res) { 04927 /* Don't actually hang up at this point */ 04928 if (p->subs[SUB_THREEWAY].owner) 04929 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04930 break; 04931 } 04932 } 04933 } else { 04934 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04935 if (p->subs[SUB_THREEWAY].owner) 04936 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04937 } 04938 } else { 04939 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04940 /* Swap subs and dis-own channel */ 04941 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04942 p->owner = NULL; 04943 /* Ring the phone */ 04944 dahdi_ring_phone(p); 04945 } 04946 } 04947 } else { 04948 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx); 04949 } 04950 /* Fall through */ 04951 default: 04952 dahdi_disable_ec(p); 04953 return NULL; 04954 } 04955 break; 04956 case DAHDI_EVENT_RINGOFFHOOK: 04957 if (p->inalarm) break; 04958 if (p->oprmode < 0) 04959 { 04960 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 04961 { 04962 /* Make sure it stops ringing */ 04963 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 04964 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1); 04965 restore_conference(p->oprpeer); 04966 } 04967 break; 04968 } 04969 if (p->radio) 04970 { 04971 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04972 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY; 04973 break; 04974 } 04975 /* for E911, its supposed to wait for offhook then dial 04976 the second half of the dial string */ 04977 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) { 04978 c = strchr(p->dialdest, '/'); 04979 if (c) 04980 c++; 04981 else 04982 c = p->dialdest; 04983 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c); 04984 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr)); 04985 if (strlen(p->dop.dialstr) > 4) { 04986 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 04987 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 04988 p->echorest[sizeof(p->echorest) - 1] = '\0'; 04989 p->echobreak = 1; 04990 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 04991 } else 04992 p->echobreak = 0; 04993 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 04994 int saveerr = errno; 04995 04996 x = DAHDI_ONHOOK; 04997 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04998 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 04999 return NULL; 05000 } 05001 p->dialing = 1; 05002 return &p->subs[idx].f; 05003 } 05004 switch (p->sig) { 05005 case SIG_FXOLS: 05006 case SIG_FXOGS: 05007 case SIG_FXOKS: 05008 switch (ast->_state) { 05009 case AST_STATE_RINGING: 05010 dahdi_enable_ec(p); 05011 dahdi_train_ec(p); 05012 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05013 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 05014 /* Make sure it stops ringing */ 05015 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 05016 ast_debug(1, "channel %d answered\n", p->channel); 05017 if (p->cidspill) { 05018 /* Cancel any running CallerID spill */ 05019 ast_free(p->cidspill); 05020 p->cidspill = NULL; 05021 } 05022 p->dialing = 0; 05023 p->callwaitcas = 0; 05024 if (p->confirmanswer) { 05025 /* Ignore answer if "confirm answer" is enabled */ 05026 p->subs[idx].f.frametype = AST_FRAME_NULL; 05027 p->subs[idx].f.subclass = 0; 05028 } else if (!ast_strlen_zero(p->dop.dialstr)) { 05029 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ 05030 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05031 if (res < 0) { 05032 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05033 p->dop.dialstr[0] = '\0'; 05034 return NULL; 05035 } else { 05036 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr); 05037 p->subs[idx].f.frametype = AST_FRAME_NULL; 05038 p->subs[idx].f.subclass = 0; 05039 p->dialing = 1; 05040 } 05041 p->dop.dialstr[0] = '\0'; 05042 ast_setstate(ast, AST_STATE_DIALING); 05043 } else 05044 ast_setstate(ast, AST_STATE_UP); 05045 return &p->subs[idx].f; 05046 case AST_STATE_DOWN: 05047 ast_setstate(ast, AST_STATE_RING); 05048 ast->rings = 1; 05049 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05050 p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK; 05051 ast_debug(1, "channel %d picked up\n", p->channel); 05052 return &p->subs[idx].f; 05053 case AST_STATE_UP: 05054 /* Make sure it stops ringing */ 05055 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 05056 /* Okay -- probably call waiting*/ 05057 if (ast_bridged_channel(p->owner)) 05058 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05059 p->subs[idx].needunhold = 1; 05060 break; 05061 case AST_STATE_RESERVED: 05062 /* Start up dialtone */ 05063 if (has_voicemail(p)) 05064 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 05065 else 05066 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 05067 break; 05068 default: 05069 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state); 05070 } 05071 break; 05072 case SIG_FXSLS: 05073 case SIG_FXSGS: 05074 case SIG_FXSKS: 05075 if (ast->_state == AST_STATE_RING) { 05076 p->ringt = p->ringt_base; 05077 } 05078 05079 /* If we get a ring then we cannot be in 05080 * reversed polarity. So we reset to idle */ 05081 ast_debug(1, "Setting IDLE polarity due " 05082 "to ring. Old polarity was %d\n", 05083 p->polarity); 05084 p->polarity = POLARITY_IDLE; 05085 05086 /* Fall through */ 05087 case SIG_EM: 05088 case SIG_EM_E1: 05089 case SIG_EMWINK: 05090 case SIG_FEATD: 05091 case SIG_FEATDMF: 05092 case SIG_FEATDMF_TA: 05093 case SIG_E911: 05094 case SIG_FGC_CAMA: 05095 case SIG_FGC_CAMAMF: 05096 case SIG_FEATB: 05097 case SIG_SF: 05098 case SIG_SFWINK: 05099 case SIG_SF_FEATD: 05100 case SIG_SF_FEATDMF: 05101 case SIG_SF_FEATB: 05102 if (ast->_state == AST_STATE_PRERING) 05103 ast_setstate(ast, AST_STATE_RING); 05104 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) { 05105 ast_debug(1, "Ring detected\n"); 05106 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05107 p->subs[idx].f.subclass = AST_CONTROL_RING; 05108 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) { 05109 ast_debug(1, "Line answered\n"); 05110 if (p->confirmanswer) { 05111 p->subs[idx].f.frametype = AST_FRAME_NULL; 05112 p->subs[idx].f.subclass = 0; 05113 } else { 05114 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05115 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 05116 ast_setstate(ast, AST_STATE_UP); 05117 } 05118 } else if (ast->_state != AST_STATE_RING) 05119 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel); 05120 break; 05121 default: 05122 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 05123 } 05124 break; 05125 case DAHDI_EVENT_RINGBEGIN: 05126 switch (p->sig) { 05127 case SIG_FXSLS: 05128 case SIG_FXSGS: 05129 case SIG_FXSKS: 05130 if (ast->_state == AST_STATE_RING) { 05131 p->ringt = p->ringt_base; 05132 } 05133 break; 05134 } 05135 break; 05136 case DAHDI_EVENT_RINGEROFF: 05137 if (p->inalarm) break; 05138 if ((p->radio || (p->oprmode < 0))) break; 05139 ast->rings++; 05140 if ((ast->rings > p->cidrings) && (p->cidspill)) { 05141 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n"); 05142 ast_free(p->cidspill); 05143 p->cidspill = NULL; 05144 p->callwaitcas = 0; 05145 } 05146 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05147 p->subs[idx].f.subclass = AST_CONTROL_RINGING; 05148 break; 05149 case DAHDI_EVENT_RINGERON: 05150 break; 05151 case DAHDI_EVENT_NOALARM: 05152 p->inalarm = 0; 05153 #ifdef HAVE_PRI 05154 /* Extremely unlikely but just in case */ 05155 if (p->bearer) 05156 p->bearer->inalarm = 0; 05157 #endif 05158 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 05159 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 05160 "Channel: %d\r\n", p->channel); 05161 break; 05162 case DAHDI_EVENT_WINKFLASH: 05163 if (p->inalarm) break; 05164 if (p->radio) break; 05165 if (p->oprmode < 0) break; 05166 if (p->oprmode > 1) 05167 { 05168 struct dahdi_params par; 05169 05170 memset(&par, 0, sizeof(par)); 05171 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1) 05172 { 05173 if (!par.rxisoffhook) 05174 { 05175 /* Make sure it stops ringing */ 05176 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 05177 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING); 05178 save_conference(p); 05179 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05180 } 05181 } 05182 break; 05183 } 05184 /* Remember last time we got a flash-hook */ 05185 p->flashtime = ast_tvnow(); 05186 switch (mysig) { 05187 case SIG_FXOLS: 05188 case SIG_FXOGS: 05189 case SIG_FXOKS: 05190 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n", 05191 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 05192 p->callwaitcas = 0; 05193 05194 if (idx != SUB_REAL) { 05195 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel); 05196 goto winkflashdone; 05197 } 05198 05199 if (p->subs[SUB_CALLWAIT].owner) { 05200 /* Swap to call-wait */ 05201 swap_subs(p, SUB_REAL, SUB_CALLWAIT); 05202 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 05203 p->owner = p->subs[SUB_REAL].owner; 05204 ast_debug(1, "Making %s the new owner\n", p->owner->name); 05205 if (p->owner->_state == AST_STATE_RINGING) { 05206 ast_setstate(p->owner, AST_STATE_UP); 05207 p->subs[SUB_REAL].needanswer = 1; 05208 } 05209 p->callwaitingrepeat = 0; 05210 p->cidcwexpire = 0; 05211 /* Start music on hold if appropriate */ 05212 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 05213 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 05214 S_OR(p->mohsuggest, NULL), 05215 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05216 } 05217 p->subs[SUB_CALLWAIT].needhold = 1; 05218 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 05219 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD, 05220 S_OR(p->mohsuggest, NULL), 05221 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05222 } 05223 p->subs[SUB_REAL].needunhold = 1; 05224 } else if (!p->subs[SUB_THREEWAY].owner) { 05225 if (!p->threewaycalling) { 05226 /* Just send a flash if no 3-way calling */ 05227 p->subs[SUB_REAL].needflash = 1; 05228 goto winkflashdone; 05229 } else if (!check_for_conference(p)) { 05230 char cid_num[256]; 05231 char cid_name[256]; 05232 05233 cid_num[0] = 0; 05234 cid_name[0] = 0; 05235 if (p->dahditrcallerid && p->owner) { 05236 if (p->owner->cid.cid_num) 05237 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num)); 05238 if (p->owner->cid.cid_name) 05239 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name)); 05240 } 05241 /* XXX This section needs much more error checking!!! XXX */ 05242 /* Start a 3-way call if feasible */ 05243 if (!((ast->pbx) || 05244 (ast->_state == AST_STATE_UP) || 05245 (ast->_state == AST_STATE_RING))) { 05246 ast_debug(1, "Flash when call not up or ringing\n"); 05247 goto winkflashdone; 05248 } 05249 if (alloc_sub(p, SUB_THREEWAY)) { 05250 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n"); 05251 goto winkflashdone; 05252 } 05253 /* Make new channel */ 05254 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0); 05255 if (p->dahditrcallerid) { 05256 if (!p->origcid_num) 05257 p->origcid_num = ast_strdup(p->cid_num); 05258 if (!p->origcid_name) 05259 p->origcid_name = ast_strdup(p->cid_name); 05260 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num)); 05261 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name)); 05262 } 05263 /* Swap things around between the three-way and real call */ 05264 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05265 /* Disable echo canceller for better dialing */ 05266 dahdi_disable_ec(p); 05267 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL); 05268 if (res) 05269 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel); 05270 p->owner = chan; 05271 if (!chan) { 05272 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel); 05273 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 05274 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel); 05275 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 05276 dahdi_enable_ec(p); 05277 ast_hangup(chan); 05278 } else { 05279 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 05280 int way3bridge = 0, cdr3way = 0; 05281 05282 if (!other) { 05283 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 05284 } else 05285 way3bridge = 1; 05286 05287 if (p->subs[SUB_THREEWAY].owner->cdr) 05288 cdr3way = 1; 05289 05290 ast_verb(3, "Started three way call on channel %d\n", p->channel); 05291 05292 /* Start music on hold if appropriate */ 05293 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 05294 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 05295 S_OR(p->mohsuggest, NULL), 05296 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05297 } 05298 p->subs[SUB_THREEWAY].needhold = 1; 05299 } 05300 } 05301 } else { 05302 /* Already have a 3 way call */ 05303 if (p->subs[SUB_THREEWAY].inthreeway) { 05304 /* Call is already up, drop the last person */ 05305 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel); 05306 /* If the primary call isn't answered yet, use it */ 05307 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) { 05308 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/ 05309 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05310 p->owner = p->subs[SUB_REAL].owner; 05311 } 05312 /* Drop the last call and stop the conference */ 05313 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name); 05314 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05315 p->subs[SUB_REAL].inthreeway = 0; 05316 p->subs[SUB_THREEWAY].inthreeway = 0; 05317 } else { 05318 /* Lets see what we're up to */ 05319 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 05320 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) { 05321 int otherindex = SUB_THREEWAY; 05322 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 05323 int way3bridge = 0, cdr3way = 0; 05324 05325 if (!other) { 05326 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 05327 } else 05328 way3bridge = 1; 05329 05330 if (p->subs[SUB_THREEWAY].owner->cdr) 05331 cdr3way = 1; 05332 05333 ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name); 05334 /* Put them in the threeway, and flip */ 05335 p->subs[SUB_THREEWAY].inthreeway = 1; 05336 p->subs[SUB_REAL].inthreeway = 1; 05337 if (ast->_state == AST_STATE_UP) { 05338 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05339 otherindex = SUB_REAL; 05340 } 05341 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner)) 05342 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD); 05343 p->subs[otherindex].needunhold = 1; 05344 p->owner = p->subs[SUB_REAL].owner; 05345 if (ast->_state == AST_STATE_RINGING) { 05346 ast_debug(1, "Enabling ringtone on real and threeway\n"); 05347 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05348 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 05349 } 05350 } else { 05351 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name); 05352 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05353 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05354 p->owner = p->subs[SUB_REAL].owner; 05355 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner)) 05356 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 05357 p->subs[SUB_REAL].needunhold = 1; 05358 dahdi_enable_ec(p); 05359 } 05360 05361 } 05362 } 05363 winkflashdone: 05364 update_conf(p); 05365 break; 05366 case SIG_EM: 05367 case SIG_EM_E1: 05368 case SIG_FEATD: 05369 case SIG_SF: 05370 case SIG_SFWINK: 05371 case SIG_SF_FEATD: 05372 case SIG_FXSLS: 05373 case SIG_FXSGS: 05374 if (option_debug) { 05375 if (p->dialing) 05376 ast_debug(1, "Ignoring wink on channel %d\n", p->channel); 05377 else 05378 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel); 05379 } 05380 break; 05381 case SIG_FEATDMF_TA: 05382 switch (p->whichwink) { 05383 case 0: 05384 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 05385 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 05386 break; 05387 case 1: 05388 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr)); 05389 break; 05390 case 2: 05391 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n"); 05392 return NULL; 05393 } 05394 p->whichwink++; 05395 /* Fall through */ 05396 case SIG_FEATDMF: 05397 case SIG_E911: 05398 case SIG_FGC_CAMAMF: 05399 case SIG_FGC_CAMA: 05400 case SIG_FEATB: 05401 case SIG_SF_FEATDMF: 05402 case SIG_SF_FEATB: 05403 case SIG_EMWINK: 05404 /* FGD MF and EMWINK *Must* wait for wink */ 05405 if (!ast_strlen_zero(p->dop.dialstr)) { 05406 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05407 if (res < 0) { 05408 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05409 p->dop.dialstr[0] = '\0'; 05410 return NULL; 05411 } else 05412 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 05413 } 05414 p->dop.dialstr[0] = '\0'; 05415 break; 05416 default: 05417 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 05418 } 05419 break; 05420 case DAHDI_EVENT_HOOKCOMPLETE: 05421 if (p->inalarm) break; 05422 if ((p->radio || (p->oprmode < 0))) break; 05423 switch (mysig) { 05424 case SIG_FXSLS: /* only interesting for FXS */ 05425 case SIG_FXSGS: 05426 case SIG_FXSKS: 05427 case SIG_EM: 05428 case SIG_EM_E1: 05429 case SIG_EMWINK: 05430 case SIG_FEATD: 05431 case SIG_SF: 05432 case SIG_SFWINK: 05433 case SIG_SF_FEATD: 05434 if (!ast_strlen_zero(p->dop.dialstr)) { 05435 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05436 if (res < 0) { 05437 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05438 p->dop.dialstr[0] = '\0'; 05439 return NULL; 05440 } else 05441 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 05442 } 05443 p->dop.dialstr[0] = '\0'; 05444 p->dop.op = DAHDI_DIAL_OP_REPLACE; 05445 break; 05446 case SIG_FEATDMF: 05447 case SIG_FEATDMF_TA: 05448 case SIG_E911: 05449 case SIG_FGC_CAMA: 05450 case SIG_FGC_CAMAMF: 05451 case SIG_FEATB: 05452 case SIG_SF_FEATDMF: 05453 case SIG_SF_FEATB: 05454 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel); 05455 break; 05456 default: 05457 break; 05458 } 05459 break; 05460 case DAHDI_EVENT_POLARITY: 05461 /* 05462 * If we get a Polarity Switch event, this could be 05463 * due to line seizure, remote end connect or remote end disconnect. 05464 * 05465 * Check to see if we should change the polarity state and 05466 * mark the channel as UP or if this is an indication 05467 * of remote end disconnect. 05468 */ 05469 05470 if (p->polarityonanswerdelay > 0) { 05471 /* check if event is not too soon after OffHook or Answer */ 05472 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) { 05473 switch (ast->_state) { 05474 case AST_STATE_DIALING: /*!< Digits (or equivalent) have been dialed */ 05475 case AST_STATE_RINGING: /*!< Remote end is ringing */ 05476 if (p->answeronpolarityswitch) { 05477 ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel); 05478 ast_setstate(p->owner, AST_STATE_UP); 05479 p->polarity = POLARITY_REV; 05480 if (p->hanguponpolarityswitch) { 05481 p->polaritydelaytv = ast_tvnow(); 05482 } 05483 } else { 05484 ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel); 05485 } 05486 break; 05487 case AST_STATE_UP: /*!< Line is up */ 05488 case AST_STATE_RING: /*!< Line is ringing */ 05489 if (p->hanguponpolarityswitch) { 05490 ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel); 05491 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 05492 p->polarity = POLARITY_IDLE; 05493 } else { 05494 ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel); 05495 } 05496 break; 05497 05498 case AST_STATE_DOWN: /*!< Channel is down and available */ 05499 case AST_STATE_RESERVED: /*!< Channel is down, but reserved */ 05500 case AST_STATE_OFFHOOK: /*!< Channel is off hook */ 05501 case AST_STATE_BUSY: /*!< Line is busy */ 05502 case AST_STATE_DIALING_OFFHOOK: /*!< Digits (or equivalent) have been dialed while offhook */ 05503 case AST_STATE_PRERING: /*!< Channel has detected an incoming call and is waiting for ring */ 05504 default: 05505 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) { 05506 ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state); 05507 } 05508 05509 } 05510 05511 } else { 05512 /* event is too soon after OffHook or Answer */ 05513 switch (ast->_state) { 05514 case AST_STATE_DIALING: /*!< Digits (or equivalent) have been dialed */ 05515 case AST_STATE_RINGING: /*!< Remote end is ringing */ 05516 if (p->answeronpolarityswitch) { 05517 ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state); 05518 } 05519 break; 05520 05521 case AST_STATE_UP: /*!< Line is up */ 05522 case AST_STATE_RING: /*!< Line is ringing */ 05523 if (p->hanguponpolarityswitch) { 05524 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); 05525 } 05526 break; 05527 05528 default: 05529 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) { 05530 ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state); 05531 } 05532 } 05533 } 05534 } 05535 /* Added more log_debug information below to provide a better indication of what is going on */ 05536 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) ); 05537 break; 05538 default: 05539 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel); 05540 } 05541 return &p->subs[idx].f; 05542 }
| static int dahdi_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3373 of file chan_dahdi.c.
References ast_channel::_state, dahdi_pvt::alerting, dahdi_pvt::alreadyhungup, ast_bridged_channel(), ast_channel_setoption(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, ast_dsp_free(), ast_dsp_set_digitmode(), ast_free, ast_log(), ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), AST_OPTION_AUDIO_MODE, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, ast_queue_control(), ast_queue_control_data(), AST_STATE_RESERVED, AST_STATE_UP, ast_strlen_zero(), ast_verb, dahdi_pvt::bearer, dahdi_pvt::call, dahdi_pvt::callwaitcas, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingrepeat, dahdi_pvt::channel, dahdi_pvt::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::guardtime, ast_channel::hangupcause, dahdi_pvt::hidecallerid, iflist, iflock, dahdi_pvt::ignoredtmf, dahdi_subchannel::inthreeway, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_WARNING, dahdi_pvt::mohsuggest, dahdi_pvt::muting, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcallerid, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needringing, dahdi_pvt::next, dahdi_pvt::onhooktime, dahdi_pvt::oprmode, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_getvar_helper(), dahdi_pvt::permcallwaiting, dahdi_pvt::permhidecallerid, dahdi_pvt::polarity, POLARITY_IDLE, dahdi_pvt::prev, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, dahdi_pvt::progress, dahdi_pvt::pulsedial, dahdi_pvt::radio, dahdi_pvt::rdnis, dahdi_pvt::realcall, reset_conf(), restart_monitor(), dahdi_pvt::restartpending, restore_gains(), dahdi_pvt::ringt, dahdi_pvt::rlt, S_OR, dahdi_pvt::setup_ack, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SS7, dahdi_pvt::span, 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(), and update_conf().
Referenced by pri_dchannel().
03374 { 03375 int res; 03376 int idx,x, law; 03377 /*static int restore_gains(struct dahdi_pvt *p);*/ 03378 struct dahdi_pvt *p = ast->tech_pvt; 03379 struct dahdi_pvt *tmp = NULL; 03380 struct dahdi_pvt *prev = NULL; 03381 struct dahdi_params par; 03382 03383 ast_debug(1, "dahdi_hangup(%s)\n", ast->name); 03384 if (!ast->tech_pvt) { 03385 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 03386 return 0; 03387 } 03388 03389 ast_mutex_lock(&p->lock); 03390 03391 idx = dahdi_get_index(ast, p, 1); 03392 03393 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 03394 x = 1; 03395 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 03396 } 03397 03398 x = 0; 03399 dahdi_confmute(p, 0); 03400 p->muting = 0; 03401 restore_gains(p); 03402 if (p->origcid_num) { 03403 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num)); 03404 ast_free(p->origcid_num); 03405 p->origcid_num = NULL; 03406 } 03407 if (p->origcid_name) { 03408 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name)); 03409 ast_free(p->origcid_name); 03410 p->origcid_name = NULL; 03411 } 03412 if (p->dsp) 03413 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 03414 p->exten[0] = '\0'; 03415 03416 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n", 03417 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 03418 p->ignoredtmf = 0; 03419 03420 if (idx > -1) { 03421 /* Real channel, do some fixup */ 03422 p->subs[idx].owner = NULL; 03423 p->subs[idx].needanswer = 0; 03424 p->subs[idx].needflash = 0; 03425 p->subs[idx].needringing = 0; 03426 p->subs[idx].needbusy = 0; 03427 p->subs[idx].needcongestion = 0; 03428 p->subs[idx].linear = 0; 03429 p->subs[idx].needcallerid = 0; 03430 p->polarity = POLARITY_IDLE; 03431 dahdi_setlinear(p->subs[idx].dfd, 0); 03432 if (idx == SUB_REAL) { 03433 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) { 03434 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n"); 03435 if (p->subs[SUB_CALLWAIT].inthreeway) { 03436 /* We had flipped over to answer a callwait and now it's gone */ 03437 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n"); 03438 /* Move to the call-wait, but un-own us until they flip back. */ 03439 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03440 unalloc_sub(p, SUB_CALLWAIT); 03441 p->owner = NULL; 03442 } else { 03443 /* The three way hung up, but we still have a call wait */ 03444 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n"); 03445 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03446 unalloc_sub(p, SUB_THREEWAY); 03447 if (p->subs[SUB_REAL].inthreeway) { 03448 /* This was part of a three way call. Immediately make way for 03449 another call */ 03450 ast_debug(1, "Call was complete, setting owner to former third call\n"); 03451 p->owner = p->subs[SUB_REAL].owner; 03452 } else { 03453 /* This call hasn't been completed yet... Set owner to NULL */ 03454 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 03455 p->owner = NULL; 03456 } 03457 p->subs[SUB_REAL].inthreeway = 0; 03458 } 03459 } else if (p->subs[SUB_CALLWAIT].dfd > -1) { 03460 /* Move to the call-wait and switch back to them. */ 03461 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03462 unalloc_sub(p, SUB_CALLWAIT); 03463 p->owner = p->subs[SUB_REAL].owner; 03464 if (p->owner->_state != AST_STATE_UP) 03465 p->subs[SUB_REAL].needanswer = 1; 03466 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 03467 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 03468 } else if (p->subs[SUB_THREEWAY].dfd > -1) { 03469 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03470 unalloc_sub(p, SUB_THREEWAY); 03471 if (p->subs[SUB_REAL].inthreeway) { 03472 /* This was part of a three way call. Immediately make way for 03473 another call */ 03474 ast_debug(1, "Call was complete, setting owner to former third call\n"); 03475 p->owner = p->subs[SUB_REAL].owner; 03476 } else { 03477 /* This call hasn't been completed yet... Set owner to NULL */ 03478 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 03479 p->owner = NULL; 03480 } 03481 p->subs[SUB_REAL].inthreeway = 0; 03482 } 03483 } else if (idx == SUB_CALLWAIT) { 03484 /* Ditch the holding callwait call, and immediately make it availabe */ 03485 if (p->subs[SUB_CALLWAIT].inthreeway) { 03486 /* This is actually part of a three way, placed on hold. Place the third part 03487 on music on hold now */ 03488 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 03489 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 03490 S_OR(p->mohsuggest, NULL), 03491 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 03492 } 03493 p->subs[SUB_THREEWAY].inthreeway = 0; 03494 /* Make it the call wait now */ 03495 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 03496 unalloc_sub(p, SUB_THREEWAY); 03497 } else 03498 unalloc_sub(p, SUB_CALLWAIT); 03499 } else if (idx == SUB_THREEWAY) { 03500 if (p->subs[SUB_CALLWAIT].inthreeway) { 03501 /* The other party of the three way call is currently in a call-wait state. 03502 Start music on hold for them, and take the main guy out of the third call */ 03503 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 03504 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 03505 S_OR(p->mohsuggest, NULL), 03506 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 03507 } 03508 p->subs[SUB_CALLWAIT].inthreeway = 0; 03509 } 03510 p->subs[SUB_REAL].inthreeway = 0; 03511 /* If this was part of a three way call index, let us make 03512 another three way call */ 03513 unalloc_sub(p, SUB_THREEWAY); 03514 } else { 03515 /* This wasn't any sort of call, but how are we an index? */ 03516 ast_log(LOG_WARNING, "Index found but not any type of call?\n"); 03517 } 03518 } 03519 03520 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 03521 p->owner = NULL; 03522 p->ringt = 0; 03523 p->distinctivering = 0; 03524 p->confirmanswer = 0; 03525 p->cidrings = 1; 03526 p->outgoing = 0; 03527 p->digital = 0; 03528 p->faxhandled = 0; 03529 p->pulsedial = 0; 03530 p->onhooktime = time(NULL); 03531 #if defined(HAVE_PRI) || defined(HAVE_SS7) 03532 p->proceeding = 0; 03533 p->dialing = 0; 03534 p->progress = 0; 03535 p->alerting = 0; 03536 p->setup_ack = 0; 03537 p->rlt = 0; 03538 #endif 03539 if (p->dsp) { 03540 ast_dsp_free(p->dsp); 03541 p->dsp = NULL; 03542 } 03543 03544 law = DAHDI_LAW_DEFAULT; 03545 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 03546 if (res < 0) 03547 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 03548 /* Perform low level hangup if no owner left */ 03549 #ifdef HAVE_SS7 03550 if (p->ss7) { 03551 if (p->ss7call) { 03552 if (!ss7_grab(p, p->ss7)) { 03553 if (!p->alreadyhungup) { 03554 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE"); 03555 int icause = ast->hangupcause ? ast->hangupcause : -1; 03556 03557 if (cause) { 03558 if (atoi(cause)) 03559 icause = atoi(cause); 03560 } 03561 isup_rel(p->ss7->ss7, p->ss7call, icause); 03562 ss7_rel(p->ss7); 03563 p->alreadyhungup = 1; 03564 } else 03565 ast_log(LOG_WARNING, "Trying to hangup twice!\n"); 03566 } else { 03567 ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic); 03568 res = -1; 03569 } 03570 } 03571 } 03572 #endif 03573 #ifdef HAVE_PRI 03574 if (p->pri) { 03575 #ifdef SUPPORT_USERUSER 03576 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO"); 03577 #endif 03578 03579 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */ 03580 if (p->call && (!p->bearer || (p->bearer->call == p->call))) { 03581 if (!pri_grab(p, p->pri)) { 03582 if (p->alreadyhungup) { 03583 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n"); 03584 03585 #ifdef SUPPORT_USERUSER 03586 pri_call_set_useruser(p->call, useruser); 03587 #endif 03588 03589 pri_hangup(p->pri->pri, p->call, -1); 03590 p->call = NULL; 03591 if (p->bearer) 03592 p->bearer->call = NULL; 03593 } else { 03594 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE"); 03595 int icause = ast->hangupcause ? ast->hangupcause : -1; 03596 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n"); 03597 03598 #ifdef SUPPORT_USERUSER 03599 pri_call_set_useruser(p->call, useruser); 03600 #endif 03601 03602 p->alreadyhungup = 1; 03603 if (p->bearer) 03604 p->bearer->alreadyhungup = 1; 03605 if (cause) { 03606 if (atoi(cause)) 03607 icause = atoi(cause); 03608 } 03609 pri_hangup(p->pri->pri, p->call, icause); 03610 } 03611 if (res < 0) 03612 ast_log(LOG_WARNING, "pri_disconnect failed\n"); 03613 pri_rel(p->pri); 03614 } else { 03615 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 03616 res = -1; 03617 } 03618 } else { 03619 if (p->bearer) 03620 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call); 03621 p->call = NULL; 03622 res = 0; 03623 } 03624 } 03625 #endif 03626 if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7) && (p->sig != SIG_BRI) && (p->sig != SIG_BRI_PTMP))) 03627 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 03628 if (res < 0) { 03629 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name); 03630 } 03631 switch (p->sig) { 03632 case SIG_FXOGS: 03633 case SIG_FXOLS: 03634 case SIG_FXOKS: 03635 memset(&par, 0, sizeof(par)); 03636 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 03637 if (!res) { 03638 #if 0 03639 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook); 03640 #endif 03641 /* If they're off hook, try playing congestion */ 03642 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0)))) 03643 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 03644 else 03645 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03646 } 03647 break; 03648 case SIG_FXSGS: 03649 case SIG_FXSLS: 03650 case SIG_FXSKS: 03651 /* Make sure we're not made available for at least two seconds assuming 03652 we were actually used for an inbound or outbound call. */ 03653 if (ast->_state != AST_STATE_RESERVED) { 03654 time(&p->guardtime); 03655 p->guardtime += 2; 03656 } 03657 break; 03658 default: 03659 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03660 } 03661 if (p->cidspill) 03662 ast_free(p->cidspill); 03663 if (p->sig) 03664 dahdi_disable_ec(p); 03665 x = 0; 03666 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); 03667 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0); 03668 p->didtdd = 0; 03669 p->cidspill = NULL; 03670 p->callwaitcas = 0; 03671 p->callwaiting = p->permcallwaiting; 03672 p->hidecallerid = p->permhidecallerid; 03673 p->dialing = 0; 03674 p->rdnis[0] = '\0'; 03675 update_conf(p); 03676 reset_conf(p); 03677 /* Restore data mode */ 03678 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 03679 x = 0; 03680 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 03681 } 03682 #ifdef HAVE_PRI 03683 if (p->bearer) { 03684 ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel); 03685 /* Free up the bearer channel as well, and 03686 don't use its file descriptor anymore */ 03687 update_conf(p->bearer); 03688 reset_conf(p->bearer); 03689 p->bearer->owner = NULL; 03690 p->bearer->realcall = NULL; 03691 p->bearer = NULL; 03692 p->subs[SUB_REAL].dfd = -1; 03693 p->pri = NULL; 03694 } 03695 #endif 03696 if (num_restart_pending == 0) 03697 restart_monitor(); 03698 } 03699 03700 p->callwaitingrepeat = 0; 03701 p->cidcwexpire = 0; 03702 p->oprmode = 0; 03703 ast->tech_pvt = NULL; 03704 ast_mutex_unlock(&p->lock); 03705 ast_module_unref(ast_module_info->self); 03706 ast_verb(3, "Hungup '%s'\n", ast->name); 03707 03708 ast_mutex_lock(&iflock); 03709 03710 if (p->restartpending) { 03711 num_restart_pending--; 03712 } 03713 03714 tmp = iflist; 03715 prev = NULL; 03716 if (p->destroy) { 03717 while (tmp) { 03718 if (tmp == p) { 03719 destroy_channel(prev, tmp, 0); 03720 break; 03721 } else { 03722 prev = tmp; 03723 tmp = tmp->next; 03724 } 03725 } 03726 } 03727 ast_mutex_unlock(&iflock); 03728 return 0; 03729 }
| static int dahdi_indicate | ( | struct ast_channel * | chan, | |
| int | condition, | |||
| const void * | data, | |||
| size_t | datalen | |||
| ) | [static] |
Definition at line 6064 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, dahdi_pvt::alerting, AST_CAUSE_CONGESTION, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_USER_BUSY, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_debug, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_SOFTHANGUP_DEV, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, dahdi_pvt::call, 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, 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().
06065 { 06066 struct dahdi_pvt *p = chan->tech_pvt; 06067 int res=-1; 06068 int idx; 06069 int func = DAHDI_FLASH; 06070 ast_mutex_lock(&p->lock); 06071 idx = dahdi_get_index(chan, p, 0); 06072 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name); 06073 if (idx == SUB_REAL) { 06074 switch (condition) { 06075 case AST_CONTROL_BUSY: 06076 #ifdef HAVE_PRI 06077 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) { 06078 chan->hangupcause = AST_CAUSE_USER_BUSY; 06079 chan->_softhangup |= AST_SOFTHANGUP_DEV; 06080 res = 0; 06081 } else if (!p->progress && 06082 ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06083 && p->pri && !p->outgoing) { 06084 if (p->pri->pri) { 06085 if (!pri_grab(p, p->pri)) { 06086 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06087 pri_rel(p->pri); 06088 } 06089 else 06090 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06091 } 06092 p->progress = 1; 06093 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY); 06094 } else 06095 #endif 06096 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY); 06097 break; 06098 case AST_CONTROL_RINGING: 06099 #ifdef HAVE_PRI 06100 if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06101 && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) { 06102 if (p->pri->pri) { 06103 if (!pri_grab(p, p->pri)) { 06104 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06105 pri_rel(p->pri); 06106 } 06107 else 06108 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06109 } 06110 p->alerting = 1; 06111 } 06112 06113 #endif 06114 #ifdef HAVE_SS7 06115 if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) { 06116 if (p->ss7->ss7) { 06117 ss7_grab(p, p->ss7); 06118 06119 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) 06120 p->rlt = 1; 06121 if (p->rlt != 1) /* No need to send CPG if call will be RELEASE */ 06122 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING); 06123 p->alerting = 1; 06124 ss7_rel(p->ss7); 06125 } 06126 } 06127 #endif 06128 06129 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE); 06130 06131 if (chan->_state != AST_STATE_UP) { 06132 if ((chan->_state != AST_STATE_RING) || 06133 ((p->sig != SIG_FXSKS) && 06134 (p->sig != SIG_FXSLS) && 06135 (p->sig != SIG_FXSGS))) 06136 ast_setstate(chan, AST_STATE_RINGING); 06137 } 06138 break; 06139 case AST_CONTROL_PROCEEDING: 06140 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name); 06141 #ifdef HAVE_PRI 06142 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06143 && p->pri && !p->outgoing) { 06144 if (p->pri->pri) { 06145 if (!pri_grab(p, p->pri)) { 06146 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06147 pri_rel(p->pri); 06148 } 06149 else 06150 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06151 } 06152 p->proceeding = 1; 06153 p->dialing = 0; 06154 } 06155 #endif 06156 #ifdef HAVE_SS7 06157 /* This IF sends the FAR for an answered ALEG call */ 06158 if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){ 06159 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) 06160 p->rlt = 1; 06161 } 06162 06163 if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) { 06164 if (p->ss7->ss7) { 06165 ss7_grab(p, p->ss7); 06166 isup_acm(p->ss7->ss7, p->ss7call); 06167 p->proceeding = 1; 06168 ss7_rel(p->ss7); 06169 06170 } 06171 } 06172 #endif 06173 /* don't continue in ast_indicate */ 06174 res = 0; 06175 break; 06176 case AST_CONTROL_PROGRESS: 06177 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name); 06178 #ifdef HAVE_PRI 06179 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */ 06180 if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06181 && p->pri && !p->outgoing) { 06182 if (p->pri->pri) { 06183 if (!pri_grab(p, p->pri)) { 06184 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06185 pri_rel(p->pri); 06186 } 06187 else 06188 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06189 } 06190 p->progress = 1; 06191 } 06192 #endif 06193 #ifdef HAVE_SS7 06194 if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) { 06195 if (p->ss7->ss7) { 06196 ss7_grab(p, p->ss7); 06197 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO); 06198 p->progress = 1; 06199 ss7_rel(p->ss7); 06200 /* enable echo canceler here on SS7 calls */ 06201 dahdi_enable_ec(p); 06202 06203 } 06204 } 06205 #endif 06206 /* don't continue in ast_indicate */ 06207 res = 0; 06208 break; 06209 case AST_CONTROL_CONGESTION: 06210 chan->hangupcause = AST_CAUSE_CONGESTION; 06211 #ifdef HAVE_PRI 06212 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) { 06213 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 06214 chan->_softhangup |= AST_SOFTHANGUP_DEV; 06215 res = 0; 06216 } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06217 && p->pri && !p->outgoing) { 06218 if (p->pri) { 06219 if (!pri_grab(p, p->pri)) { 06220 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06221 pri_rel(p->pri); 06222 } else 06223 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06224 } 06225 p->progress = 1; 06226 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06227 } else 06228 #endif 06229 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06230 break; 06231 case AST_CONTROL_HOLD: 06232 #ifdef HAVE_PRI 06233 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 06234 if (!pri_grab(p, p->pri)) { 06235 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD); 06236 pri_rel(p->pri); 06237 } else 06238 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06239 } else 06240 #endif 06241 ast_moh_start(chan, data, p->mohinterpret); 06242 break; 06243 case AST_CONTROL_UNHOLD: 06244 #ifdef HAVE_PRI 06245 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 06246 if (!pri_grab(p, p->pri)) { 06247 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL); 06248 pri_rel(p->pri); 06249 } else 06250 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06251 } else 06252 #endif 06253 ast_moh_stop(chan); 06254 break; 06255 case AST_CONTROL_RADIO_KEY: 06256 if (p->radio) 06257 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 06258 res = 0; 06259 break; 06260 case AST_CONTROL_RADIO_UNKEY: 06261 if (p->radio) 06262 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF); 06263 res = 0; 06264 break; 06265 case AST_CONTROL_FLASH: 06266 /* flash hookswitch */ 06267 if (ISTRUNK(p) && (p->sig != SIG_PRI)) { 06268 /* Clear out the dial buffer */ 06269 p->dop.dialstr[0] = '\0'; 06270 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 06271 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 06272 chan->name, strerror(errno)); 06273 } else 06274 res = 0; 06275 } else 06276 res = 0; 06277 break; 06278 case AST_CONTROL_SRCUPDATE: 06279 res = 0; 06280 break; 06281 case -1: 06282 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 06283 break; 06284 } 06285 } else 06286 res = 0; 06287 ast_mutex_unlock(&p->lock); 06288 return res; 06289 }
Definition at line 4087 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::channel, LOG_WARNING, dahdi_pvt::master, MAX_SLAVES, and dahdi_pvt::slaves.
Referenced by dahdi_bridge().
04087 { 04088 int x; 04089 if (!slave || !master) { 04090 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n"); 04091 return; 04092 } 04093 for (x = 0; x < MAX_SLAVES; x++) { 04094 if (!master->slaves[x]) { 04095 master->slaves[x] = slave; 04096 break; 04097 } 04098 } 04099 if (x >= MAX_SLAVES) { 04100 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel); 04101 master->slaves[MAX_SLAVES - 1] = slave; 04102 } 04103 if (slave->master) 04104 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel); 04105 slave->master = master; 04106 04107 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x); 04108 }
| static void dahdi_loopback | ( | struct dahdi_pvt * | p, | |
| int | enable | |||
| ) | [static] |
Definition at line 9797 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().
09798 { 09799 if (p->loopedback != enable) { 09800 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) { 09801 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno)); 09802 return; 09803 } 09804 p->loopedback = enable; 09805 } 09806 }
| 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 6291 of file chan_dahdi.c.
References accountcode, dahdi_pvt::accountcode, dahdi_pvt::adsi, ast_channel::adsicpe, dahdi_pvt::alreadyhungup, ast_channel::amaflags, dahdi_pvt::amaflags, AST_ADSI_UNAVAILABLE, ast_channel_alloc, ast_channel_set_fd(), ast_copy_string(), ast_debug, ast_devstate_changed_literal(), ast_dsp_new(), ast_dsp_set_busy_count(), ast_dsp_set_busy_pattern(), ast_dsp_set_call_progress_zone(), ast_dsp_set_digitmode(), ast_dsp_set_features(), AST_FORMAT_ALAW, AST_FORMAT_ULAW, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_random(), ast_state_chan2dev(), AST_STATE_RING, ast_str_alloca, ast_str_set(), ast_strdup, ast_string_field_set, ast_strlen_zero(), AST_TRANS_CAP_DIGITAL, ast_transfercapability2str(), dahdi_pvt::bearer, dahdi_pvt::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, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DIGIT_DETECT, DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, DSP_PROGRESS_TALK, dahdi_pvt::dtmfrelax, errno, ast_channel::exten, dahdi_pvt::exten, dahdi_pvt::fake_event, global_jbconf, dahdi_pvt::hardwaredtmf, dahdi_pvt::isidlecall, language, dahdi_pvt::language, dahdi_subchannel::linear, LOG_WARNING, dahdi_pvt::muting, ast_variable::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, ast_str::str, SUB_REAL, dahdi_pvt::subs, ast_channel::tech, ast_channel::tech_pvt, ast_channel::transfercapability, dahdi_pri::trunkgroup, ast_variable::value, dahdi_pvt::vars, and ast_channel::writeformat.
Referenced by dahdi_handle_event(), dahdi_request(), handle_init_event(), mwi_thread(), pri_dchannel(), and ss7_start_call().
06292 { 06293 struct ast_channel *tmp; 06294 int deflaw; 06295 int res; 06296 int x,y; 06297 int features; 06298 struct ast_str *chan_name; 06299 struct ast_variable *v; 06300 struct dahdi_params ps; 06301 if (i->subs[idx].owner) { 06302 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]); 06303 return NULL; 06304 } 06305 y = 1; 06306 chan_name = ast_str_alloca(32); 06307 do { 06308 #ifdef HAVE_PRI 06309 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS))) 06310 ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y); 06311 else 06312 #endif 06313 if (i->channel == CHAN_PSEUDO) 06314 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random()); 06315 else 06316 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y); 06317 for (x = 0; x < 3; x++) { 06318 if ((idx != x) && i->subs[x].owner && !strcasecmp(chan_name->str, i->subs[x].owner->name + 6)) 06319 break; 06320 } 06321 y++; 06322 } while (x < 3); 06323 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "DAHDI/%s", chan_name->str); 06324 if (!tmp) 06325 return NULL; 06326 tmp->tech = &dahdi_tech; 06327 memset(&ps, 0, sizeof(ps)); 06328 ps.channo = i->channel; 06329 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps); 06330 if (res) { 06331 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno)); 06332 ps.curlaw = DAHDI_LAW_MULAW; 06333 } 06334 if (ps.curlaw == DAHDI_LAW_ALAW) 06335 deflaw = AST_FORMAT_ALAW; 06336 else 06337 deflaw = AST_FORMAT_ULAW; 06338 if (law) { 06339 if (law == DAHDI_LAW_ALAW) 06340 deflaw = AST_FORMAT_ALAW; 06341 else 06342 deflaw = AST_FORMAT_ULAW; 06343 } 06344 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd); 06345 tmp->nativeformats = deflaw; 06346 /* Start out assuming ulaw since it's smaller :) */ 06347 tmp->rawreadformat = deflaw; 06348 tmp->readformat = deflaw; 06349 tmp->rawwriteformat = deflaw; 06350 tmp->writeformat = deflaw; 06351 i->subs[idx].linear = 0; 06352 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear); 06353 features = 0; 06354 if (idx == SUB_REAL) { 06355 if (i->busydetect && CANBUSYDETECT(i)) 06356 features |= DSP_FEATURE_BUSY_DETECT; 06357 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i)) 06358 features |= DSP_FEATURE_CALL_PROGRESS; 06359 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) || 06360 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) { 06361 features |= DSP_FEATURE_FAX_DETECT; 06362 } 06363 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 06364 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) { 06365 i->hardwaredtmf = 0; 06366 features |= DSP_FEATURE_DIGIT_DETECT; 06367 } else if (NEED_MFDETECT(i)) { 06368 i->hardwaredtmf = 1; 06369 features |= DSP_FEATURE_DIGIT_DETECT; 06370 } 06371 } 06372 if (features) { 06373 if (i->dsp) { 06374 ast_debug(1, "Already have a dsp on %s?\n", tmp->name); 06375 } else { 06376 if (i->channel != CHAN_PSEUDO) 06377 i->dsp = ast_dsp_new(); 06378 else 06379 i->dsp = NULL; 06380 if (i->dsp) { 06381 i->dsp_features = features; 06382 #if defined(HAVE_PRI) || defined(HAVE_SS7) 06383 /* We cannot do progress detection until receives PROGRESS message */ 06384 if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) { 06385 /* Remember requested DSP features, don't treat 06386 talking as ANSWER */ 06387 i->dsp_features = features & ~DSP_PROGRESS_TALK; 06388 features = 0; 06389 } 06390 #endif 06391 ast_dsp_set_features(i->dsp, features); 06392 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax); 06393 if (!ast_strlen_zero(progzone)) 06394 ast_dsp_set_call_progress_zone(i->dsp, progzone); 06395 if (i->busydetect && CANBUSYDETECT(i)) { 06396 ast_dsp_set_busy_count(i->dsp, i->busycount); 06397 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength); 06398 } 06399 } 06400 } 06401 } 06402 06403 if (state == AST_STATE_RING) 06404 tmp->rings = 1; 06405 tmp->tech_pvt = i; 06406 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) { 06407 /* Only FXO signalled stuff can be picked up */ 06408 tmp->callgroup = i->callgroup; 06409 tmp->pickupgroup = i->pickupgroup; 06410 } 06411 if (!ast_strlen_zero(i->parkinglot)) 06412 ast_string_field_set(tmp, parkinglot, i->parkinglot); 06413 if (!ast_strlen_zero(i->language)) 06414 ast_string_field_set(tmp, language, i->language); 06415 if (!i->owner) 06416 i->owner = tmp; 06417 if (!ast_strlen_zero(i->accountcode)) 06418 ast_string_field_set(tmp, accountcode, i->accountcode); 06419 if (i->amaflags) 06420 tmp->amaflags = i->amaflags; 06421 i->subs[idx].owner = tmp; 06422 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 06423 ast_string_field_set(tmp, call_forward, i->call_forward); 06424 /* If we've been told "no ADSI" then enforce it */ 06425 if (!i->adsi) 06426 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 06427 if (!ast_strlen_zero(i->exten)) 06428 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 06429 if (!ast_strlen_zero(i->rdnis)) 06430 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 06431 if (!ast_strlen_zero(i->dnid)) 06432 tmp->cid.cid_dnid = ast_strdup(i->dnid); 06433 06434 /* Don't use ast_set_callerid() here because it will 06435 * generate a needless NewCallerID event */ 06436 #ifdef PRI_ANI 06437 if (!ast_strlen_zero(i->cid_ani)) 06438 tmp->cid.cid_ani = ast_strdup(i->cid_ani); 06439 else 06440 tmp->cid.cid_ani = ast_strdup(i->cid_num); 06441 #else 06442 tmp->cid.cid_ani = ast_strdup(i->cid_num); 06443 #endif 06444 tmp->cid.cid_pres = i->callingpres; 06445 tmp->cid.cid_ton = i->cid_ton; 06446 tmp->cid.cid_ani2 = i->cid_ani2; 06447 #if defined(HAVE_PRI) || defined(HAVE_SS7) 06448 tmp->transfercapability = transfercapability; 06449 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability)); 06450 if (transfercapability & AST_TRANS_CAP_DIGITAL) 06451 i->digital = 1; 06452 /* Assume calls are not idle calls unless we're told differently */ 06453 i->isidlecall = 0; 06454 i->alreadyhungup = 0; 06455 #endif 06456 /* clear the fake event in case we posted one before we had ast_channel */ 06457 i->fake_event = 0; 06458 /* Assure there is no confmute on this channel */ 06459 dahdi_confmute(i, 0); 06460 i->muting = 0; 06461 /* Configure the new channel jb */ 06462 ast_jb_configure(tmp, &global_jbconf); 06463 06464 ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name); 06465 06466 for (v = i->vars ; v ; v = v->next) 06467 pbx_builtin_setvar_helper(tmp, v->name, v->value); 06468 06469 if (startpbx) { 06470 if (ast_pbx_start(tmp)) { 06471 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 06472 ast_hangup(tmp); 06473 i->owner = NULL; 06474 return NULL; 06475 } 06476 } 06477 06478 ast_module_ref(ast_module_info->self); 06479 return tmp; 06480 }
| static int dahdi_open | ( | char * | fn | ) | [static] |
Definition at line 1436 of file chan_dahdi.c.
References ast_log(), chan, errno, LOG_WARNING, and READ_SIZE.
Referenced by alloc_sub(), chandup(), and mkintf().
01437 { 01438 int fd; 01439 int isnum; 01440 int chan = 0; 01441 int bs; 01442 int x; 01443 isnum = 1; 01444 for (x = 0; x < strlen(fn); x++) { 01445 if (!isdigit(fn[x])) { 01446 isnum = 0; 01447 break; 01448 } 01449 } 01450 if (isnum) { 01451 chan = atoi(fn); 01452 if (chan < 1) { 01453 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn); 01454 return -1; 01455 } 01456 fn = "/dev/dahdi/channel"; 01457 } 01458 fd = open(fn, O_RDWR | O_NONBLOCK); 01459 if (fd < 0) { 01460 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno)); 01461 return -1; 01462 } 01463 if (chan) { 01464 if (ioctl(fd, DAHDI_SPECIFY, &chan)) { 01465 x = errno; 01466 close(fd); 01467 errno = x; 01468 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno)); 01469 return -1; 01470 } 01471 } 01472 bs = READ_SIZE; 01473 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) { 01474 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno)); 01475 x = errno; 01476 close(fd); 01477 errno = x; 01478 return -1; 01479 } 01480 return fd; 01481 }
| static void dahdi_pri_error | ( | struct pri * | pri, | |
| char * | s | |||
| ) | [static] |
Definition at line 10736 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), errno, LOG_ERROR, LOG_WARNING, NUM_DCHANS, NUM_SPANS, pridebugfdlock, and pris.
Referenced by dahdi_restart(), and load_module().
10737 { 10738 int x, y; 10739 int dchan = -1, span = -1; 10740 int dchancount = 0; 10741 10742 if (pri) { 10743 for (x = 0; x < NUM_SPANS; x++) { 10744 for (y = 0; y < NUM_DCHANS; y++) { 10745 if (pris[x].dchans[y]) 10746 dchancount++; 10747 10748 if (pris[x].dchans[y] == pri) 10749 dchan = y; 10750 } 10751 if (dchan >= 0) { 10752 span = x; 10753 break; 10754 } 10755 dchancount = 0; 10756 } 10757 if ((dchancount > 1) && (span > -1)) 10758 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s); 10759 else 10760 ast_log(LOG_ERROR, "%s", s); 10761 } else 10762 ast_log(LOG_ERROR, "%s", s); 10763 10764 ast_mutex_lock(&pridebugfdlock); 10765 10766 if (pridebugfd >= 0) { 10767 if (write(pridebugfd, s, strlen(s)) < 0) { 10768 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 10769 } 10770 } 10771 10772 ast_mutex_unlock(&pridebugfdlock); 10773 }
| static void dahdi_pri_message | ( | struct pri * | pri, | |
| char * | s | |||
| ) | [static] |
Definition at line 10697 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose, errno, LOG_WARNING, NUM_DCHANS, NUM_SPANS, pridebugfdlock, and pris.
Referenced by dahdi_restart(), and load_module().
10698 { 10699 int x, y; 10700 int dchan = -1, span = -1; 10701 int dchancount = 0; 10702 10703 if (pri) { 10704 for (x = 0; x < NUM_SPANS; x++) { 10705 for (y = 0; y < NUM_DCHANS; y++) { 10706 if (pris[x].dchans[y]) 10707 dchancount++; 10708 10709 if (pris[x].dchans[y] == pri) 10710 dchan = y; 10711 } 10712 if (dchan >= 0) { 10713 span = x; 10714 break; 10715 } 10716 dchancount = 0; 10717 } 10718 if (dchancount > 1 && (span > -1)) 10719 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s); 10720 else 10721 ast_verbose("%s", s); 10722 } else 10723 ast_verbose("%s", s); 10724 10725 ast_mutex_lock(&pridebugfdlock); 10726 10727 if (pridebugfd >= 0) { 10728 if (write(pridebugfd, s, strlen(s)) < 0) { 10729 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 10730 } 10731 } 10732 10733 ast_mutex_unlock(&pridebugfdlock); 10734 }
Definition at line 1342 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_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_PRI, SIG_SS7, and dahdi_ss7::ss7.
Referenced by action_dahdidialoffhook(), pri_dchannel(), and ss7_linkset().
01343 { 01344 #ifdef HAVE_PRI 01345 struct dahdi_pri *pri = (struct dahdi_pri*) data; 01346 #endif 01347 #ifdef HAVE_SS7 01348 struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data; 01349 #endif 01350 /* We must unlock the PRI to avoid the possibility of a deadlock */ 01351 #if defined(HAVE_PRI) || defined(HAVE_SS7) 01352 if (data) { 01353 switch (p->sig) { 01354 #ifdef HAVE_PRI 01355 case SIG_BRI: 01356 case SIG_BRI_PTMP: 01357 case SIG_PRI: 01358 ast_mutex_unlock(&pri->lock); 01359 break; 01360 #endif 01361 #ifdef HAVE_SS7 01362 case SIG_SS7: 01363 ast_mutex_unlock(&ss7->lock); 01364 break; 01365 #endif 01366 default: 01367 break; 01368 } 01369 } 01370 #endif 01371 for (;;) { 01372 if (p->owner) { 01373 if (ast_channel_trylock(p->owner)) { 01374 DEADLOCK_AVOIDANCE(&p->lock); 01375 } else { 01376 ast_queue_frame(p->owner, f); 01377 ast_channel_unlock(p->owner); 01378 break; 01379 } 01380 } else 01381 break; 01382 } 01383 #if defined(HAVE_PRI) || defined(HAVE_SS7) 01384 if (data) { 01385 switch (p->sig) { 01386 #ifdef HAVE_PRI 01387 case SIG_BRI: 01388 case SIG_BRI_PTMP: 01389 case SIG_PRI: 01390 ast_mutex_lock(&pri->lock); 01391 break; 01392 #endif 01393 #ifdef HAVE_SS7 01394 case SIG_SS7: 01395 ast_mutex_lock(&ss7->lock); 01396 break; 01397 #endif 01398 default: 01399 break; 01400 } 01401 } 01402 01403 #endif 01404 }
| static struct ast_frame * dahdi_read | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 5660 of file chan_dahdi.c.
References __dahdi_exception(), ast_channel::_state, ast_clear_flag, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_debug, ast_dsp_process(), ast_dsp_was_muted(), AST_FLAG_BLOCKING, AST_FLAG_EXCEPTION, AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_getformatname(), ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_set_callerid(), ast_set_flag, ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_tv(), ast_verb, dahdi_subchannel::buffer, dahdi_pvt::busydetect, dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitingrepeat, dahdi_pvt::callwaitrings, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, CHECK_BLOCKING, dahdi_pvt::cidcwexpire, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_callwait(), dahdi_confmute(), dahdi_get_index(), dahdi_handle_dtmfup(), DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_setlinear(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dsp, errno, dahdi_subchannel::f, f, dahdi_pvt::fake_event, dahdi_pvt::firstradio, ast_frame::frametype, dahdi_pvt::ignoredtmf, dahdi_pvt::inalarm, dahdi_subchannel::inthreeway, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_WARNING, ast_frame::mallocd, dahdi_pvt::muting, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcallerid, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pri::overlapdial, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::proceeding, ast_frame::ptr, dahdi_pvt::pulsedial, dahdi_pvt::radio, ast_channel::rawreadformat, READ_SIZE, restore_conference(), ast_channel::rings, dahdi_pvt::ringt, S_OR, ast_frame::samples, send_callerid(), dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_PRI, ast_frame::src, SUB_CALLWAIT, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_feed(), and ast_channel::tech_pvt.
05661 { 05662 struct dahdi_pvt *p = ast->tech_pvt; 05663 int res; 05664 int idx; 05665 void *readbuf; 05666 struct ast_frame *f; 05667 05668 while (ast_mutex_trylock(&p->lock)) { 05669 CHANNEL_DEADLOCK_AVOIDANCE(ast); 05670 } 05671 05672 idx = dahdi_get_index(ast, p, 0); 05673 05674 /* Hang up if we don't really exist */ 05675 if (idx < 0) { 05676 ast_log(LOG_WARNING, "We dont exist?\n"); 05677 ast_mutex_unlock(&p->lock); 05678 return NULL; 05679 } 05680 05681 if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL; 05682 05683 p->subs[idx].f.frametype = AST_FRAME_NULL; 05684 p->subs[idx].f.datalen = 0; 05685 p->subs[idx].f.samples = 0; 05686 p->subs[idx].f.mallocd = 0; 05687 p->subs[idx].f.offset = 0; 05688 p->subs[idx].f.subclass = 0; 05689 p->subs[idx].f.delivery = ast_tv(0,0); 05690 p->subs[idx].f.src = "dahdi_read"; 05691 p->subs[idx].f.data.ptr = NULL; 05692 05693 /* make sure it sends initial key state as first frame */ 05694 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio)) 05695 { 05696 struct dahdi_params ps; 05697 05698 memset(&ps, 0, sizeof(ps)); 05699 ps.channo = p->channel; 05700 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 05701 ast_mutex_unlock(&p->lock); 05702 return NULL; 05703 } 05704 p->firstradio = 1; 05705 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05706 if (ps.rxisoffhook) 05707 { 05708 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY; 05709 } 05710 else 05711 { 05712 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY; 05713 } 05714 ast_mutex_unlock(&p->lock); 05715 return &p->subs[idx].f; 05716 } 05717 if (p->ringt == 1) { 05718 ast_mutex_unlock(&p->lock); 05719 return NULL; 05720 } 05721 else if (p->ringt > 0) 05722 p->ringt--; 05723 05724 if (p->subs[idx].needringing) { 05725 /* Send ringing frame if requested */ 05726 p->subs[idx].needringing = 0; 05727 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05728 p->subs[idx].f.subclass = AST_CONTROL_RINGING; 05729 ast_setstate(ast, AST_STATE_RINGING); 05730 ast_mutex_unlock(&p->lock); 05731 return &p->subs[idx].f; 05732 } 05733 05734 if (p->subs[idx].needbusy) { 05735 /* Send busy frame if requested */ 05736 p->subs[idx].needbusy = 0; 05737 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05738 p->subs[idx].f.subclass = AST_CONTROL_BUSY; 05739 ast_mutex_unlock(&p->lock); 05740 return &p->subs[idx].f; 05741 } 05742 05743 if (p->subs[idx].needcongestion) { 05744 /* Send congestion frame if requested */ 05745 p->subs[idx].needcongestion = 0; 05746 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05747 p->subs[idx].f.subclass = AST_CONTROL_CONGESTION; 05748 ast_mutex_unlock(&p->lock); 05749 return &p->subs[idx].f; 05750 } 05751 05752 if (p->subs[idx].needcallerid) { 05753 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL), 05754 S_OR(p->lastcid_name, NULL), 05755 S_OR(p->lastcid_num, NULL) 05756 ); 05757 p->subs[idx].needcallerid = 0; 05758 } 05759 05760 if (p->subs[idx].needanswer) { 05761 /* Send answer frame if requested */ 05762 p->subs[idx].needanswer = 0; 05763 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05764 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 05765 ast_mutex_unlock(&p->lock); 05766 return &p->subs[idx].f; 05767 } 05768 05769 if (p->subs[idx].needflash) { 05770 /* Send answer frame if requested */ 05771 p->subs[idx].needflash = 0; 05772 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05773 p->subs[idx].f.subclass = AST_CONTROL_FLASH; 05774 ast_mutex_unlock(&p->lock); 05775 return &p->subs[idx].f; 05776 } 05777 05778 if (p->subs[idx].needhold) { 05779 /* Send answer frame if requested */ 05780 p->subs[idx].needhold = 0; 05781 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05782 p->subs[idx].f.subclass = AST_CONTROL_HOLD; 05783 ast_mutex_unlock(&p->lock); 05784 ast_debug(1, "Sending hold on '%s'\n", ast->name); 05785 return &p->subs[idx].f; 05786 } 05787 05788 if (p->subs[idx].needunhold) { 05789 /* Send answer frame if requested */ 05790 p->subs[idx].needunhold = 0; 05791 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05792 p->subs[idx].f.subclass = AST_CONTROL_UNHOLD; 05793 ast_mutex_unlock(&p->lock); 05794 ast_debug(1, "Sending unhold on '%s'\n", ast->name); 05795 return &p->subs[idx].f; 05796 } 05797 05798 if (ast->rawreadformat == AST_FORMAT_SLINEAR) { 05799 if (!p->subs[idx].linear) { 05800 p->subs[idx].linear = 1; 05801 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 05802 if (res) 05803 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx); 05804 } 05805 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) || 05806 (ast->rawreadformat == AST_FORMAT_ALAW)) { 05807 if (p->subs[idx].linear) { 05808 p->subs[idx].linear = 0; 05809 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 05810 if (res) 05811 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx); 05812 } 05813 } else { 05814 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat)); 05815 ast_mutex_unlock(&p->lock); 05816 return NULL; 05817 } 05818 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET; 05819 CHECK_BLOCKING(ast); 05820 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); 05821 ast_clear_flag(ast, AST_FLAG_BLOCKING); 05822 /* Check for hangup */ 05823 if (res < 0) { 05824 f = NULL; 05825 if (res == -1) { 05826 if (errno == EAGAIN) { 05827 /* Return "NULL" frame if there is nobody there */ 05828 ast_mutex_unlock(&p->lock); 05829 return &p->subs[idx].f; 05830 } else if (errno == ELAST) { 05831 f = __dahdi_exception(ast); 05832 } else 05833 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno)); 05834 } 05835 ast_mutex_unlock(&p->lock); 05836 return f; 05837 } 05838 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) { 05839 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); 05840 f = __dahdi_exception(ast); 05841 ast_mutex_unlock(&p->lock); 05842 return f; 05843 } 05844 if (p->tdd) { /* if in TDD mode, see if we receive that */ 05845 int c; 05846 05847 c = tdd_feed(p->tdd,readbuf,READ_SIZE); 05848 if (c < 0) { 05849 ast_debug(1,"tdd_feed failed\n"); 05850 ast_mutex_unlock(&p->lock); 05851 return NULL; 05852 } 05853 if (c) { /* if a char to return */ 05854 p->subs[idx].f.subclass = 0; 05855 p->subs[idx].f.frametype = AST_FRAME_TEXT; 05856 p->subs[idx].f.mallocd = 0; 05857 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; 05858 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET; 05859 p->subs[idx].f.datalen = 1; 05860 *((char *) p->subs[idx].f.data.ptr) = c; 05861 ast_mutex_unlock(&p->lock); 05862 return &p->subs[idx].f; 05863 } 05864 } 05865 /* Ensure the CW timer decrements only on a single subchannel */ 05866 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) { 05867 p->callwaitingrepeat--; 05868 } 05869 if (p->cidcwexpire) 05870 p->cidcwexpire--; 05871 /* Repeat callwaiting */ 05872 if (p->callwaitingrepeat == 1) { 05873 p->callwaitrings++; 05874 dahdi_callwait(ast); 05875 } 05876 /* Expire CID/CW */ 05877 if (p->cidcwexpire == 1) { 05878 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n"); 05879 restore_conference(p); 05880 } 05881 if (p->subs[idx].linear) { 05882 p->subs[idx].f.datalen = READ_SIZE * 2; 05883 } else 05884 p->subs[idx].f.datalen = READ_SIZE; 05885 05886 /* Handle CallerID Transmission */ 05887 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) { 05888 send_callerid(p); 05889 } 05890 05891 p->subs[idx].f.frametype = AST_FRAME_VOICE; 05892 p->subs[idx].f.subclass = ast->rawreadformat; 05893 p->subs[idx].f.samples = READ_SIZE; 05894 p->subs[idx].f.mallocd = 0; 05895 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; 05896 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]); 05897 #if 0 05898 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name); 05899 #endif 05900 if (p->dialing || /* Transmitting something */ 05901 (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */ 05902 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */ 05903 ) { 05904 /* Whoops, we're still dialing, or in a state where we shouldn't transmit.... 05905 don't send anything */ 05906 p->subs[idx].f.frametype = AST_FRAME_NULL; 05907 p->subs[idx].f.subclass = 0; 05908 p->subs[idx].f.samples = 0; 05909 p->subs[idx].f.mallocd = 0; 05910 p->subs[idx].f.offset = 0; 05911 p->subs[idx].f.data.ptr = NULL; 05912 p->subs[idx].f.datalen= 0; 05913 } 05914 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !idx) { 05915 /* Perform busy detection. etc on the dahdi line */ 05916 int mute; 05917 05918 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f); 05919 05920 /* Check if DSP code thinks we should be muting this frame and mute the conference if so */ 05921 mute = ast_dsp_was_muted(p->dsp); 05922 if (p->muting != mute) { 05923 p->muting = mute; 05924 dahdi_confmute(p, mute); 05925 } 05926 05927 if (f) { 05928 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) { 05929 if ((ast->_state == AST_STATE_UP) && !p->outgoing) { 05930 /* Treat this as a "hangup" instead of a "busy" on the assumption that 05931 a busy */ 05932 f = NULL; 05933 } 05934 } else if (f->frametype == AST_FRAME_DTMF) { 05935 #ifdef HAVE_PRI 05936 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && 05937 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) || 05938 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) { 05939 /* Don't accept in-band DTMF when in overlap dial mode */ 05940 f->frametype = AST_FRAME_NULL; 05941 f->subclass = 0; 05942 } 05943 #endif 05944 /* DSP clears us of being pulse */ 05945 p->pulsedial = 0; 05946 } 05947 } 05948 } else 05949 f = &p->subs[idx].f; 05950 05951 if (f && (f->frametype == AST_FRAME_DTMF)) 05952 dahdi_handle_dtmfup(ast, idx, &f); 05953 05954 /* If we have a fake_event, trigger exception to handle it */ 05955 if (p->fake_event) 05956 ast_set_flag(ast, AST_FLAG_EXCEPTION); 05957 05958 ast_mutex_unlock(&p->lock); 05959 return f; 05960 }
| static struct ast_channel * dahdi_request | ( | const char * | type, | |
| int | format, | |||
| void * | data, | |||
| int * | cause | |||
| ) | [static, read] |
Definition at line 9450 of file chan_dahdi.c.
References alloc_sub(), AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CDR_CALLWAIT, ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RESERVED, ast_strdupa, AST_TRANS_CAP_DIGITAL, ast_verbose, available(), dahdi_pvt::bearer, ast_channel::cdrflags, CHAN_PSEUDO, chandup(), dahdi_pvt::channel, dahdi_pvt::confirmanswer, dahdi_pri::crvend, dahdi_pri::crvs, dahdi_new(), dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::distinctivering, iflist, iflock, dahdi_pvt::inalarm, dahdi_pri::lock, lock, LOG_NOTICE, LOG_WARNING, dahdi_pvt::next, NUM_SPANS, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::prev, dahdi_pvt::pri, pri_assign_bearer(), pri_find_empty_chan(), pris, dahdi_pri::pvts, restart_monitor(), s, dahdi_pvt::sig, SIG_FXSKS, dahdi_pri::span, strsep(), SUB_CALLWAIT, SUB_REAL, dahdi_pvt::subs, and ast_channel::transfercapability.
Referenced by pri_dchannel().
09451 { 09452 ast_group_t groupmatch = 0; 09453 int channelmatch = -1; 09454 int roundrobin = 0; 09455 int callwait = 0; 09456 int busy = 0; 09457 struct dahdi_pvt *p; 09458 struct ast_channel *tmp = NULL; 09459 char *dest=NULL; 09460 int x; 09461 char *s; 09462 char opt=0; 09463 int res=0, y=0; 09464 int backwards = 0; 09465 #ifdef HAVE_PRI 09466 int crv; 09467 int bearer = -1; 09468 int trunkgroup; 09469 struct dahdi_pri *pri=NULL; 09470 #endif 09471 struct dahdi_pvt *exitpvt, *start, *end; 09472 ast_mutex_t *lock; 09473 int channelmatched = 0; 09474 int groupmatched = 0; 09475 09476 /* 09477 * data is ---v 09478 * Dial(DAHDI/pseudo[/extension]) 09479 * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension]) 09480 * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension]) 09481 * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension]) 09482 * 09483 * g - channel group allocation search forward 09484 * G - channel group allocation search backward 09485 * r - channel group allocation round robin search forward 09486 * R - channel group allocation round robin search backward 09487 * 09488 * c - Wait for DTMF digit to confirm answer 09489 * r<cadance#> - Set distintive ring cadance number 09490 * d - Force bearer capability for ISDN/SS7 call to digital. 09491 */ 09492 09493 /* Assume we're locking the iflock */ 09494 lock = &iflock; 09495 start = iflist; 09496 end = ifend; 09497 if (data) { 09498 dest = ast_strdupa((char *)data); 09499 } else { 09500 ast_log(LOG_WARNING, "Channel requested with no data\n"); 09501 return NULL; 09502 } 09503 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') { 09504 /* Retrieve the group number */ 09505 char *stringp; 09506 09507 stringp = dest + 1; 09508 s = strsep(&stringp, "/"); 09509 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) { 09510 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data); 09511 return NULL; 09512 } 09513 groupmatch = ((ast_group_t) 1 << x); 09514 if (toupper(dest[0]) == 'G') { 09515 if (dest[0] == 'G') { 09516 backwards = 1; 09517 p = ifend; 09518 } else 09519 p = iflist; 09520 } else { 09521 if (dest[0] == 'R') { 09522 backwards = 1; 09523 p = round_robin[x]?round_robin[x]->prev:ifend; 09524 if (!p) 09525 p = ifend; 09526 } else { 09527 p = round_robin[x]?round_robin[x]->next:iflist; 09528 if (!p) 09529 p = iflist; 09530 } 09531 roundrobin = 1; 09532 } 09533 } else { 09534 char *stringp; 09535 09536 stringp = dest; 09537 s = strsep(&stringp, "/"); 09538 p = iflist; 09539 if (!strcasecmp(s, "pseudo")) { 09540 /* Special case for pseudo */ 09541 x = CHAN_PSEUDO; 09542 channelmatch = x; 09543 } 09544 #ifdef HAVE_PRI 09545 else if ((res = sscanf(s, "%30d:%30d%1c%30d", &trunkgroup, &crv, &opt, &y)) > 1) { 09546 if ((trunkgroup < 1) || (crv < 1)) { 09547 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data); 09548 return NULL; 09549 } 09550 res--; 09551 for (x = 0; x < NUM_SPANS; x++) { 09552 if (pris[x].trunkgroup == trunkgroup) { 09553 pri = pris + x; 09554 lock = &pri->lock; 09555 start = pri->crvs; 09556 end = pri->crvend; 09557 break; 09558 } 09559 } 09560 if (!pri) { 09561 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup); 09562 return NULL; 09563 } 09564 channelmatch = crv; 09565 p = pris[x].crvs; 09566 } 09567 #endif 09568 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) { 09569 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data); 09570 return NULL; 09571 } else { 09572 channelmatch = x; 09573 } 09574 } 09575 /* Search for an unowned channel */ 09576 ast_mutex_lock(lock); 09577 exitpvt = p; 09578 while (p && !tmp) { 09579 if (roundrobin) 09580 round_robin[x] = p; 09581 #if 0 09582 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch); 09583 #endif 09584 09585 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) { 09586 ast_debug(1, "Using channel %d\n", p->channel); 09587 if (p->inalarm) 09588 goto next; 09589 09590 callwait = (p->owner != NULL); 09591 #ifdef HAVE_PRI 09592 if (pri && (p->subs[SUB_REAL].dfd < 0)) { 09593 if (p->sig != SIG_FXSKS) { 09594 /* Gotta find an actual channel to use for this 09595 CRV if this isn't a callwait */ 09596 bearer = pri_find_empty_chan(pri, 0); 09597 if (bearer < 0) { 09598 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv); 09599 p = NULL; 09600 break; 09601 } 09602 pri_assign_bearer(p, pri, pri->pvts[bearer]); 09603 } else { 09604 if (alloc_sub(p, 0)) { 09605 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n"); 09606 p = NULL; 09607 break; 09608 } else 09609 ast_debug(1, "Allocated placeholder pseudo channel\n"); 09610 09611 p->pri = pri; 09612 } 09613 } 09614 #endif 09615 if (p->channel == CHAN_PSEUDO) { 09616 p = chandup(p); 09617 if (!p) { 09618 break; 09619 } 09620 } 09621 if (p->owner) { 09622 if (alloc_sub(p, SUB_CALLWAIT)) { 09623 p = NULL; 09624 break; 09625 } 09626 } 09627 p->outgoing = 1; 09628 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0); 09629 #ifdef HAVE_PRI 09630 if (p->bearer) { 09631 /* Log owner to bearer channel, too */ 09632 p->bearer->owner = tmp; 09633 } 09634 #endif 09635 /* Make special notes */ 09636 if (res > 1) { 09637 if (opt == 'c') { 09638 /* Confirm answer */ 09639 p->confirmanswer = 1; 09640 } else if (opt == 'r') { 09641 /* Distinctive ring */ 09642 if (res < 3) 09643 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data); 09644 else 09645 p->distinctivering = y; 09646 } else if (opt == 'd') { 09647 /* If this is an ISDN call, make it digital */ 09648 p->digital = 1; 09649 if (tmp) 09650 tmp->transfercapability = AST_TRANS_CAP_DIGITAL; 09651 } else { 09652 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data); 09653 } 09654 } 09655 /* Note if the call is a call waiting call */ 09656 if (tmp && callwait) 09657 tmp->cdrflags |= AST_CDR_CALLWAIT; 09658 break; 09659 } 09660 next: 09661 if (backwards) { 09662 p = p->prev; 09663 if (!p) 09664 p = end; 09665 } else { 09666 p = p->next; 09667 if (!p) 09668 p = start; 09669 } 09670 /* stop when you roll to the one that we started from */ 09671 if (p == exitpvt) 09672 break; 09673 } 09674 ast_mutex_unlock(lock); 09675 restart_monitor(); 09676 if (callwait) 09677 *cause = AST_CAUSE_BUSY; 09678 else if (!tmp) { 09679 if (channelmatched) { 09680 if (busy) 09681 *cause = AST_CAUSE_BUSY; 09682 } else if (groupmatched) { 09683 *cause = AST_CAUSE_CONGESTION; 09684 } 09685 } 09686 09687 return tmp; 09688 }
| static int dahdi_restart | ( | void | ) | [static] |
Definition at line 12505 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, mwi_thread_lock, dahdi_pvt::next, NUM_SPANS, 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().
12506 { 12507 #if defined(HAVE_PRI) || defined(HAVE_SS7) 12508 int i, j; 12509 #endif 12510 int cancel_code; 12511 struct dahdi_pvt *p; 12512 12513 ast_mutex_lock(&restart_lock); 12514 12515 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n"); 12516 dahdi_softhangup_all(); 12517 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n"); 12518 12519 #if defined(HAVE_PRI) 12520 for (i = 0; i < NUM_SPANS; i++) { 12521 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) { 12522 cancel_code = pthread_cancel(pris[i].master); 12523 pthread_kill(pris[i].master, SIGURG); 12524 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code); 12525 pthread_join(pris[i].master, NULL); 12526 ast_debug(4, "Joined thread of span %d\n", i); 12527 } 12528 } 12529 #endif 12530 12531 #if defined(HAVE_SS7) 12532 for (i = 0; i < NUM_SPANS; i++) { 12533 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) { 12534 cancel_code = pthread_cancel(linksets[i].master); 12535 pthread_kill(linksets[i].master, SIGURG); 12536 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code); 12537 pthread_join(linksets[i].master, NULL); 12538 ast_debug(4, "Joined thread of span %d\n", i); 12539 } 12540 } 12541 #endif 12542 12543 ast_mutex_lock(&monlock); 12544 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 12545 cancel_code = pthread_cancel(monitor_thread); 12546 pthread_kill(monitor_thread, SIGURG); 12547 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code); 12548 pthread_join(monitor_thread, NULL); 12549 ast_debug(4, "Joined monitor thread\n"); 12550 } 12551 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */ 12552 12553 ast_mutex_lock(&mwi_thread_lock); 12554 while (mwi_thread_count > 0) { 12555 ast_debug(3, "Waiting on %d mwi_send_thread(s) to finish\n", mwi_thread_count); 12556 ast_cond_wait(&mwi_thread_complete, &mwi_thread_lock); 12557 } 12558 ast_mutex_unlock(&mwi_thread_lock); 12559 ast_mutex_lock(&ss_thread_lock); 12560 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */ 12561 int x = DAHDI_FLASH; 12562 ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count); 12563 12564 for (p = iflist; p; p = p->next) { 12565 if (p->owner) 12566 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 */ 12567 } 12568 ast_cond_wait(&ss_thread_complete, &ss_thread_lock); 12569 } 12570 12571 /* ensure any created channels before monitor threads were stopped are hungup */ 12572 dahdi_softhangup_all(); 12573 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n"); 12574 destroy_all_channels(); 12575 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels()); 12576 12577 ast_mutex_unlock(&monlock); 12578 12579 #ifdef HAVE_PRI 12580 for (i = 0; i < NUM_SPANS; i++) { 12581 for (j = 0; j < NUM_DCHANS; j++) 12582 dahdi_close_pri_fd(&(pris[i]), j); 12583 } 12584 12585 memset(pris, 0, sizeof(pris)); 12586 for (i = 0; i < NUM_SPANS; i++) { 12587 ast_mutex_init(&pris[i].lock); 12588 pris[i].offset = -1; 12589 pris[i].master = AST_PTHREADT_NULL; 12590 for (j = 0; j < NUM_DCHANS; j++) 12591 pris[i].fds[j] = -1; 12592 } 12593 pri_set_error(dahdi_pri_error); 12594 pri_set_message(dahdi_pri_message); 12595 #endif 12596 #ifdef HAVE_SS7 12597 for (i = 0; i < NUM_SPANS; i++) { 12598 for (j = 0; j < NUM_DCHANS; j++) 12599 dahdi_close_ss7_fd(&(linksets[i]), j); 12600 } 12601 12602 memset(linksets, 0, sizeof(linksets)); 12603 for (i = 0; i < NUM_SPANS; i++) { 12604 ast_mutex_init(&linksets[i].lock); 12605 linksets[i].master = AST_PTHREADT_NULL; 12606 for (j = 0; j < NUM_DCHANS; j++) 12607 linksets[i].fds[j] = -1; 12608 } 12609 ss7_set_error(dahdi_ss7_error); 12610 ss7_set_message(dahdi_ss7_message); 12611 #endif 12612 12613 if (setup_dahdi(2) != 0) { 12614 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n"); 12615 ast_mutex_unlock(&ss_thread_lock); 12616 return 1; 12617 } 12618 ast_mutex_unlock(&ss_thread_lock); 12619 ast_mutex_unlock(&restart_lock); 12620 return 0; 12621 }
| static char* dahdi_restart_cmd | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12623 of file chan_dahdi.c.
References ast_cli_args::argc, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_restart(), and ast_cli_entry::usage.
12624 { 12625 switch (cmd) { 12626 case CLI_INIT: 12627 e->command = "dahdi restart"; 12628 e->usage = 12629 "Usage: dahdi restart\n" 12630 " Restarts the DAHDI channels: destroys them all and then\n" 12631 " re-reads them from chan_dahdi.conf.\n" 12632 " Note that this will STOP any running CALL on DAHDI channels.\n" 12633 ""; 12634 return NULL; 12635 case CLI_GENERATE: 12636 return NULL; 12637 } 12638 if (a->argc != 2) 12639 return CLI_SHOWUSAGE; 12640 12641 if (dahdi_restart() != 0) 12642 return CLI_FAILURE; 12643 return CLI_SUCCESS; 12644 }
| static int dahdi_ring_phone | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4457 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().
04458 { 04459 int x; 04460 int res; 04461 /* Make sure our transmit state is on hook */ 04462 x = 0; 04463 x = DAHDI_ONHOOK; 04464 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04465 do { 04466 x = DAHDI_RING; 04467 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04468 if (res) { 04469 switch (errno) { 04470 case EBUSY: 04471 case EINTR: 04472 /* Wait just in case */ 04473 usleep(10000); 04474 continue; 04475 case EINPROGRESS: 04476 res = 0; 04477 break; 04478 default: 04479 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno)); 04480 res = 0; 04481 } 04482 } 04483 } while (res); 04484 return res; 04485 }
| static int dahdi_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 3254 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().
03255 { 03256 /* Data will be our digit string */ 03257 struct dahdi_pvt *p; 03258 char *digits = (char *) data; 03259 03260 if (ast_strlen_zero(digits)) { 03261 ast_debug(1, "No digit string sent to application!\n"); 03262 return -1; 03263 } 03264 03265 p = (struct dahdi_pvt *)chan->tech_pvt; 03266 03267 if (!p) { 03268 ast_debug(1, "Unable to find technology private\n"); 03269 return -1; 03270 } 03271 03272 ast_mutex_lock(&p->lock); 03273 03274 if (!p->pri || !p->call) { 03275 ast_debug(1, "Unable to find pri or call on channel!\n"); 03276 ast_mutex_unlock(&p->lock); 03277 return -1; 03278 } 03279 03280 if (!pri_grab(p, p->pri)) { 03281 pri_keypad_facility(p->pri->pri, p->call, digits); 03282 pri_rel(p->pri); 03283 } else { 03284 ast_debug(1, "Unable to grab pri to send keypad facility!\n"); 03285 ast_mutex_unlock(&p->lock); 03286 return -1; 03287 } 03288 03289 ast_mutex_unlock(&p->lock); 03290 03291 return 0; 03292 }
| static int dahdi_sendtext | ( | struct ast_channel * | c, | |
| const char * | text | |||
| ) | [static] |
Definition at line 15354 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, HEADER_MS, len(), LOG_ERROR, LOG_WARNING, dahdi_pvt::mate, PUT_CLID, PUT_CLID_MARKMS, READ_SIZE, dahdi_pvt::subs, dahdi_pvt::tdd, TDD_BYTES_PER_CHAR, tdd_generate(), ast_channel::tech_pvt, and TRAILER_MS.
15355 { 15356 #define END_SILENCE_LEN 400 15357 #define HEADER_MS 50 15358 #define TRAILER_MS 5 15359 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) 15360 #define ASCII_BYTES_PER_CHAR 80 15361 15362 unsigned char *buf,*mybuf; 15363 struct dahdi_pvt *p = c->tech_pvt; 15364 struct pollfd fds[1]; 15365 int size,res,fd,len,x; 15366 int bytes=0; 15367 /* Initial carrier (imaginary) */ 15368 float cr = 1.0; 15369 float ci = 0.0; 15370 float scont = 0.0; 15371 int idx; 15372 15373 idx = dahdi_get_index(c, p, 0); 15374 if (idx < 0) { 15375 ast_log(LOG_WARNING, "Huh? I don't exist?\n"); 15376 return -1; 15377 } 15378 if (!text[0]) return(0); /* if nothing to send, dont */ 15379 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */ 15380 if (p->mate) 15381 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN); 15382 else 15383 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN); 15384 if (!buf) 15385 return -1; 15386 mybuf = buf; 15387 if (p->mate) { 15388 int codec = AST_LAW(p); 15389 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */ 15390 PUT_CLID_MARKMS; 15391 } 15392 /* Put actual message */ 15393 for (x = 0; text[x]; x++) { 15394 PUT_CLID(text[x]); 15395 } 15396 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */ 15397 PUT_CLID_MARKMS; 15398 } 15399 len = bytes; 15400 buf = mybuf; 15401 } else { 15402 len = tdd_generate(p->tdd, buf, text); 15403 if (len < 1) { 15404 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text)); 15405 ast_free(mybuf); 15406 return -1; 15407 } 15408 } 15409 memset(buf + len, 0x7f, END_SILENCE_LEN); 15410 len += END_SILENCE_LEN; 15411 fd = p->subs[idx].dfd; 15412 while (len) { 15413 if (ast_check_hangup(c)) { 15414 ast_free(mybuf); 15415 return -1; 15416 } 15417 size = len; 15418 if (size > READ_SIZE) 15419 size = READ_SIZE; 15420 fds[0].fd = fd; 15421 fds[0].events = POLLOUT | POLLPRI; 15422 fds[0].revents = 0; 15423 res = poll(fds, 1, -1); 15424 if (!res) { 15425 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 15426 continue; 15427 } 15428 /* if got exception */ 15429 if (fds[0].revents & POLLPRI) { 15430 ast_free(mybuf); 15431 return -1; 15432 } 15433 if (!(fds[0].revents & POLLOUT)) { 15434 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 15435 continue; 15436 } 15437 res = write(fd, buf, size); 15438 if (res != size) { 15439 if (res == -1) { 15440 ast_free(mybuf); 15441 return -1; 15442 } 15443 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 15444 break; 15445 } 15446 len -= size; 15447 buf += size; 15448 } 15449 ast_free(mybuf); 15450 return(0); 15451 }
| static char* dahdi_set_dnd | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13252 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_false(), ast_mutex_lock(), ast_mutex_unlock(), ast_true(), dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_dnd(), ast_cli_args::fd, iflist, iflock, dahdi_pvt::next, and ast_cli_entry::usage.
13253 { 13254 int channel; 13255 int on; 13256 struct dahdi_pvt *dahdi_chan = NULL; 13257 13258 switch (cmd) { 13259 case CLI_INIT: 13260 e->command = "dahdi set dnd"; 13261 e->usage = 13262 "Usage: dahdi set dnd <chan#> <on|off>\n" 13263 " Sets/resets DND (Do Not Disturb) mode on a channel.\n" 13264 " Changes take effect immediately.\n" 13265 " <chan num> is the channel number\n" 13266 " <on|off> Enable or disable DND mode?\n" 13267 ; 13268 return NULL; 13269 case CLI_GENERATE: 13270 return NULL; 13271 } 13272 13273 if (a->argc != 5) 13274 return CLI_SHOWUSAGE; 13275 13276 if ((channel = atoi(a->argv[3])) <= 0) { 13277 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]); 13278 return CLI_SHOWUSAGE; 13279 } 13280 13281 if (ast_true(a->argv[4])) 13282 on = 1; 13283 else if (ast_false(a->argv[4])) 13284 on = 0; 13285 else { 13286 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]); 13287 return CLI_SHOWUSAGE; 13288 } 13289 13290 ast_mutex_lock(&iflock); 13291 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) { 13292 if (dahdi_chan->channel != channel) 13293 continue; 13294 13295 /* Found the channel. Actually set it */ 13296 dahdi_dnd(dahdi_chan, on); 13297 break; 13298 } 13299 ast_mutex_unlock(&iflock); 13300 13301 if (!dahdi_chan) { 13302 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 13303 return CLI_FAILURE; 13304 } 13305 13306 return CLI_SUCCESS; 13307 }
| static int dahdi_set_hook | ( | int | fd, | |
| int | hs | |||
| ) | [inline, static] |
Definition at line 2207 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_thread(), and ss_thread().
02208 { 02209 int x, res; 02210 02211 x = hs; 02212 res = ioctl(fd, DAHDI_HOOK, &x); 02213 02214 if (res < 0) { 02215 if (errno == EINPROGRESS) 02216 return 0; 02217 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno)); 02218 /* will expectedly fail if phone is off hook during operation, such as during a restart */ 02219 } 02220 02221 return res; 02222 }
| static char* dahdi_set_hwgain | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13109 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_subchannel::dfd, errno, ast_cli_args::fd, iflist, iflock, dahdi_pvt::next, SUB_REAL, dahdi_pvt::subs, and ast_cli_entry::usage.
13110 { 13111 int channel; 13112 int gain; 13113 int tx; 13114 struct dahdi_hwgain hwgain; 13115 struct dahdi_pvt *tmp = NULL; 13116 13117 switch (cmd) { 13118 case CLI_INIT: 13119 e->command = "dahdi set hwgain"; 13120 e->usage = 13121 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n" 13122 " Sets the hardware gain on a a given channel, overriding the\n" 13123 " value provided at module loadtime, whether the channel is in\n" 13124 " use or not. Changes take effect immediately.\n" 13125 " <rx|tx> which direction do you want to change (relative to our module)\n" 13126 " <chan num> is the channel number relative to the device\n" 13127 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"; 13128 return NULL; 13129 case CLI_GENERATE: 13130 return NULL; 13131 } 13132 13133 if (a->argc != 6) 13134 return CLI_SHOWUSAGE; 13135 13136 if (!strcasecmp("rx", a->argv[3])) 13137 tx = 0; /* rx */ 13138 else if (!strcasecmp("tx", a->argv[3])) 13139 tx = 1; /* tx */ 13140 else 13141 return CLI_SHOWUSAGE; 13142 13143 channel = atoi(a->argv[4]); 13144 gain = atof(a->argv[5])*10.0; 13145 13146 ast_mutex_lock(&iflock); 13147 13148 for (tmp = iflist; tmp; tmp = tmp->next) { 13149 13150 if (tmp->channel != channel) 13151 continue; 13152 13153 if (tmp->subs[SUB_REAL].dfd == -1) 13154 break; 13155 13156 hwgain.newgain = gain; 13157 hwgain.tx = tx; 13158 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) { 13159 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno)); 13160 ast_mutex_unlock(&iflock); 13161 return CLI_FAILURE; 13162 } 13163 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n", 13164 tx ? "tx" : "rx", gain, (float)gain/10.0, channel); 13165 break; 13166 } 13167 13168 ast_mutex_unlock(&iflock); 13169 13170 if (tmp) 13171 return CLI_SUCCESS; 13172 13173 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 13174 return CLI_FAILURE; 13175 13176 }
| static char* dahdi_set_swgain | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13178 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_subchannel::dfd, ast_cli_args::fd, iflist, iflock, dahdi_pvt::law, lock, dahdi_pvt::next, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, dahdi_pvt::subs, and ast_cli_entry::usage.
13179 { 13180 int channel; 13181 float gain; 13182 int tx; 13183 int res; 13184 ast_mutex_t *lock; 13185 struct dahdi_pvt *tmp = NULL; 13186 13187 switch (cmd) { 13188 case CLI_INIT: 13189 e->command = "dahdi set swgain"; 13190 e->usage = 13191 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n" 13192 " Sets the software gain on a a given channel, overriding the\n" 13193 " value provided at module loadtime, whether the channel is in\n" 13194 " use or not. Changes take effect immediately.\n" 13195 " <rx|tx> which direction do you want to change (relative to our module)\n" 13196 " <chan num> is the channel number relative to the device\n" 13197 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"; 13198 return NULL; 13199 case CLI_GENERATE: 13200 return NULL; 13201 } 13202 13203 lock = &iflock; 13204 13205 if (a->argc != 6) 13206 return CLI_SHOWUSAGE; 13207 13208 if (!strcasecmp("rx", a->argv[3])) 13209 tx = 0; /* rx */ 13210 else if (!strcasecmp("tx", a->argv[3])) 13211 tx = 1; /* tx */ 13212 else 13213 return CLI_SHOWUSAGE; 13214 13215 channel = atoi(a->argv[4]); 13216 gain = atof(a->argv[5]); 13217 13218 ast_mutex_lock(lock); 13219 for (tmp = iflist; tmp; tmp = tmp->next) { 13220 13221 if (tmp->channel != channel) 13222 continue; 13223 13224 if (tmp->subs[SUB_REAL].dfd == -1) 13225 break; 13226 13227 if (tx) 13228 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law); 13229 else 13230 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law); 13231 13232 if (res) { 13233 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel); 13234 ast_mutex_unlock(lock); 13235 return CLI_FAILURE; 13236 } 13237 13238 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n", 13239 tx ? "tx" : "rx", gain, channel); 13240 break; 13241 } 13242 ast_mutex_unlock(lock); 13243 13244 if (tmp) 13245 return CLI_SUCCESS; 13246 13247 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 13248 return CLI_FAILURE; 13249 13250 }
| static int dahdi_setlaw | ( | int | dfd, | |
| int | law | |||
| ) | [static] |
Definition at line 9691 of file chan_dahdi.c.
Referenced by pri_dchannel(), and ss7_start_call().
09692 { 09693 return ioctl(dfd, DAHDI_SETLAW, &law); 09694 }
| static int dahdi_setlinear | ( | int | dfd, | |
| int | linear | |||
| ) | [static] |
Definition at line 1511 of file chan_dahdi.c.
Referenced by dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_write(), send_callerid(), and ss_thread().
| static int dahdi_setoption | ( | struct ast_channel * | chan, | |
| int | option, | |||
| void * | data, | |||
| int | datalen | |||
| ) | [static] |
Definition at line 3831 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, len(), LOG_WARNING, dahdi_pvt::mate, oprmode::mode, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, oprmode::peer, pp, READ_SIZE, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_free(), tdd_new(), ast_channel::tech_pvt, and dahdi_pvt::txgain.
03832 { 03833 char *cp; 03834 signed char *scp; 03835 int x; 03836 int idx; 03837 struct dahdi_pvt *p = chan->tech_pvt, *pp; 03838 struct oprmode *oprmode; 03839 03840 03841 /* all supported options require data */ 03842 if (!data || (datalen < 1)) { 03843 errno = EINVAL; 03844 return -1; 03845 } 03846 03847 switch (option) { 03848 case AST_OPTION_TXGAIN: 03849 scp = (signed char *) data; 03850 idx = dahdi_get_index(chan, p, 0); 03851 if (idx < 0) { 03852 ast_log(LOG_WARNING, "No index in TXGAIN?\n"); 03853 return -1; 03854 } 03855 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp); 03856 return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law); 03857 case AST_OPTION_RXGAIN: 03858 scp = (signed char *) data; 03859 idx = dahdi_get_index(chan, p, 0); 03860 if (idx < 0) { 03861 ast_log(LOG_WARNING, "No index in RXGAIN?\n"); 03862 return -1; 03863 } 03864 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp); 03865 return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law); 03866 case AST_OPTION_TONE_VERIFY: 03867 if (!p->dsp) 03868 break; 03869 cp = (char *) data; 03870 switch (*cp) { 03871 case 1: 03872 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name); 03873 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */ 03874 break; 03875 case 2: 03876 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name); 03877 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */ 03878 break; 03879 default: 03880 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name); 03881 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */ 03882 break; 03883 } 03884 break; 03885 case AST_OPTION_TDD: 03886 /* turn on or off TDD */ 03887 cp = (char *) data; 03888 p->mate = 0; 03889 if (!*cp) { /* turn it off */ 03890 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name); 03891 if (p->tdd) 03892 tdd_free(p->tdd); 03893 p->tdd = 0; 03894 break; 03895 } 03896 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n", 03897 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name); 03898 dahdi_disable_ec(p); 03899 /* otherwise, turn it on */ 03900 if (!p->didtdd) { /* if havent done it yet */ 03901 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */ 03902 unsigned char *buf; 03903 int size, res, fd, len; 03904 struct pollfd fds[1]; 03905 03906 buf = mybuf; 03907 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */ 03908 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */ 03909 len = 40000; 03910 idx = dahdi_get_index(chan, p, 0); 03911 if (idx < 0) { 03912 ast_log(LOG_WARNING, "No index in TDD?\n"); 03913 return -1; 03914 } 03915 fd = p->subs[idx].dfd; 03916 while (len) { 03917 if (ast_check_hangup(chan)) 03918 return -1; 03919 size = len; 03920 if (size > READ_SIZE) 03921 size = READ_SIZE; 03922 fds[0].fd = fd; 03923 fds[0].events = POLLPRI | POLLOUT; 03924 fds[0].revents = 0; 03925 res = poll(fds, 1, -1); 03926 if (!res) { 03927 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 03928 continue; 03929 } 03930 /* if got exception */ 03931 if (fds[0].revents & POLLPRI) 03932 return -1; 03933 if (!(fds[0].revents & POLLOUT)) { 03934 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 03935 continue; 03936 } 03937 res = write(fd, buf, size); 03938 if (res != size) { 03939 if (res == -1) return -1; 03940 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 03941 break; 03942 } 03943 len -= size; 03944 buf += size; 03945 } 03946 p->didtdd = 1; /* set to have done it now */ 03947 } 03948 if (*cp == 2) { /* Mate mode */ 03949 if (p->tdd) 03950 tdd_free(p->tdd); 03951 p->tdd = 0; 03952 p->mate = 1; 03953 break; 03954 } 03955 if (!p->tdd) { /* if we dont have one yet */ 03956 p->tdd = tdd_new(); /* allocate one */ 03957 } 03958 break; 03959 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */ 03960 if (!p->dsp) 03961 break; 03962 cp = (char *) data; 03963 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n", 03964 *cp ? "ON" : "OFF", (int) *cp, chan->name); 03965 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax); 03966 break; 03967 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */ 03968 cp = (char *) data; 03969 if (!*cp) { 03970 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name); 03971 x = 0; 03972 dahdi_disable_ec(p); 03973 } else { 03974 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name); 03975 x = 1; 03976 } 03977 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1) 03978 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno)); 03979 break; 03980 case AST_OPTION_OPRMODE: /* Operator services mode */ 03981 oprmode = (struct oprmode *) data; 03982 pp = oprmode->peer->tech_pvt; 03983 p->oprmode = pp->oprmode = 0; 03984 /* setup peers */ 03985 p->oprpeer = pp; 03986 pp->oprpeer = p; 03987 /* setup modes, if any */ 03988 if (oprmode->mode) 03989 { 03990 pp->oprmode = oprmode->mode; 03991 p->oprmode = -oprmode->mode; 03992 } 03993 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n", 03994 oprmode->mode, chan->name,oprmode->peer->name); 03995 break; 03996 case AST_OPTION_ECHOCAN: 03997 cp = (char *) data; 03998 if (*cp) { 03999 ast_debug(1, "Enabling echo cancelation on %s\n", chan->name); 04000 dahdi_enable_ec(p); 04001 } else { 04002 ast_debug(1, "Disabling echo cancelation on %s\n", chan->name); 04003 dahdi_disable_ec(p); 04004 } 04005 break; 04006 } 04007 errno = 0; 04008 04009 return 0; 04010 }
| static char* dahdi_show_channel | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12780 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_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, 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, MAX_SLAVES, ast_variable::name, dahdi_pvt::next, ast_variable::next, NUM_SPANS, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::params, dahdi_pvt::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, and dahdi_pvt::vars.
12781 { 12782 int channel; 12783 struct dahdi_pvt *tmp = NULL; 12784 struct dahdi_confinfo ci; 12785 struct dahdi_params ps; 12786 int x; 12787 ast_mutex_t *lock; 12788 struct dahdi_pvt *start; 12789 #ifdef HAVE_PRI 12790 char *c; 12791 int trunkgroup; 12792 struct dahdi_pri *pri=NULL; 12793 #endif 12794 switch (cmd) { 12795 case CLI_INIT: 12796 e->command = "dahdi show channel"; 12797 e->usage = 12798 "Usage: dahdi show channel <chan num>\n" 12799 " Detailed information about a given channel\n"; 12800 return NULL; 12801 case CLI_GENERATE: 12802 return NULL; 12803 } 12804 12805 lock = &iflock; 12806 start = iflist; 12807 12808 if (a->argc != 4) 12809 return CLI_SHOWUSAGE; 12810 #ifdef HAVE_PRI 12811 if ((c = strchr(a->argv[3], ':'))) { 12812 if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2) 12813 return CLI_SHOWUSAGE; 12814 if ((trunkgroup < 1) || (channel < 1)) 12815 return CLI_SHOWUSAGE; 12816 for (x = 0; x < NUM_SPANS; x++) { 12817 if (pris[x].trunkgroup == trunkgroup) { 12818 pri = pris + x; 12819 break; 12820 } 12821 } 12822 if (pri) { 12823 start = pri->crvs; 12824 lock = &pri->lock; 12825 } else { 12826 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup); 12827 return CLI_FAILURE; 12828 } 12829 } else 12830 #endif 12831 channel = atoi(a->argv[3]); 12832 12833 ast_mutex_lock(lock); 12834 tmp = start; 12835 while (tmp) { 12836 if (tmp->channel == channel) { 12837 #ifdef HAVE_PRI 12838 if (pri) 12839 ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel); 12840 else 12841 #endif 12842 ast_cli(a->fd, "Channel: %d\n", tmp->channel); 12843 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd); 12844 ast_cli(a->fd, "Span: %d\n", tmp->span); 12845 ast_cli(a->fd, "Extension: %s\n", tmp->exten); 12846 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no"); 12847 ast_cli(a->fd, "Context: %s\n", tmp->context); 12848 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num); 12849 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton); 12850 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name); 12851 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none")); 12852 if (tmp->vars) { 12853 struct ast_variable *v; 12854 ast_cli(a->fd, "Variables:\n"); 12855 for (v = tmp->vars ; v ; v = v->next) 12856 ast_cli(a->fd, " %s = %s\n", v->name, v->value); 12857 } 12858 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy); 12859 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm); 12860 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig)); 12861 ast_cli(a->fd, "Radio: %d\n", tmp->radio); 12862 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>"); 12863 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)" : ""); 12864 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)" : ""); 12865 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)" : ""); 12866 ast_cli(a->fd, "Confno: %d\n", tmp->confno); 12867 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno); 12868 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference); 12869 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no"); 12870 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no"); 12871 if (tmp->busydetect) { 12872 #if defined(BUSYDETECT_TONEONLY) 12873 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n"); 12874 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE) 12875 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n"); 12876 #endif 12877 #ifdef BUSYDETECT_DEBUG 12878 ast_cli(a->fd, " Busy Detector Debug: Enabled\n"); 12879 #endif 12880 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount); 12881 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength); 12882 } 12883 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no"); 12884 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no"); 12885 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas); 12886 ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown"); 12887 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no"); 12888 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no"); 12889 ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no"); 12890 ast_cli(a->fd, "Echo Cancellation:\n"); 12891 12892 if (tmp->echocancel.head.tap_length) { 12893 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length); 12894 for (x = 0; x < tmp->echocancel.head.param_count; x++) { 12895 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value); 12896 } 12897 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF"); 12898 } else { 12899 ast_cli(a->fd, "\tnone\n"); 12900 } 12901 if (tmp->master) 12902 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel); 12903 for (x = 0; x < MAX_SLAVES; x++) { 12904 if (tmp->slaves[x]) 12905 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel); 12906 } 12907 #ifdef HAVE_SS7 12908 if (tmp->ss7) { 12909 ast_cli(a->fd, "CIC: %d\n", tmp->cic); 12910 } 12911 #endif 12912 #ifdef HAVE_PRI 12913 if (tmp->pri) { 12914 ast_cli(a->fd, "PRI Flags: "); 12915 if (tmp->resetting) 12916 ast_cli(a->fd, "Resetting "); 12917 if (tmp->call) 12918 ast_cli(a->fd, "Call "); 12919 if (tmp->bearer) 12920 ast_cli(a->fd, "Bearer "); 12921 ast_cli(a->fd, "\n"); 12922 if (tmp->logicalspan) 12923 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan); 12924 else 12925 ast_cli(a->fd, "PRI Logical Span: Implicit\n"); 12926 } 12927 12928 #endif 12929 memset(&ci, 0, sizeof(ci)); 12930 ps.channo = tmp->channel; 12931 if (tmp->subs[SUB_REAL].dfd > -1) { 12932 memset(&ci, 0, sizeof(ci)); 12933 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 12934 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode); 12935 } 12936 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) { 12937 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No"); 12938 } 12939 memset(&ps, 0, sizeof(ps)); 12940 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 12941 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno)); 12942 } else { 12943 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook"); 12944 } 12945 } 12946 ast_mutex_unlock(lock); 12947 return CLI_SUCCESS; 12948 } 12949 tmp = tmp->next; 12950 } 12951 12952 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 12953 ast_mutex_unlock(lock); 12954 return CLI_FAILURE; 12955 }
| static char* dahdi_show_channels | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12656 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_pvt::context, dahdi_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, NUM_SPANS, pris, dahdi_pvt::remotelyblocked, and ast_cli_entry::usage.
12657 { 12658 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 12659 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 12660 unsigned int targetnum = 0; 12661 int filtertype = 0; 12662 struct dahdi_pvt *tmp = NULL; 12663 char tmps[20] = ""; 12664 char statestr[20] = ""; 12665 char blockstr[20] = ""; 12666 ast_mutex_t *lock; 12667 struct dahdi_pvt *start; 12668 #ifdef HAVE_PRI 12669 int trunkgroup; 12670 struct dahdi_pri *pri = NULL; 12671 int x; 12672 #endif 12673 switch (cmd) { 12674 case CLI_INIT: 12675 e->command = "dahdi show channels [trunkgroup|group|context]"; 12676 e->usage = 12677 "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n" 12678 " Shows a list of available channels with optional filtering\n" 12679 " <group> must be a number between 0 and 63\n"; 12680 return NULL; 12681 case CLI_GENERATE: 12682 return NULL; 12683 } 12684 12685 lock = &iflock; 12686 start = iflist; 12687 12688 /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */ 12689 12690 if (!((a->argc == 3) || (a->argc == 5))) 12691 return CLI_SHOWUSAGE; 12692 12693 if (a->argc == 5) { 12694 #ifdef HAVE_PRI 12695 if (!strcasecmp(a->argv[3], "trunkgroup")) { 12696 /* this option requires no special handling, so leave filtertype to zero */ 12697 if ((trunkgroup = atoi(a->argv[4])) < 1) 12698 return CLI_SHOWUSAGE; 12699 for (x = 0; x < NUM_SPANS; x++) { 12700 if (pris[x].trunkgroup == trunkgroup) { 12701 pri = pris + x; 12702 break; 12703 } 12704 } 12705 if (pri) { 12706 start = pri->crvs; 12707 lock = &pri->lock; 12708 } else { 12709 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup); 12710 return CLI_FAILURE; 12711 } 12712 } else 12713 #endif 12714 if (!strcasecmp(a->argv[3], "group")) { 12715 targetnum = atoi(a->argv[4]); 12716 if ((targetnum < 0) || (targetnum > 63)) 12717 return CLI_SHOWUSAGE; 12718 targetnum = 1 << targetnum; 12719 filtertype = 1; 12720 } else if (!strcasecmp(a->argv[3], "context")) { 12721 filtertype = 2; 12722 } 12723 } 12724 12725 ast_mutex_lock(lock); 12726 #ifdef HAVE_PRI 12727 ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State"); 12728 #else 12729 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State"); 12730 #endif 12731 12732 tmp = start; 12733 while (tmp) { 12734 if (filtertype) { 12735 switch(filtertype) { 12736 case 1: /* dahdi show channels group <group> */ 12737 if (!(tmp->group & targetnum)) { 12738 tmp = tmp->next; 12739 continue; 12740 } 12741 break; 12742 case 2: /* dahdi show channels context <context> */ 12743 if (strcasecmp(tmp->context, a->argv[4])) { 12744 tmp = tmp->next; 12745 continue; 12746 } 12747 break; 12748 default: 12749 ; 12750 } 12751 } 12752 if (tmp->channel > 0) { 12753 snprintf(tmps, sizeof(tmps), "%d", tmp->channel); 12754 } else 12755 ast_copy_string(tmps, "pseudo", sizeof(tmps)); 12756 12757 if (tmp->locallyblocked) 12758 blockstr[0] = 'L'; 12759 else 12760 blockstr[0] = ' '; 12761 12762 if (tmp->remotelyblocked) 12763 blockstr[1] = 'R'; 12764 else 12765 blockstr[1] = ' '; 12766 12767 blockstr[2] = '\0'; 12768 12769 snprintf(statestr, sizeof(statestr), "%s", "In Service"); 12770 12771 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr); 12772 tmp = tmp->next; 12773 } 12774 ast_mutex_unlock(lock); 12775 return CLI_SUCCESS; 12776 #undef FORMAT 12777 #undef FORMAT2 12778 }
| static char* dahdi_show_status | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12994 of file chan_dahdi.c.
References ast_cli(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, errno, ast_cli_args::fd, FORMAT, FORMAT2, and ast_cli_entry::usage.
12995 { 12996 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n" 12997 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n" 12998 int span; 12999 int res; 13000 char alarmstr[50]; 13001 13002 int ctl; 13003 struct dahdi_spaninfo s; 13004 13005 switch (cmd) { 13006 case CLI_INIT: 13007 e->command = "dahdi show status"; 13008 e->usage = 13009 "Usage: dahdi show status\n" 13010 " Shows a list of DAHDI cards with status\n"; 13011 return NULL; 13012 case CLI_GENERATE: 13013 return NULL; 13014 } 13015 ctl = open("/dev/dahdi/ctl", O_RDWR); 13016 if (ctl < 0) { 13017 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno)); 13018 return CLI_FAILURE; 13019 } 13020 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO"); 13021 13022 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 13023 s.spanno = span; 13024 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 13025 if (res) { 13026 continue; 13027 } 13028 alarmstr[0] = '\0'; 13029 if (s.alarms > 0) { 13030 if (s.alarms & DAHDI_ALARM_BLUE) 13031 strcat(alarmstr, "BLU/"); 13032 if (s.alarms & DAHDI_ALARM_YELLOW) 13033 strcat(alarmstr, "YEL/"); 13034 if (s.alarms & DAHDI_ALARM_RED) 13035 strcat(alarmstr, "RED/"); 13036 if (s.alarms & DAHDI_ALARM_LOOPBACK) 13037 strcat(alarmstr, "LB/"); 13038 if (s.alarms & DAHDI_ALARM_RECOVER) 13039 strcat(alarmstr, "REC/"); 13040 if (s.alarms & DAHDI_ALARM_NOTOPEN) 13041 strcat(alarmstr, "NOP/"); 13042 if (!strlen(alarmstr)) 13043 strcat(alarmstr, "UUU/"); 13044 if (strlen(alarmstr)) { 13045 /* Strip trailing / */ 13046 alarmstr[strlen(alarmstr) - 1] = '\0'; 13047 } 13048 } else { 13049 if (s.numchans) 13050 strcpy(alarmstr, "OK"); 13051 else 13052 strcpy(alarmstr, "UNCONFIGURED"); 13053 } 13054 13055 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count 13056 , s.lineconfig & DAHDI_CONFIG_D4 ? "D4" : 13057 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" : 13058 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" : 13059 "CAS" 13060 , s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" : 13061 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" : 13062 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" : 13063 "Unk" 13064 , s.lineconfig & DAHDI_CONFIG_CRC4 ? 13065 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL" 13066 , lbostr[s.lbo] 13067 ); 13068 } 13069 close(ctl); 13070 13071 return CLI_SUCCESS; 13072 #undef FORMAT 13073 #undef FORMAT2 13074 }
| static char* dahdi_show_version | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13076 of file chan_dahdi.c.
References ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, errno, ast_cli_args::fd, and ast_cli_entry::usage.
13077 { 13078 int pseudo_fd = -1; 13079 struct dahdi_versioninfo vi; 13080 13081 switch (cmd) { 13082 case CLI_INIT: 13083 e->command = "dahdi show version"; 13084 e->usage = 13085 "Usage: dahdi show version\n" 13086 " Shows the DAHDI version in use\n"; 13087 return NULL; 13088 case CLI_GENERATE: 13089 return NULL; 13090 } 13091 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) { 13092 ast_cli(a->fd, "Failed to open control file to get version.\n"); 13093 return CLI_SUCCESS; 13094 } 13095 13096 strcpy(vi.version, "Unknown"); 13097 strcpy(vi.echo_canceller, "Unknown"); 13098 13099 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) 13100 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno)); 13101 else 13102 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller); 13103 13104 close(pseudo_fd); 13105 13106 return CLI_SUCCESS; 13107 }
| static char* dahdi_sig2str | ( | int | sig | ) | [static] |
Definition at line 1754 of file chan_dahdi.c.
References buf, SIG_BRI, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, and SIG_SS7.
01755 { 01756 static char buf[256]; 01757 switch (sig) { 01758 case SIG_EM: 01759 return "E & M Immediate"; 01760 case SIG_EMWINK: 01761 return "E & M Wink"; 01762 case SIG_EM_E1: 01763 return "E & M E1"; 01764 case SIG_FEATD: 01765 return "Feature Group D (DTMF)"; 01766 case SIG_FEATDMF: 01767 return "Feature Group D (MF)"; 01768 case SIG_FEATDMF_TA: 01769 return "Feature Groud D (MF) Tandem Access"; 01770 case SIG_FEATB: 01771 return "Feature Group B (MF)"; 01772 case SIG_E911: 01773 return "E911 (MF)"; 01774 case SIG_FGC_CAMA: 01775 return "FGC/CAMA (Dialpulse)"; 01776 case SIG_FGC_CAMAMF: 01777 return "FGC/CAMA (MF)"; 01778 case SIG_FXSLS: 01779 return "FXS Loopstart"; 01780 case SIG_FXSGS: 01781 return "FXS Groundstart"; 01782 case SIG_FXSKS: 01783 return "FXS Kewlstart"; 01784 case SIG_FXOLS: 01785 return "FXO Loopstart"; 01786 case SIG_FXOGS: 01787 return "FXO Groundstart"; 01788 case SIG_FXOKS: 01789 return "FXO Kewlstart"; 01790 case SIG_PRI: 01791 return "ISDN PRI"; 01792 case SIG_BRI: 01793 return "ISDN BRI Point to Point"; 01794 case SIG_BRI_PTMP: 01795 return "ISDN BRI Point to MultiPoint"; 01796 case SIG_SS7: 01797 return "SS7"; 01798 case SIG_SF: 01799 return "SF (Tone) Immediate"; 01800 case SIG_SFWINK: 01801 return "SF (Tone) Wink"; 01802 case SIG_SF_FEATD: 01803 return "SF (Tone) with Feature Group D (DTMF)"; 01804 case SIG_SF_FEATDMF: 01805 return "SF (Tone) with Feature Group D (MF)"; 01806 case SIG_SF_FEATB: 01807 return "SF (Tone) with Feature Group B (MF)"; 01808 case SIG_GR303FXOKS: 01809 return "GR-303 with FXOKS"; 01810 case SIG_GR303FXSKS: 01811 return "GR-303 with FXSKS"; 01812 case 0: 01813 return "Pseudo"; 01814 default: 01815 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig); 01816 return buf; 01817 } 01818 }
| static void dahdi_softhangup_all | ( | void | ) | [static] |
Definition at line 12476 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, dahdi_pvt::next, option_debug, dahdi_pvt::owner, and dahdi_pvt::restartpending.
Referenced by dahdi_restart().
12477 { 12478 struct dahdi_pvt *p; 12479 retry: 12480 ast_mutex_lock(&iflock); 12481 for (p = iflist; p; p = p->next) { 12482 ast_mutex_lock(&p->lock); 12483 if (p->owner && !p->restartpending) { 12484 if (ast_channel_trylock(p->owner)) { 12485 if (option_debug > 2) 12486 ast_verbose("Avoiding deadlock\n"); 12487 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */ 12488 ast_mutex_unlock(&p->lock); 12489 ast_mutex_unlock(&iflock); 12490 goto retry; 12491 } 12492 if (option_debug > 2) 12493 ast_verbose("Softhanging up on %s\n", p->owner->name); 12494 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT); 12495 p->restartpending = 1; 12496 num_restart_pending++; 12497 ast_channel_unlock(p->owner); 12498 } 12499 ast_mutex_unlock(&p->lock); 12500 } 12501 ast_mutex_unlock(&iflock); 12502 }
| static void dahdi_ss7_error | ( | struct ss7 * | ss7, | |
| char * | s | |||
| ) | [static] |
Definition at line 10505 of file chan_dahdi.c.
References ast_log(), linksets, LOG_ERROR, and NUM_SPANS.
Referenced by dahdi_restart(), and load_module().
| static void dahdi_ss7_message | ( | struct ss7 * | ss7, | |
| char * | s | |||
| ) | [static] |
Definition at line 10490 of file chan_dahdi.c.
References ast_verbose, linksets, and NUM_SPANS.
Referenced by dahdi_restart(), and load_module().
10491 { 10492 #if 0 10493 int i; 10494 10495 for (i = 0; i < NUM_SPANS; i++) 10496 if (linksets[i].ss7 == ss7) 10497 break; 10498 10499 ast_verbose("[%d] %s", i+1, s); 10500 #else 10501 ast_verbose("%s", s); 10502 #endif 10503 }
| static void dahdi_train_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2036 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().
02037 { 02038 int x; 02039 int res; 02040 02041 if (p && p->echocanon && p->echotraining) { 02042 x = p->echotraining; 02043 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x); 02044 if (res) 02045 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno)); 02046 else 02047 ast_debug(1, "Engaged echo training on channel %d\n", p->channel); 02048 } else { 02049 ast_debug(1, "No echo training requested\n"); 02050 } 02051 }
| static void dahdi_unlink | ( | struct dahdi_pvt * | slave, | |
| struct dahdi_pvt * | master, | |||
| int | needlock | |||
| ) | [static] |
Definition at line 4031 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, MAX_SLAVES, dahdi_pvt::slaves, SUB_REAL, dahdi_pvt::subs, and update_conf().
Referenced by dahdi_bridge(), and dahdi_fixup().
04032 { 04033 /* Unlink a specific slave or all slaves/masters from a given master */ 04034 int x; 04035 int hasslaves; 04036 if (!master) 04037 return; 04038 if (needlock) { 04039 ast_mutex_lock(&master->lock); 04040 if (slave) { 04041 while (ast_mutex_trylock(&slave->lock)) { 04042 DEADLOCK_AVOIDANCE(&master->lock); 04043 } 04044 } 04045 } 04046 hasslaves = 0; 04047 for (x = 0; x < MAX_SLAVES; x++) { 04048 if (master->slaves[x]) { 04049 if (!slave || (master->slaves[x] == slave)) { 04050 /* Take slave out of the conference */ 04051 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel); 04052 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL); 04053 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL); 04054 master->slaves[x]->master = NULL; 04055 master->slaves[x] = NULL; 04056 } else 04057 hasslaves = 1; 04058 } 04059 if (!hasslaves) 04060 master->inconference = 0; 04061 } 04062 if (!slave) { 04063 if (master->master) { 04064 /* Take master out of the conference */ 04065 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL); 04066 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL); 04067 hasslaves = 0; 04068 for (x = 0; x < MAX_SLAVES; x++) { 04069 if (master->master->slaves[x] == master) 04070 master->master->slaves[x] = NULL; 04071 else if (master->master->slaves[x]) 04072 hasslaves = 1; 04073 } 04074 if (!hasslaves) 04075 master->master->inconference = 0; 04076 } 04077 master->master = NULL; 04078 } 04079 update_conf(master); 04080 if (needlock) { 04081 if (slave) 04082 ast_mutex_unlock(&slave->lock); 04083 ast_mutex_unlock(&master->lock); 04084 } 04085 }
| static int dahdi_wait_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition at line 312 of file chan_dahdi.c.
Referenced by ss_thread().
| static int dahdi_wink | ( | struct dahdi_pvt * | p, | |
| int | idx | |||
| ) | [static] |
Definition at line 6502 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by ss_thread().
06503 { 06504 int j; 06505 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK); 06506 for (;;) 06507 { 06508 /* set bits of interest */ 06509 j = DAHDI_IOMUX_SIGEVENT; 06510 /* wait for some happening */ 06511 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1); 06512 /* exit loop if we have it */ 06513 if (j & DAHDI_IOMUX_SIGEVENT) break; 06514 } 06515 /* get the event info */ 06516 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1); 06517 return 0; 06518 }
| static int dahdi_write | ( | struct ast_channel * | ast, | |
| struct ast_frame * | frame | |||
| ) | [static] |
Definition at line 5984 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(), 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.
05985 { 05986 struct dahdi_pvt *p = ast->tech_pvt; 05987 int res; 05988 int idx; 05989 idx = dahdi_get_index(ast, p, 0); 05990 if (idx < 0) { 05991 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name); 05992 return -1; 05993 } 05994 05995 #if 0 05996 #ifdef HAVE_PRI 05997 ast_mutex_lock(&p->lock); 05998 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { 05999 if (p->pri->pri) { 06000 if (!pri_grab(p, p->pri)) { 06001 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06002 pri_rel(p->pri); 06003 } else 06004 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06005 } 06006 p->proceeding=1; 06007 } 06008 ast_mutex_unlock(&p->lock); 06009 #endif 06010 #endif 06011 /* Write a frame of (presumably voice) data */ 06012 if (frame->frametype != AST_FRAME_VOICE) { 06013 if (frame->frametype != AST_FRAME_IMAGE) 06014 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); 06015 return 0; 06016 } 06017 if ((frame->subclass != AST_FORMAT_SLINEAR) && 06018 (frame->subclass != AST_FORMAT_ULAW) && 06019 (frame->subclass != AST_FORMAT_ALAW)) { 06020 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass); 06021 return -1; 06022 } 06023 if (p->dialing) { 06024 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name); 06025 return 0; 06026 } 06027 if (!p->owner) { 06028 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name); 06029 return 0; 06030 } 06031 if (p->cidspill) { 06032 ast_debug(1, "Dropping frame since I've still got a callerid spill\n"); 06033 return 0; 06034 } 06035 /* Return if it's not valid data */ 06036 if (!frame->data.ptr || !frame->datalen) 06037 return 0; 06038 06039 if (frame->subclass == AST_FORMAT_SLINEAR) { 06040 if (!p->subs[idx].linear) { 06041 p->subs[idx].linear = 1; 06042 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 06043 if (res) 06044 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel); 06045 } 06046 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1); 06047 } else { 06048 /* x-law already */ 06049 if (p->subs[idx].linear) { 06050 p->subs[idx].linear = 0; 06051 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 06052 if (res) 06053 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel); 06054 } 06055 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0); 06056 } 06057 if (res < 0) { 06058 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 06059 return -1; 06060 } 06061 return 0; 06062 }
| static void destroy_all_channels | ( | void | ) | [static] |
Definition at line 3215 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().
03216 { 03217 int x; 03218 struct dahdi_pvt *p, *pl; 03219 03220 while (num_restart_pending) { 03221 usleep(1); 03222 } 03223 03224 ast_mutex_lock(&iflock); 03225 /* Destroy all the interfaces and free their memory */ 03226 p = iflist; 03227 while (p) { 03228 /* Free any callerid */ 03229 if (p->cidspill) 03230 ast_free(p->cidspill); 03231 pl = p; 03232 p = p->next; 03233 x = pl->channel; 03234 /* Free associated memory */ 03235 if (pl) 03236 destroy_dahdi_pvt(&pl); 03237 if (option_verbose > 2) 03238 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x); 03239 } 03240 iflist = NULL; 03241 ifcount = 0; 03242 ast_mutex_unlock(&iflock); 03243 }
Definition at line 3165 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().
03166 { 03167 int owned = 0; 03168 int i = 0; 03169 03170 if (!now) { 03171 if (cur->owner) { 03172 owned = 1; 03173 } 03174 03175 for (i = 0; i < 3; i++) { 03176 if (cur->subs[i].owner) { 03177 owned = 1; 03178 } 03179 } 03180 if (!owned) { 03181 if (prev) { 03182 prev->next = cur->next; 03183 if (prev->next) 03184 prev->next->prev = prev; 03185 else 03186 ifend = prev; 03187 } else { 03188 iflist = cur->next; 03189 if (iflist) 03190 iflist->prev = NULL; 03191 else 03192 ifend = NULL; 03193 } 03194 destroy_dahdi_pvt(&cur); 03195 } 03196 } else { 03197 if (prev) { 03198 prev->next = cur->next; 03199 if (prev->next) 03200 prev->next->prev = prev; 03201 else 03202 ifend = prev; 03203 } else { 03204 iflist = cur->next; 03205 if (iflist) 03206 iflist->prev = NULL; 03207 else 03208 ifend = NULL; 03209 } 03210 destroy_dahdi_pvt(&cur); 03211 } 03212 return 0; 03213 }
| static void destroy_dahdi_pvt | ( | struct dahdi_pvt ** | pvt | ) | [static] |
Definition at line 3143 of file chan_dahdi.c.
References ast_event_unsubscribe(), ast_mutex_destroy(), ast_smdi_interface_unref(), ast_variables_destroy(), dahdi_close_sub(), free, dahdi_pvt::lock, dahdi_pvt::mwi_event_sub, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::prev, dahdi_pvt::smdi_iface, SUB_REAL, ast_channel::tech_pvt, dahdi_pvt::use_smdi, and dahdi_pvt::vars.
Referenced by chandup(), destroy_all_channels(), destroy_channel(), and mkintf().
03144 { 03145 struct dahdi_pvt *p = *pvt; 03146 /* Remove channel from the list */ 03147 if (p->prev) 03148 p->prev->next = p->next; 03149 if (p->next) 03150 p->next->prev = p->prev; 03151 if (p->use_smdi) 03152 ast_smdi_interface_unref(p->smdi_iface); 03153 if (p->mwi_event_sub) 03154 ast_event_unsubscribe(p->mwi_event_sub); 03155 if (p->vars) 03156 ast_variables_destroy(p->vars); 03157 ast_mutex_destroy(&p->lock); 03158 dahdi_close_sub(p, SUB_REAL); 03159 if (p->owner) 03160 p->owner->tech_pvt = NULL; 03161 free(p); 03162 *pvt = NULL; 03163 }
| static char* dialplan2str | ( | int | dialplan | ) | [static] |
Definition at line 1745 of file chan_dahdi.c.
Referenced by dahdi_call(), and mkintf().
| static int digit_to_dtmfindex | ( | char | digit | ) | [static] |
Definition at line 1575 of file chan_dahdi.c.
Referenced by dahdi_digit_begin().
01576 { 01577 if (isdigit(digit)) 01578 return DAHDI_TONE_DTMF_BASE + (digit - '0'); 01579 else if (digit >= 'A' && digit <= 'D') 01580 return DAHDI_TONE_DTMF_A + (digit - 'A'); 01581 else if (digit >= 'a' && digit <= 'd') 01582 return DAHDI_TONE_DTMF_A + (digit - 'a'); 01583 else if (digit == '*') 01584 return DAHDI_TONE_DTMF_s; 01585 else if (digit == '#') 01586 return DAHDI_TONE_DTMF_p; 01587 else 01588 return -1; 01589 }
| static void disable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4110 of file chan_dahdi.c.
References ast_dsp_set_features(), dahdi_subchannel::dfd, dahdi_pvt::dsp, DSP_FEATURE_DIGIT_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::hardwaredtmf, dahdi_pvt::ignoredtmf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_bridge().
04111 { 04112 int val; 04113 04114 p->ignoredtmf = 1; 04115 04116 val = 0; 04117 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 04118 04119 if (!p->hardwaredtmf && p->dsp) { 04120 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT; 04121 ast_dsp_set_features(p->dsp, p->dsp_features); 04122 } 04123 }
| static void* do_idle_thread | ( | void * | vchan | ) | [static] |
Definition at line 10646 of file chan_dahdi.c.
References ast_call(), AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, ast_copy_string(), AST_FRAME_CONTROL, ast_frfree, ast_hangup(), ast_log(), ast_pbx_run(), ast_read(), ast_verb, ast_waitfor(), chan, dahdi_pvt::channel, ast_channel::context, ast_channel::exten, f, ast_frame::frametype, dahdi_pri::idlecontext, dahdi_pri::idledial, dahdi_pri::idleext, LOG_WARNING, dahdi_pvt::pri, ast_channel::priority, ast_frame::subclass, and ast_channel::tech_pvt.
Referenced by pri_dchannel().
10647 { 10648 struct ast_channel *chan = vchan; 10649 struct dahdi_pvt *pvt = chan->tech_pvt; 10650 struct ast_frame *f; 10651 char ex[80]; 10652 /* Wait up to 30 seconds for an answer */ 10653 int newms, ms = 30000; 10654 ast_verb(3, "Initiating idle call on channel %s\n", chan->name); 10655 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial); 10656 if (ast_call(chan, ex, 0)) { 10657 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex); 10658 ast_hangup(chan); 10659 return NULL; 10660 } 10661 while ((newms = ast_waitfor(chan, ms)) > 0) { 10662 f = ast_read(chan); 10663 if (!f) { 10664 /* Got hangup */ 10665 break; 10666 } 10667 if (f->frametype == AST_FRAME_CONTROL) { 10668 switch (f->subclass) { 10669 case AST_CONTROL_ANSWER: 10670 /* Launch the PBX */ 10671 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten)); 10672 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context)); 10673 chan->priority = 1; 10674 ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context); 10675 ast_pbx_run(chan); 10676 /* It's already hungup, return immediately */ 10677 return NULL; 10678 case AST_CONTROL_BUSY: 10679 ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name); 10680 break; 10681 case AST_CONTROL_CONGESTION: 10682 ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name); 10683 break; 10684 }; 10685 } 10686 ast_frfree(f); 10687 ms = newms; 10688 } 10689 /* Hangup the channel since nothing happend */ 10690 ast_hangup(chan); 10691 return NULL; 10692 }
| static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 8318 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, mwi_thread_data::buf, buf, calc_energy(), dahdi_pvt::channel, dahdi_pvt::cidspill, dahdi_get_event(), dahdi_subchannel::dfd, errno, event2str(), handle_init_event(), has_voicemail(), iflist, iflock, last, mwi_thread_data::len, LOG_DEBUG, LOG_WARNING, dahdi_pvt::msgstate, mwi_send_thread(), mwi_thread(), dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitoractive, dahdi_pvt::mwisendactive, dahdi_pvt::next, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pri, mwi_thread_data::pvt, dahdi_pvt::radio, dahdi_pvt::sig, SUB_REAL, and dahdi_pvt::subs.
Referenced by restart_monitor().
08319 { 08320 int count, res, res2, spoint, pollres=0; 08321 struct dahdi_pvt *i; 08322 struct dahdi_pvt *last = NULL; 08323 time_t thispass = 0, lastpass = 0; 08324 int found; 08325 char buf[1024]; 08326 struct pollfd *pfds=NULL; 08327 int lastalloc = -1; 08328 /* This thread monitors all the frame relay interfaces which are not yet in use 08329 (and thus do not have a separate thread) indefinitely */ 08330 /* From here on out, we die whenever asked */ 08331 #if 0 08332 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 08333 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 08334 return NULL; 08335 } 08336 ast_debug(1, "Monitor starting...\n"); 08337 #endif 08338 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08339 08340 for (;;) { 08341 /* Lock the interface list */ 08342 ast_mutex_lock(&iflock); 08343 if (!pfds || (lastalloc != ifcount)) { 08344 if (pfds) { 08345 ast_free(pfds); 08346 pfds = NULL; 08347 } 08348 if (ifcount) { 08349 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) { 08350 ast_mutex_unlock(&iflock); 08351 return NULL; 08352 } 08353 } 08354 lastalloc = ifcount; 08355 } 08356 /* Build the stuff we're going to poll on, that is the socket of every 08357 dahdi_pvt that does not have an associated owner channel */ 08358 count = 0; 08359 i = iflist; 08360 while (i) { 08361 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) { 08362 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive && !i->mwisendactive) { 08363 /* This needs to be watched, as it lacks an owner */ 08364 pfds[count].fd = i->subs[SUB_REAL].dfd; 08365 pfds[count].events = POLLPRI; 08366 pfds[count].revents = 0; 08367 /* If we are monitoring for VMWI or sending CID, we need to 08368 read from the channel as well */ 08369 if (i->cidspill || i->mwimonitor_fsk) 08370 pfds[count].events |= POLLIN; 08371 count++; 08372 } 08373 } 08374 i = i->next; 08375 } 08376 /* Okay, now that we know what to do, release the interface lock */ 08377 ast_mutex_unlock(&iflock); 08378 08379 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 08380 pthread_testcancel(); 08381 /* Wait at least a second for something to happen */ 08382 res = poll(pfds, count, 1000); 08383 pthread_testcancel(); 08384 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08385 08386 /* Okay, poll has finished. Let's see what happened. */ 08387 if (res < 0) { 08388 if ((errno != EAGAIN) && (errno != EINTR)) 08389 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno)); 08390 continue; 08391 } 08392 /* Alright, lock the interface list again, and let's look and see what has 08393 happened */ 08394 ast_mutex_lock(&iflock); 08395 found = 0; 08396 spoint = 0; 08397 lastpass = thispass; 08398 thispass = time(NULL); 08399 i = iflist; 08400 while (i) { 08401 if (thispass != lastpass) { 08402 if (!found && ((i == last) || ((i == iflist) && !last))) { 08403 last = i; 08404 if (last) { 08405 if (!last->mwisendactive && last->sig & __DAHDI_SIG_FXO) { 08406 res = has_voicemail(last); 08407 if (last->msgstate != res) { 08408 08409 /* This channel has a new voicemail state, 08410 * initiate a thread to send an MWI message 08411 */ 08412 pthread_attr_t attr; 08413 pthread_t threadid; 08414 struct mwi_thread_data *mtd; 08415 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res); 08416 if (res2) { 08417 /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */ 08418 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno)); 08419 } 08420 pthread_attr_init(&attr); 08421 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 08422 if ((mtd = ast_calloc(1, sizeof(*mtd)))) { 08423 last->msgstate = res; 08424 mtd->pvt = last; 08425 last->mwisendactive = 1; 08426 if (ast_pthread_create_background(&threadid, &attr, mwi_send_thread, mtd)) { 08427 ast_log(LOG_WARNING, "Unable to start mwi send thread on channel %d\n", last->channel); 08428 ast_free(mtd); 08429 last->mwisendactive = 0; 08430 } 08431 } 08432 found ++; 08433 } 08434 } 08435 last = last->next; 08436 } 08437 } 08438 } 08439 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) { 08440 if (i->radio && !i->owner) 08441 { 08442 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 08443 if (res) 08444 { 08445 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel); 08446 /* Don't hold iflock while handling init events */ 08447 ast_mutex_unlock(&iflock); 08448 handle_init_event(i, res); 08449 ast_mutex_lock(&iflock); 08450 } 08451 i = i->next; 08452 continue; 08453 } 08454 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint); 08455 if (pollres & POLLIN) { 08456 if (i->owner || i->subs[SUB_REAL].owner) { 08457 #ifdef HAVE_PRI 08458 if (!i->pri) 08459 #endif 08460 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd); 08461 i = i->next; 08462 continue; 08463 } 08464 if (!i->cidspill && !i->mwimonitor_fsk) { 08465 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd); 08466 i = i->next; 08467 continue; 08468 } 08469 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf)); 08470 if (res > 0) { 08471 if (i->mwimonitor_fsk) { 08472 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) { 08473 pthread_attr_t attr; 08474 pthread_t threadid; 08475 struct mwi_thread_data *mtd; 08476 08477 pthread_attr_init(&attr); 08478 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 08479 08480 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel); 08481 if ((mtd = ast_calloc(1, sizeof(*mtd)))) { 08482 mtd->pvt = i; 08483 memcpy(mtd->buf, buf, res); 08484 mtd->len = res; 08485 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) { 08486 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel); 08487 ast_free(mtd); 08488 } 08489 i->mwimonitoractive = 1; 08490 } 08491 } 08492 } 08493 } else { 08494 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno)); 08495 } 08496 } 08497 if (pollres & POLLPRI) { 08498 if (i->owner || i->subs[SUB_REAL].owner) { 08499 #ifdef HAVE_PRI 08500 if (!i->pri) 08501 #endif 08502 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd); 08503 i = i->next; 08504 continue; 08505 } 08506 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 08507 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel); 08508 /* Don't hold iflock while handling init events */ 08509 ast_mutex_unlock(&iflock); 08510 handle_init_event(i, res); 08511 ast_mutex_lock(&iflock); 08512 } 08513 } 08514 i=i->next; 08515 } 08516 ast_mutex_unlock(&iflock); 08517 } 08518 /* Never reached */ 08519 return NULL; 08520 08521 }
| static void enable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4125 of file chan_dahdi.c.
References ast_dsp_set_features(), CHAN_PSEUDO, dahdi_pvt::channel, dahdi_subchannel::dfd, dahdi_pvt::dsp, DSP_FEATURE_DIGIT_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::hardwaredtmf, dahdi_pvt::ignoredtmf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_bridge().
04126 { 04127 int val; 04128 04129 if (p->channel == CHAN_PSEUDO) 04130 return; 04131 04132 p->ignoredtmf = 0; 04133 04134 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 04135 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 04136 04137 if (!p->hardwaredtmf && p->dsp) { 04138 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT; 04139 ast_dsp_set_features(p->dsp, p->dsp_features); 04140 } 04141 }
| static char* event2str | ( | int | event | ) | [static] |
Definition at line 1735 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 2105 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_rxgain().
02106 { 02107 int j; 02108 int k; 02109 float linear_gain = pow(10.0, gain / 20.0); 02110 02111 switch (law) { 02112 case DAHDI_LAW_ALAW: 02113 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 02114 if (gain) { 02115 k = (int) (((float) AST_ALAW(j)) * linear_gain); 02116 if (k > 32767) k = 32767; 02117 if (k < -32767) k = -32767; 02118 g->rxgain[j] = AST_LIN2A(k); 02119 } else { 02120 g->rxgain[j] = j; 02121 } 02122 } 02123 break; 02124 case DAHDI_LAW_MULAW: 02125 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 02126 if (gain) { 02127 k = (int) (((float) AST_MULAW(j)) * linear_gain); 02128 if (k > 32767) k = 32767; 02129 if (k < -32767) k = -32767; 02130 g->rxgain[j] = AST_LIN2MU(k); 02131 } else { 02132 g->rxgain[j] = j; 02133 } 02134 } 02135 break; 02136 } 02137 }
| static void fill_txgain | ( | struct dahdi_gains * | g, | |
| float | gain, | |||
| int | law | |||
| ) | [static] |
Definition at line 2071 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_txgain().
02072 { 02073 int j; 02074 int k; 02075 float linear_gain = pow(10.0, gain / 20.0); 02076 02077 switch (law) { 02078 case DAHDI_LAW_ALAW: 02079 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 02080 if (gain) { 02081 k = (int) (((float) AST_ALAW(j)) * linear_gain); 02082 if (k > 32767) k = 32767; 02083 if (k < -32767) k = -32767; 02084 g->txgain[j] = AST_LIN2A(k); 02085 } else { 02086 g->txgain[j] = j; 02087 } 02088 } 02089 break; 02090 case DAHDI_LAW_MULAW: 02091 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 02092 if (gain) { 02093 k = (int) (((float) AST_MULAW(j)) * linear_gain); 02094 if (k > 32767) k = 32767; 02095 if (k < -32767) k = -32767; 02096 g->txgain[j] = AST_LIN2MU(k); 02097 } else { 02098 g->txgain[j] = j; 02099 } 02100 } 02101 break; 02102 } 02103 }
| static struct dahdi_pvt* find_channel | ( | int | channel | ) | [static, read] |
Definition at line 13341 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 4569 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().
04570 { 04571 int res; 04572 struct dahdi_spaninfo zi; 04573 struct dahdi_params params; 04574 04575 memset(&zi, 0, sizeof(zi)); 04576 zi.spanno = p->span; 04577 04578 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) { 04579 if (zi.alarms != DAHDI_ALARM_NONE) 04580 return zi.alarms; 04581 } else { 04582 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno)); 04583 return 0; 04584 } 04585 04586 /* No alarms on the span. Check for channel alarms. */ 04587 memset(¶ms, 0, sizeof(params)); 04588 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0) 04589 return params.chan_alarms; 04590 04591 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel); 04592 04593 return DAHDI_ALARM_NONE; 04594 }
| static void handle_alarms | ( | struct dahdi_pvt * | p, | |
| int | alms | |||
| ) | [static] |
Definition at line 4662 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().
04663 { 04664 const char *alarm_str = alarm2str(alms); 04665 04666 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); 04667 manager_event(EVENT_FLAG_SYSTEM, "Alarm", 04668 "Alarm: %s\r\n" 04669 "Channel: %d\r\n", 04670 alarm_str, p->channel); 04671 }
| static char* handle_dahdi_show_cadences | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12957 of file chan_dahdi.c.
References ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, COLOR_BLACK, COLOR_GREEN, COLOR_MAGENTA, ast_cli_entry::command, ast_cli_args::fd, term_color(), and ast_cli_entry::usage.
12958 { 12959 int i, j; 12960 switch (cmd) { 12961 case CLI_INIT: 12962 e->command = "dahdi show cadences"; 12963 e->usage = 12964 "Usage: dahdi show cadences\n" 12965 " Shows all cadences currently defined\n"; 12966 return NULL; 12967 case CLI_GENERATE: 12968 return NULL; 12969 } 12970 for (i = 0; i < num_cadence; i++) { 12971 char output[1024]; 12972 char tmp[16], tmp2[64]; 12973 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1); 12974 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output)); 12975 12976 for (j = 0; j < 16; j++) { 12977 if (cadences[i].ringcadence[j] == 0) 12978 break; 12979 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]); 12980 if (cidrings[i] * 2 - 1 == j) 12981 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1); 12982 else 12983 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1); 12984 if (j != 0) 12985 strncat(output, ",", sizeof(output) - strlen(output) - 1); 12986 strncat(output, tmp2, sizeof(output) - strlen(output) - 1); 12987 } 12988 ast_cli(a->fd,"%s\n",output); 12989 } 12990 return CLI_SUCCESS; 12991 }
| static int handle_init_event | ( | struct dahdi_pvt * | i, | |
| int | event | |||
| ) | [static] |
Definition at line 8087 of file chan_dahdi.c.
References ast_free, ast_hangup(), ast_log(), ast_pthread_create_detached, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, ast_verb, chan, dahdi_pvt::channel, dahdi_pvt::cid_start, CID_START_POLARITY, CID_START_POLARITY_IN, dahdi_pvt::cidspill, dahdi_destroy_channel_bynum(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_new(), dahdi_set_hook(), dahdi_subchannel::dfd, errno, EVENT_FLAG_SYSTEM, 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, POLARITY_REV, dahdi_pvt::radio, dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, sig2str, SIG_BRI, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, ss_thread(), SUB_REAL, and dahdi_pvt::subs.
Referenced by do_monitor(), and mwi_send_thread().
08088 { 08089 int res; 08090 int thread_spawned = 0; 08091 pthread_t threadid; 08092 struct ast_channel *chan; 08093 08094 /* Handle an event on a given channel for the monitor thread. */ 08095 08096 switch (event) { 08097 case DAHDI_EVENT_NONE: 08098 case DAHDI_EVENT_BITSCHANGED: 08099 break; 08100 case DAHDI_EVENT_WINKFLASH: 08101 case DAHDI_EVENT_RINGOFFHOOK: 08102 if (i->inalarm) break; 08103 if (i->radio) break; 08104 /* Got a ring/answer. What kind of channel are we? */ 08105 switch (i->sig) { 08106 case SIG_FXOLS: 08107 case SIG_FXOGS: 08108 case SIG_FXOKS: 08109 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08110 if (res && (errno == EBUSY)) 08111 break; 08112 if (i->cidspill) { 08113 /* Cancel VMWI spill */ 08114 ast_free(i->cidspill); 08115 i->cidspill = NULL; 08116 } 08117 if (i->immediate) { 08118 dahdi_enable_ec(i); 08119 /* The channel is immediately up. Start right away */ 08120 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 08121 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0); 08122 if (!chan) { 08123 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel); 08124 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08125 if (res < 0) 08126 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08127 } 08128 } else { 08129 /* Check for callerid, digits, etc */ 08130 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0); 08131 if (chan) { 08132 if (has_voicemail(i)) 08133 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 08134 else 08135 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 08136 if (res < 0) 08137 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel); 08138 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 08139 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08140 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08141 if (res < 0) 08142 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08143 ast_hangup(chan); 08144 } else { 08145 thread_spawned = 1; 08146 } 08147 } else 08148 ast_log(LOG_WARNING, "Unable to create channel\n"); 08149 } 08150 break; 08151 case SIG_FXSLS: 08152 case SIG_FXSGS: 08153 case SIG_FXSKS: 08154 i->ringt = i->ringt_base; 08155 /* Fall through */ 08156 case SIG_EMWINK: 08157 case SIG_FEATD: 08158 case SIG_FEATDMF: 08159 case SIG_FEATDMF_TA: 08160 case SIG_E911: 08161 case SIG_FGC_CAMA: 08162 case SIG_FGC_CAMAMF: 08163 case SIG_FEATB: 08164 case SIG_EM: 08165 case SIG_EM_E1: 08166 case SIG_SFWINK: 08167 case SIG_SF_FEATD: 08168 case SIG_SF_FEATDMF: 08169 case SIG_SF_FEATB: 08170 case SIG_SF: 08171 /* Check for callerid, digits, etc */ 08172 if (i->cid_start == CID_START_POLARITY_IN) { 08173 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 08174 } else { 08175 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0); 08176 } 08177 08178 if (!chan) { 08179 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 08180 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 08181 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08182 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08183 if (res < 0) { 08184 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08185 } 08186 ast_hangup(chan); 08187 } else { 08188 thread_spawned = 1; 08189 } 08190 break; 08191 default: 08192 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 08193 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08194 if (res < 0) 08195 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08196 return -1; 08197 } 08198 break; 08199 case DAHDI_EVENT_NOALARM: 08200 i->inalarm = 0; 08201 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel); 08202 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 08203 "Channel: %d\r\n", i->channel); 08204 break; 08205 case DAHDI_EVENT_ALARM: 08206 i->inalarm = 1; 08207 res = get_alarms(i); 08208 handle_alarms(i, res); 08209 /* fall thru intentionally */ 08210 case DAHDI_EVENT_ONHOOK: 08211 if (i->radio) 08212 break; 08213 /* Back on hook. Hang up. */ 08214 switch (i->sig) { 08215 case SIG_FXOLS: 08216 case SIG_FXOGS: 08217 case SIG_FEATD: 08218 case SIG_FEATDMF: 08219 case SIG_FEATDMF_TA: 08220 case SIG_E911: 08221 case SIG_FGC_CAMA: 08222 case SIG_FGC_CAMAMF: 08223 case SIG_FEATB: 08224 case SIG_EM: 08225 case SIG_EM_E1: 08226 case SIG_EMWINK: 08227 case SIG_SF_FEATD: 08228 case SIG_SF_FEATDMF: 08229 case SIG_SF_FEATB: 08230 case SIG_SF: 08231 case SIG_SFWINK: 08232 case SIG_FXSLS: 08233 case SIG_FXSGS: 08234 case SIG_FXSKS: 08235 case SIG_GR303FXSKS: 08236 dahdi_disable_ec(i); 08237 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08238 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08239 break; 08240 case SIG_GR303FXOKS: 08241 case SIG_FXOKS: 08242 dahdi_disable_ec(i); 08243 /* Diddle the battery for the zhone */ 08244 #ifdef ZHONE_HACK 08245 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08246 usleep(1); 08247 #endif 08248 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08249 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08250 break; 08251 case SIG_PRI: 08252 case SIG_SS7: 08253 case SIG_BRI: 08254 case SIG_BRI_PTMP: 08255 dahdi_disable_ec(i); 08256 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08257 break; 08258 default: 08259 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 08260 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08261 return -1; 08262 } 08263 break; 08264 case DAHDI_EVENT_POLARITY: 08265 switch (i->sig) { 08266 case SIG_FXSLS: 08267 case SIG_FXSKS: 08268 case SIG_FXSGS: 08269 /* We have already got a PR before the channel was 08270 created, but it wasn't handled. We need polarity 08271 to be REV for remote hangup detection to work. 08272 At least in Spain */ 08273 if (i->hanguponpolarityswitch) 08274 i->polarity = POLARITY_REV; 08275 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) { 08276 i->polarity = POLARITY_REV; 08277 ast_verb(2, "Starting post polarity " 08278 "CID detection on channel %d\n", 08279 i->channel); 08280 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 08281 if (!chan) { 08282 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 08283 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 08284 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08285 } else { 08286 thread_spawned = 1; 08287 } 08288 } 08289 break; 08290 default: 08291 ast_log(LOG_WARNING, "handle_init_event detected " 08292 "polarity reversal on non-FXO (SIG_FXS) " 08293 "interface %d\n", i->channel); 08294 } 08295 break; 08296 case DAHDI_EVENT_REMOVED: /* destroy channel */ 08297 ast_log(LOG_NOTICE, 08298 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 08299 i->channel); 08300 dahdi_destroy_channel_bynum(i->channel); 08301 break; 08302 case DAHDI_EVENT_NEONMWI_ACTIVE: 08303 if (i->mwimonitor_neon) { 08304 notify_message(i->mailbox, 1); 08305 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox); 08306 } 08307 break; 08308 case DAHDI_EVENT_NEONMWI_INACTIVE: 08309 if (i->mwimonitor_neon) { 08310 notify_message(i->mailbox, 0); 08311 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox); 08312 } 08313 break; 08314 } 08315 return thread_spawned; 08316 }
| static char* handle_pri_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12169 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_span_4(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, NUM_SPANS, ast_cli_args::pos, pris, ast_cli_entry::usage, and ast_cli_args::word.
12170 { 12171 int span; 12172 int x; 12173 switch (cmd) { 12174 case CLI_INIT: 12175 e->command = "pri debug span"; 12176 e->usage = 12177 "Usage: pri debug span <span>\n" 12178 " Enables debugging on a given PRI span\n"; 12179 return NULL; 12180 case CLI_GENERATE: 12181 return complete_span_4(a->line, a->word, a->pos, a->n); 12182 } 12183 if (a->argc < 4) { 12184 return CLI_SHOWUSAGE; 12185 } 12186 span = atoi(a->argv[3]); 12187 if ((span < 1) || (span > NUM_SPANS)) { 12188 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 12189 return CLI_SUCCESS; 12190 } 12191 if (!pris[span-1].pri) { 12192 ast_cli(a->fd, "No PRI running on span %d\n", span); 12193 return CLI_SUCCESS; 12194 } 12195 for (x = 0; x < NUM_DCHANS; x++) { 12196 if (pris[span-1].dchans[x]) 12197 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 12198 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 12199 PRI_DEBUG_Q921_STATE); 12200 } 12201 ast_cli(a->fd, "Enabled debugging on span %d\n", span); 12202 return CLI_SUCCESS; 12203 }
| static char* handle_pri_no_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12207 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_span_5(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, NUM_SPANS, ast_cli_args::pos, pris, ast_cli_entry::usage, and ast_cli_args::word.
12208 { 12209 int span; 12210 int x; 12211 switch (cmd) { 12212 case CLI_INIT: 12213 e->command = "pri no debug span"; 12214 e->usage = 12215 "Usage: pri no debug span <span>\n" 12216 " Disables debugging on a given PRI span\n"; 12217 return NULL; 12218 case CLI_GENERATE: 12219 return complete_span_5(a->line, a->word, a->pos, a->n); 12220 } 12221 if (a->argc < 5) 12222 return CLI_SHOWUSAGE; 12223 12224 span = atoi(a->argv[4]); 12225 if ((span < 1) || (span > NUM_SPANS)) { 12226 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS); 12227 return CLI_SUCCESS; 12228 } 12229 if (!pris[span-1].pri) { 12230 ast_cli(a->fd, "No PRI running on span %d\n", span); 12231 return CLI_SUCCESS; 12232 } 12233 for (x = 0; x < NUM_DCHANS; x++) { 12234 if (pris[span-1].dchans[x]) 12235 pri_set_debug(pris[span-1].dchans[x], 0); 12236 } 12237 ast_cli(a->fd, "Disabled debugging on span %d\n", span); 12238 return CLI_SUCCESS; 12239 }
| static char* handle_pri_really_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12241 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_span_5(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, NUM_SPANS, ast_cli_args::pos, pris, ast_cli_entry::usage, and ast_cli_args::word.
12242 { 12243 int span; 12244 int x; 12245 switch (cmd) { 12246 case CLI_INIT: 12247 e->command = "pri intensive debug span"; 12248 e->usage = 12249 "Usage: pri intensive debug span <span>\n" 12250 " Enables debugging down to the Q.921 level\n"; 12251 return NULL; 12252 case CLI_GENERATE: 12253 return complete_span_5(a->line, a->word, a->pos, a->n); 12254 } 12255 12256 if (a->argc < 5) 12257 return CLI_SHOWUSAGE; 12258 span = atoi(a->argv[4]); 12259 if ((span < 1) || (span > NUM_SPANS)) { 12260 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS); 12261 return CLI_SUCCESS; 12262 } 12263 if (!pris[span-1].pri) { 12264 ast_cli(a->fd, "No PRI running on span %d\n", span); 12265 return CLI_SUCCESS; 12266 } 12267 for (x = 0; x < NUM_DCHANS; x++) { 12268 if (pris[span-1].dchans[x]) 12269 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 12270 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 12271 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE); 12272 } 12273 ast_cli(a->fd, "Enabled EXTENSIVE debugging on span %d\n", span); 12274 return CLI_SUCCESS; 12275 }
| static char* handle_pri_set_debug_file | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12133 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), AST_FILE_MODE, ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, pridebugfdlock, and ast_cli_entry::usage.
12134 { 12135 int myfd; 12136 switch (cmd) { 12137 case CLI_INIT: 12138 e->command = "pri set debug file"; 12139 e->usage = "Usage: pri set debug file [output-file]\n" 12140 " Sends PRI debug output to the specified output file\n"; 12141 return NULL; 12142 case CLI_GENERATE: 12143 return NULL; 12144 } 12145 if (a->argc < 5) 12146 return CLI_SHOWUSAGE; 12147 12148 if (ast_strlen_zero(a->argv[4])) 12149 return CLI_SHOWUSAGE; 12150 12151 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE); 12152 if (myfd < 0) { 12153 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]); 12154 return CLI_SUCCESS; 12155 } 12156 12157 ast_mutex_lock(&pridebugfdlock); 12158 12159 if (pridebugfd >= 0) 12160 close(pridebugfd); 12161 12162 pridebugfd = myfd; 12163 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename)); 12164 ast_mutex_unlock(&pridebugfdlock); 12165 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]); 12166 return CLI_SUCCESS; 12167 }
| static char* handle_pri_show_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12381 of file chan_dahdi.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, debug, ast_cli_args::fd, NUM_SPANS, pridebugfdlock, pris, and ast_cli_entry::usage.
12382 { 12383 int x; 12384 int span; 12385 int count=0; 12386 int debug=0; 12387 12388 switch (cmd) { 12389 case CLI_INIT: 12390 e->command = "pri show debug"; 12391 e->usage = 12392 "Usage: pri show debug\n" 12393 " Show the debug state of pri spans\n"; 12394 return NULL; 12395 case CLI_GENERATE: 12396 return NULL; 12397 } 12398 12399 for (span = 0; span < NUM_SPANS; span++) { 12400 if (pris[span].pri) { 12401 for (x = 0; x < NUM_DCHANS; x++) { 12402 debug = 0; 12403 if (pris[span].dchans[x]) { 12404 debug = pri_get_debug(pris[span].dchans[x]); 12405 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" ); 12406 count++; 12407 } 12408 } 12409 } 12410 12411 } 12412 ast_mutex_lock(&pridebugfdlock); 12413 if (pridebugfd >= 0) 12414 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename); 12415 ast_mutex_unlock(&pridebugfdlock); 12416 12417 if (!count) 12418 ast_cli(a->fd, "No debug set or no PRI running\n"); 12419 return CLI_SUCCESS; 12420 }
| static char* handle_pri_show_span | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12331 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_free, build_status(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_span_4(), DAHDI_OVERLAPDIAL_INCOMING, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, NUM_SPANS, dahdi_pri::overlapdial, ast_cli_args::pos, pri_order(), pris, status, ast_cli_entry::usage, and ast_cli_args::word.
12332 { 12333 int span; 12334 int x; 12335 char status[256]; 12336 switch (cmd) { 12337 case CLI_INIT: 12338 e->command = "pri show span"; 12339 e->usage = 12340 "Usage: pri show span <span>\n" 12341 " Displays PRI Information on a given PRI span\n"; 12342 return NULL; 12343 case CLI_GENERATE: 12344 return complete_span_4(a->line, a->word, a->pos, a->n); 12345 } 12346 12347 if (a->argc < 4) 12348 return CLI_SHOWUSAGE; 12349 span = atoi(a->argv[3]); 12350 if ((span < 1) || (span > NUM_SPANS)) { 12351 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS); 12352 return CLI_SUCCESS; 12353 } 12354 if (!pris[span-1].pri) { 12355 ast_cli(a->fd, "No PRI running on span %d\n", span); 12356 return CLI_SUCCESS; 12357 } 12358 for (x = 0; x < NUM_DCHANS; x++) { 12359 if (pris[span-1].dchannels[x]) { 12360 #ifdef PRI_DUMP_INFO_STR 12361 char *info_str = NULL; 12362 #endif 12363 ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]); 12364 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri); 12365 ast_cli(a->fd, "Status: %s\n", status); 12366 #ifdef PRI_DUMP_INFO_STR 12367 info_str = pri_dump_info_str(pris[span-1].pri); 12368 if (info_str) { 12369 ast_cli(a->fd, "%s", info_str); 12370 ast_free(info_str); 12371 } 12372 #else 12373 pri_dump_info(pris[span-1].pri); 12374 #endif 12375 ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No"); 12376 } 12377 } 12378 return CLI_SUCCESS; 12379 }
| static char* handle_pri_show_spans | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12298 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli(), build_status(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, NUM_SPANS, pris, status, and ast_cli_entry::usage.
12299 { 12300 int span; 12301 int x; 12302 char status[256]; 12303 12304 switch (cmd) { 12305 case CLI_INIT: 12306 e->command = "pri show spans"; 12307 e->usage = 12308 "Usage: pri show spans\n" 12309 " Displays PRI Information\n"; 12310 return NULL; 12311 case CLI_GENERATE: 12312 return NULL; 12313 } 12314 12315 if (a->argc != 3) 12316 return CLI_SHOWUSAGE; 12317 12318 for (span = 0; span < NUM_SPANS; span++) { 12319 if (pris[span].pri) { 12320 for (x = 0; x < NUM_DCHANS; x++) { 12321 if (pris[span].dchannels[x]) { 12322 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri); 12323 ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status); 12324 } 12325 } 12326 } 12327 } 12328 return CLI_SUCCESS; 12329 }
| static char* handle_pri_unset_debug_file | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12112 of file chan_dahdi.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, pridebugfdlock, and ast_cli_entry::usage.
12113 { 12114 switch (cmd) { 12115 case CLI_INIT: 12116 e->command = "pri unset debug file"; 12117 e->usage = "Usage: pri unset debug file\n" 12118 " Stop sending debug output to the previously \n" 12119 " specified file\n"; 12120 return NULL; 12121 case CLI_GENERATE: 12122 return NULL; 12123 } 12124 /* Assume it is unset */ 12125 ast_mutex_lock(&pridebugfdlock); 12126 close(pridebugfd); 12127 pridebugfd = -1; 12128 ast_cli(a->fd, "PRI debug output to file disabled\n"); 12129 ast_mutex_unlock(&pridebugfdlock); 12130 return CLI_SUCCESS; 12131 }
| static char* handle_pri_version | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12422 of file chan_dahdi.c.
References ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
12423 { 12424 switch (cmd) { 12425 case CLI_INIT: 12426 e->command = "pri show version"; 12427 e->usage = 12428 "Usage: pri show version\n" 12429 "Show libpri version information\n"; 12430 return NULL; 12431 case CLI_GENERATE: 12432 return NULL; 12433 } 12434 12435 ast_cli(a->fd, "libpri version: %s\n", pri_get_version()); 12436 12437 return CLI_SUCCESS; 12438 }
| static char* handle_ss7_block_cic | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13730 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, CLI_SHOWUSAGE, CLI_SUCCESS, 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.
13731 { 13732 int linkset, cic; 13733 int blocked = -1, i; 13734 switch (cmd) { 13735 case CLI_INIT: 13736 e->command = "ss7 block cic"; 13737 e->usage = 13738 "Usage: ss7 block cic <linkset> <CIC>\n" 13739 " Sends a remote blocking request for the given CIC on the specified linkset\n"; 13740 return NULL; 13741 case CLI_GENERATE: 13742 return NULL; 13743 } 13744 if (a->argc == 5) 13745 linkset = atoi(a->argv[3]); 13746 else 13747 return CLI_SHOWUSAGE; 13748 13749 if ((linkset < 1) || (linkset > NUM_SPANS)) { 13750 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 13751 return CLI_SUCCESS; 13752 } 13753 13754 if (!linksets[linkset-1].ss7) { 13755 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset); 13756 return CLI_SUCCESS; 13757 } 13758 13759 cic = atoi(a->argv[4]); 13760 13761 if (cic < 1) { 13762 ast_cli(a->fd, "Invalid CIC specified!\n"); 13763 return CLI_SUCCESS; 13764 } 13765 13766 for (i = 0; i < linksets[linkset-1].numchans; i++) { 13767 if (linksets[linkset-1].pvts[i]->cic == cic) { 13768 blocked = linksets[linkset-1].pvts[i]->locallyblocked; 13769 if (!blocked) { 13770 ast_mutex_lock(&linksets[linkset-1].lock); 13771 isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc); 13772 ast_mutex_unlock(&linksets[linkset-1].lock); 13773 } 13774 } 13775 } 13776 13777 if (blocked < 0) { 13778 ast_cli(a->fd, "Invalid CIC specified!\n"); 13779 return CLI_SUCCESS; 13780 } 13781 13782 if (!blocked) 13783 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic); 13784 else 13785 ast_cli(a->fd, "CIC %d already locally blocked\n", cic); 13786 13787 /* Break poll on the linkset so it sends our messages */ 13788 pthread_kill(linksets[linkset-1].master, SIGURG); 13789 13790 return CLI_SUCCESS; 13791 }
| static char* handle_ss7_block_linkset | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13793 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, CLI_SHOWUSAGE, CLI_SUCCESS, 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.
13794 { 13795 int linkset; 13796 int i; 13797 switch (cmd) { 13798 case CLI_INIT: 13799 e->command = "ss7 block linkset"; 13800 e->usage = 13801 "Usage: ss7 block linkset <linkset number>\n" 13802 " Sends a remote blocking request for all CICs on the given linkset\n"; 13803 return NULL; 13804 case CLI_GENERATE: 13805 return NULL; 13806 } 13807 if (a->argc == 4) 13808 linkset = atoi(a->argv[3]); 13809 else 13810 return CLI_SHOWUSAGE; 13811 13812 if ((linkset < 1) || (linkset > NUM_SPANS)) { 13813 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 13814 return CLI_SUCCESS; 13815 } 13816 13817 if (!linksets[linkset-1].ss7) { 13818 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset); 13819 return CLI_SUCCESS; 13820 } 13821 13822 for (i = 0; i < linksets[linkset-1].numchans; i++) { 13823 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic); 13824 ast_mutex_lock(&linksets[linkset-1].lock); 13825 isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc); 13826 ast_mutex_unlock(&linksets[linkset-1].lock); 13827 } 13828 13829 /* Break poll on the linkset so it sends our messages */ 13830 pthread_kill(linksets[linkset-1].master, SIGURG); 13831 13832 return CLI_SUCCESS; 13833 }
| static char* handle_ss7_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13699 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, linksets, NUM_SPANS, and ast_cli_entry::usage.
13700 { 13701 int span; 13702 switch (cmd) { 13703 case CLI_INIT: 13704 e->command = "ss7 debug linkset"; 13705 e->usage = 13706 "Usage: ss7 debug linkset <linkset>\n" 13707 " Enables debugging on a given SS7 linkset\n"; 13708 return NULL; 13709 case CLI_GENERATE: 13710 return NULL; 13711 } 13712 if (a->argc < 4) 13713 return CLI_SHOWUSAGE; 13714 span = atoi(a->argv[3]); 13715 if ((span < 1) || (span > NUM_SPANS)) { 13716 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS); 13717 return CLI_SUCCESS; 13718 } 13719 if (!linksets[span-1].ss7) { 13720 ast_cli(a->fd, "No SS7 running on linkset %d\n", span); 13721 return CLI_SUCCESS; 13722 } 13723 if (linksets[span-1].ss7) 13724 ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP); 13725 13726 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span); 13727 return CLI_SUCCESS; 13728 }
| static char* handle_ss7_no_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13668 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, linksets, NUM_SPANS, and ast_cli_entry::usage.
13669 { 13670 int span; 13671 switch (cmd) { 13672 case CLI_INIT: 13673 e->command = "ss7 no debug linkset"; 13674 e->usage = 13675 "Usage: ss7 no debug linkset <span>\n" 13676 " Disables debugging on a given SS7 linkset\n"; 13677 return NULL; 13678 case CLI_GENERATE: 13679 return NULL; 13680 } 13681 if (a->argc < 5) 13682 return CLI_SHOWUSAGE; 13683 span = atoi(a->argv[4]); 13684 if ((span < 1) || (span > NUM_SPANS)) { 13685 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[4], 1, NUM_SPANS); 13686 return CLI_SUCCESS; 13687 } 13688 if (!linksets[span-1].ss7) { 13689 ast_cli(a->fd, "No SS7 running on linkset %d\n", span); 13690 return CLI_SUCCESS; 13691 } 13692 if (linksets[span-1].ss7) 13693 ss7_set_debug(linksets[span-1].ss7, 0); 13694 13695 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span); 13696 return CLI_SUCCESS; 13697 }
| static char* handle_ss7_show_linkset | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13935 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, dahdi_ss7::LINKSET_STATE_UP, linksets, NUM_SPANS, dahdi_ss7::ss7, dahdi_ss7::state, and ast_cli_entry::usage.
13936 { 13937 int linkset; 13938 struct dahdi_ss7 *ss7; 13939 switch (cmd) { 13940 case CLI_INIT: 13941 e->command = "ss7 show linkset"; 13942 e->usage = 13943 "Usage: ss7 show linkset <span>\n" 13944 " Shows the status of an SS7 linkset.\n"; 13945 return NULL; 13946 case CLI_GENERATE: 13947 return NULL; 13948 } 13949 13950 if (a->argc < 4) 13951 return CLI_SHOWUSAGE; 13952 linkset = atoi(a->argv[3]); 13953 if ((linkset < 1) || (linkset > NUM_SPANS)) { 13954 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 13955 return CLI_SUCCESS; 13956 } 13957 if (!linksets[linkset-1].ss7) { 13958 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset); 13959 return CLI_SUCCESS; 13960 } 13961 if (linksets[linkset-1].ss7) 13962 ss7 = &linksets[linkset-1]; 13963 13964 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down"); 13965 13966 return CLI_SUCCESS; 13967 }
| static char* handle_ss7_unblock_cic | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13835 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, CLI_SHOWUSAGE, CLI_SUCCESS, 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.
13836 { 13837 int linkset, cic; 13838 int i, blocked = -1; 13839 switch (cmd) { 13840 case CLI_INIT: 13841 e->command = "ss7 unblock cic"; 13842 e->usage = 13843 "Usage: ss7 unblock cic <linkset> <CIC>\n" 13844 " Sends a remote unblocking request for the given CIC on the specified linkset\n"; 13845 return NULL; 13846 case CLI_GENERATE: 13847 return NULL; 13848 } 13849 13850 if (a->argc == 5) 13851 linkset = atoi(a->argv[3]); 13852 else 13853 return CLI_SHOWUSAGE; 13854 13855 if ((linkset < 1) || (linkset > NUM_SPANS)) { 13856 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 13857 return CLI_SUCCESS; 13858 } 13859 13860 if (!linksets[linkset-1].ss7) { 13861 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset); 13862 return CLI_SUCCESS; 13863 } 13864 13865 cic = atoi(a->argv[4]); 13866 13867 if (cic < 1) { 13868 ast_cli(a->fd, "Invalid CIC specified!\n"); 13869 return CLI_SUCCESS; 13870 } 13871 13872 for (i = 0; i < linksets[linkset-1].numchans; i++) { 13873 if (linksets[linkset-1].pvts[i]->cic == cic) { 13874 blocked = linksets[linkset-1].pvts[i]->locallyblocked; 13875 if (blocked) { 13876 ast_mutex_lock(&linksets[linkset-1].lock); 13877 isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc); 13878 ast_mutex_unlock(&linksets[linkset-1].lock); 13879 } 13880 } 13881 } 13882 13883 if (blocked > 0) 13884 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic); 13885 13886 /* Break poll on the linkset so it sends our messages */ 13887 pthread_kill(linksets[linkset-1].master, SIGURG); 13888 13889 return CLI_SUCCESS; 13890 }
| static char* handle_ss7_unblock_linkset | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13892 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, CLI_SHOWUSAGE, CLI_SUCCESS, 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.
13893 { 13894 int linkset; 13895 int i; 13896 switch (cmd) { 13897 case CLI_INIT: 13898 e->command = "ss7 unblock linkset"; 13899 e->usage = 13900 "Usage: ss7 unblock linkset <linkset number>\n" 13901 " Sends a remote unblocking request for all CICs on the specified linkset\n"; 13902 return NULL; 13903 case CLI_GENERATE: 13904 return NULL; 13905 } 13906 13907 if (a->argc == 4) 13908 linkset = atoi(a->argv[3]); 13909 else 13910 return CLI_SHOWUSAGE; 13911 13912 if ((linkset < 1) || (linkset > NUM_SPANS)) { 13913 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 13914 return CLI_SUCCESS; 13915 } 13916 13917 if (!linksets[linkset-1].ss7) { 13918 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset); 13919 return CLI_SUCCESS; 13920 } 13921 13922 for (i = 0; i < linksets[linkset-1].numchans; i++) { 13923 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic); 13924 ast_mutex_lock(&linksets[linkset-1].lock); 13925 isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc); 13926 ast_mutex_unlock(&linksets[linkset-1].lock); 13927 } 13928 13929 /* Break poll on the linkset so it sends our messages */ 13930 pthread_kill(linksets[linkset-1].master, SIGURG); 13931 13932 return CLI_SUCCESS; 13933 }
| static char* handle_ss7_version | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13969 of file chan_dahdi.c.
References ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
13970 { 13971 switch (cmd) { 13972 case CLI_INIT: 13973 e->command = "ss7 show version"; 13974 e->usage = 13975 "Usage: ss7 show version\n" 13976 " Show the libss7 version\n"; 13977 return NULL; 13978 case CLI_GENERATE: 13979 return NULL; 13980 } 13981 13982 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version()); 13983 13984 return CLI_SUCCESS; 13985 }
| static int has_voicemail | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2345 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_thread().
02346 { 02347 int new_msgs; 02348 struct ast_event *event; 02349 char *mailbox, *context; 02350 02351 mailbox = context = ast_strdupa(p->mailbox); 02352 strsep(&context, "@"); 02353 if (ast_strlen_zero(context)) 02354 context = "default"; 02355 02356 event = ast_event_get_cached(AST_EVENT_MWI, 02357 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 02358 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 02359 AST_EVENT_IE_END); 02360 02361 if (event) { 02362 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 02363 ast_event_destroy(event); 02364 } else 02365 new_msgs = ast_app_has_voicemail(p->mailbox, NULL); 02366 02367 return new_msgs; 02368 }
| static int isourconf | ( | struct dahdi_pvt * | p, | |
| struct dahdi_subchannel * | c | |||
| ) | [static] |
Definition at line 1860 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::confno, and dahdi_subchannel::curconf.
Referenced by conf_del().
01861 { 01862 /* If they're listening to our channel, they're ours */ 01863 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON)) 01864 return 1; 01865 /* If they're a talker on our (allocated) conference, they're ours */ 01866 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER)) 01867 return 1; 01868 return 0; 01869 }
Definition at line 1890 of file chan_dahdi.c.
References dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, dahdi_pvt::law, MAX_SLAVES, dahdi_pvt::slaves, and dahdi_pvt::subs.
Referenced by update_conf().
01891 { 01892 int x; 01893 int useslavenative; 01894 struct dahdi_pvt *slave = NULL; 01895 /* Start out optimistic */ 01896 useslavenative = 1; 01897 /* Update conference state in a stateless fashion */ 01898 for (x = 0; x < 3; x++) { 01899 /* Any three-way calling makes slave native mode *definitely* out 01900 of the question */ 01901 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) 01902 useslavenative = 0; 01903 } 01904 /* If we don't have any 3-way calls, check to see if we have 01905 precisely one slave */ 01906 if (useslavenative) { 01907 for (x = 0; x < MAX_SLAVES; x++) { 01908 if (p->slaves[x]) { 01909 if (slave) { 01910 /* Whoops already have a slave! No 01911 slave native and stop right away */ 01912 slave = NULL; 01913 useslavenative = 0; 01914 break; 01915 } else { 01916 /* We have one slave so far */ 01917 slave = p->slaves[x]; 01918 } 01919 } 01920 } 01921 } 01922 /* If no slave, slave native definitely out */ 01923 if (!slave) 01924 useslavenative = 0; 01925 else if (slave->law != p->law) { 01926 useslavenative = 0; 01927 slave = NULL; 01928 } 01929 if (out) 01930 *out = slave; 01931 return useslavenative; 01932 }
| static int linkset_addsigchan | ( | int | sigchan | ) | [static] |
Definition at line 13547 of file chan_dahdi.c.
References ast_log(), dahdi_close_ss7_fd(), errno, LINKSTATE_DOWN, LINKSTATE_INALARM, LOG_ERROR, NUM_SPANS, and ss7_resolve_linkset().
Referenced by process_dahdi().
13548 { 13549 struct dahdi_ss7 *link; 13550 int res; 13551 int curfd; 13552 struct dahdi_params p; 13553 struct dahdi_bufferinfo bi; 13554 struct dahdi_spaninfo si; 13555 13556 13557 link = ss7_resolve_linkset(cur_linkset); 13558 if (!link) { 13559 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1); 13560 return -1; 13561 } 13562 13563 if (cur_ss7type < 0) { 13564 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n"); 13565 return -1; 13566 } 13567 13568 if (!link->ss7) 13569 link->ss7 = ss7_new(cur_ss7type); 13570 13571 if (!link->ss7) { 13572 ast_log(LOG_ERROR, "Can't create new SS7!\n"); 13573 return -1; 13574 } 13575 13576 link->type = cur_ss7type; 13577 13578 if (cur_pointcode < 0) { 13579 ast_log(LOG_ERROR, "Unspecified pointcode!\n"); 13580 return -1; 13581 } else 13582 ss7_set_pc(link->ss7, cur_pointcode); 13583 13584 if (sigchan < 0) { 13585 ast_log(LOG_ERROR, "Invalid sigchan!\n"); 13586 return -1; 13587 } else { 13588 if (link->numsigchans >= NUM_DCHANS) { 13589 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset); 13590 return -1; 13591 } 13592 curfd = link->numsigchans; 13593 13594 link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600); 13595 if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) { 13596 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno)); 13597 return -1; 13598 } 13599 memset(&p, 0, sizeof(p)); 13600 res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p); 13601 if (res) { 13602 dahdi_close_ss7_fd(link, curfd); 13603 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno)); 13604 return -1; 13605 } 13606 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) { 13607 dahdi_close_ss7_fd(link, curfd); 13608 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan); 13609 return -1; 13610 } 13611 13612 memset(&bi, 0, sizeof(bi)); 13613 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 13614 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 13615 bi.numbufs = 32; 13616 bi.bufsize = 512; 13617 13618 if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) { 13619 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno)); 13620 dahdi_close_ss7_fd(link, curfd); 13621 return -1; 13622 } 13623 13624 if (p.sigtype == DAHDI_SIG_MTP2) 13625 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]); 13626 else 13627 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]); 13628 13629 link->numsigchans++; 13630 13631 memset(&si, 0, sizeof(si)); 13632 res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si); 13633 if (res) { 13634 dahdi_close_ss7_fd(link, curfd); 13635 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno)); 13636 } 13637 13638 if (!si.alarms) { 13639 link->linkstate[curfd] = LINKSTATE_DOWN; 13640 ss7_link_noalarm(link->ss7, link->fds[curfd]); 13641 } else { 13642 link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM; 13643 ss7_link_alarm(link->ss7, link->fds[curfd]); 13644 } 13645 } 13646 13647 if (cur_adjpointcode < 0) { 13648 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n"); 13649 return -1; 13650 } else { 13651 ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode); 13652 } 13653 13654 if (cur_defaultdpc < 0) { 13655 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n"); 13656 return -1; 13657 } 13658 13659 if (cur_networkindicator < 0) { 13660 ast_log(LOG_ERROR, "Invalid networkindicator!\n"); 13661 return -1; 13662 } else 13663 ss7_set_network_ind(link->ss7, cur_networkindicator); 13664 13665 return 0; 13666 }
| static int load_module | ( | void | ) | [static] |
Definition at line 15287 of file chan_dahdi.c.
References __unload_module(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdirestart(), action_dahdishowchannels(), action_transfer(), action_transferhangup(), ARRAY_LEN, ast_channel_register(), ast_cli_register_multiple(), ast_cond_init(), ast_log(), ast_manager_register, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, ast_mutex_init(), AST_PTHREADT_NULL, ast_register_application, ast_string_field_init, ast_string_field_set, dahdi_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, NUM_SPANS, dahdi_pri::offset, pris, and setup_dahdi().
15288 { 15289 int res; 15290 #if defined(HAVE_PRI) || defined(HAVE_SS7) 15291 int y, i; 15292 #endif 15293 15294 #ifdef HAVE_PRI 15295 memset(pris, 0, sizeof(pris)); 15296 for (y = 0; y < NUM_SPANS; y++) { 15297 ast_mutex_init(&pris[y].lock); 15298 pris[y].offset = -1; 15299 pris[y].master = AST_PTHREADT_NULL; 15300 for (i = 0; i < NUM_DCHANS; i++) 15301 pris[y].fds[i] = -1; 15302 } 15303 pri_set_error(dahdi_pri_error); 15304 pri_set_message(dahdi_pri_message); 15305 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec, 15306 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip); 15307 #endif 15308 #ifdef HAVE_SS7 15309 memset(linksets, 0, sizeof(linksets)); 15310 for (y = 0; y < NUM_SPANS; y++) { 15311 ast_mutex_init(&linksets[y].lock); 15312 linksets[y].master = AST_PTHREADT_NULL; 15313 for (i = 0; i < NUM_DCHANS; i++) 15314 linksets[y].fds[i] = -1; 15315 } 15316 ss7_set_error(dahdi_ss7_error); 15317 ss7_set_message(dahdi_ss7_message); 15318 #endif /* HAVE_SS7 */ 15319 res = setup_dahdi(0); 15320 /* Make sure we can register our DAHDI channel type */ 15321 if (res) 15322 return AST_MODULE_LOAD_DECLINE; 15323 if (ast_channel_register(&dahdi_tech)) { 15324 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n"); 15325 __unload_module(); 15326 return AST_MODULE_LOAD_FAILURE; 15327 } 15328 #ifdef HAVE_PRI 15329 ast_string_field_init(&inuse, 16); 15330 ast_string_field_set(&inuse, name, "GR-303InUse"); 15331 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 15332 #endif 15333 #ifdef HAVE_SS7 15334 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli)); 15335 #endif 15336 15337 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli)); 15338 15339 memset(round_robin, 0, sizeof(round_robin)); 15340 ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" ); 15341 ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" ); 15342 ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" ); 15343 ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" ); 15344 ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" ); 15345 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels"); 15346 ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)"); 15347 15348 ast_cond_init(&mwi_thread_complete, NULL); 15349 ast_cond_init(&ss_thread_complete, NULL); 15350 15351 return res; 15352 }
| static struct dahdi_pvt* mkintf | ( | int | channel, | |
| const struct dahdi_chan_conf * | conf, | |||
| struct dahdi_pri * | pri, | |||
| int | reloading | |||
| ) | [static, read] |
Definition at line 8707 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(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, 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_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::firstradio, free, get_alarms(), dahdi_pvt::group, handle_alarms(), dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::head, dahdi_pvt::hidecallerid, 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, dahdi_pri::nationalprefix, dahdi_ss7::nationalprefix, dahdi_pvt::next, dahdi_pri::nodetype, dahdi_pri::nsf, NUM_DCHANS, 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_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_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, and dahdi_pvt::vars.
Referenced by build_channels(), and process_dahdi().
08708 { 08709 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */ 08710 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL; 08711 char fn[80]; 08712 struct dahdi_bufferinfo bi; 08713 08714 int res; 08715 int span = 0; 08716 int here = 0; 08717 int x; 08718 struct dahdi_pvt **wlist; 08719 struct dahdi_pvt **wend; 08720 struct dahdi_params p; 08721 08722 wlist = &iflist; 08723 wend = &ifend; 08724 08725 #ifdef HAVE_PRI 08726 if (pri) { 08727 wlist = &pri->crvs; 08728 wend = &pri->crvend; 08729 } 08730 #endif 08731 08732 tmp2 = *wlist; 08733 prev = NULL; 08734 08735 while (tmp2) { 08736 if (!tmp2->destroy) { 08737 if (tmp2->channel == channel) { 08738 tmp = tmp2; 08739 here = 1; 08740 break; 08741 } 08742 if (tmp2->channel > channel) { 08743 break; 08744 } 08745 } 08746 prev = tmp2; 08747 tmp2 = tmp2->next; 08748 } 08749 08750 if (!here && reloading != 1) { 08751 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { 08752 if (tmp) 08753 free(tmp); 08754 return NULL; 08755 } 08756 ast_mutex_init(&tmp->lock); 08757 ifcount++; 08758 for (x = 0; x < 3; x++) 08759 tmp->subs[x].dfd = -1; 08760 tmp->channel = channel; 08761 tmp->priindication_oob = conf->chan.priindication_oob; 08762 } 08763 08764 if (tmp) { 08765 int chan_sig = conf->chan.sig; 08766 if (!here) { 08767 if ((channel != CHAN_PSEUDO) && !pri) { 08768 int count = 0; 08769 snprintf(fn, sizeof(fn), "%d", channel); 08770 /* Open non-blocking */ 08771 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 08772 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 */ 08773 usleep(1); 08774 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 08775 count++; 08776 } 08777 /* Allocate a DAHDI structure */ 08778 if (tmp->subs[SUB_REAL].dfd < 0) { 08779 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); 08780 destroy_dahdi_pvt(&tmp); 08781 return NULL; 08782 } 08783 memset(&p, 0, sizeof(p)); 08784 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 08785 if (res < 0) { 08786 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno)); 08787 destroy_dahdi_pvt(&tmp); 08788 return NULL; 08789 } 08790 if (conf->is_sig_auto) 08791 chan_sig = sigtype_to_signalling(p.sigtype); 08792 if (p.sigtype != (chan_sig & 0x3ffff)) { 08793 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)); 08794 destroy_dahdi_pvt(&tmp); 08795 return NULL; 08796 } 08797 tmp->law = p.curlaw; 08798 tmp->span = p.spanno; 08799 span = p.spanno - 1; 08800 } else { 08801 if (channel == CHAN_PSEUDO) 08802 chan_sig = 0; 08803 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) { 08804 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n"); 08805 return NULL; 08806 } 08807 } 08808 #ifdef HAVE_SS7 08809 if (chan_sig == SIG_SS7) { 08810 struct dahdi_ss7 *ss7; 08811 int clear = 0; 08812 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) { 08813 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 08814 destroy_dahdi_pvt(&tmp); 08815 return NULL; 08816 } 08817 08818 ss7 = ss7_resolve_linkset(cur_linkset); 08819 if (!ss7) { 08820 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset); 08821 destroy_dahdi_pvt(&tmp); 08822 return NULL; 08823 } 08824 if (cur_cicbeginswith < 0) { 08825 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n"); 08826 destroy_dahdi_pvt(&tmp); 08827 return NULL; 08828 } 08829 08830 tmp->cic = cur_cicbeginswith++; 08831 08832 /* DB: Add CIC's DPC information */ 08833 tmp->dpc = cur_defaultdpc; 08834 08835 tmp->ss7 = ss7; 08836 tmp->ss7call = NULL; 08837 ss7->pvts[ss7->numchans++] = tmp; 08838 08839 ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix)); 08840 ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix)); 08841 ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix)); 08842 ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix)); 08843 08844 ss7->called_nai = conf->ss7.called_nai; 08845 ss7->calling_nai = conf->ss7.calling_nai; 08846 } 08847 #endif 08848 #ifdef HAVE_PRI 08849 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) { 08850 int offset; 08851 int myswitchtype; 08852 int matchesdchan; 08853 int x,y; 08854 offset = 0; 08855 if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP)) 08856 && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) { 08857 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 08858 destroy_dahdi_pvt(&tmp); 08859 return NULL; 08860 } 08861 if (span >= NUM_SPANS) { 08862 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span); 08863 destroy_dahdi_pvt(&tmp); 08864 return NULL; 08865 } else { 08866 struct dahdi_spaninfo si; 08867 si.spanno = 0; 08868 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) { 08869 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); 08870 destroy_dahdi_pvt(&tmp); 08871 return NULL; 08872 } 08873 /* Store the logical span first based upon the real span */ 08874 tmp->logicalspan = pris[span].prilogicalspan; 08875 pri_resolve_span(&span, channel, (channel - p.chanpos), &si); 08876 if (span < 0) { 08877 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel); 08878 destroy_dahdi_pvt(&tmp); 08879 return NULL; 08880 } 08881 if ((chan_sig == SIG_PRI) || 08882 (chan_sig == SIG_BRI) || 08883 (chan_sig == SIG_BRI_PTMP)) 08884 myswitchtype = conf->pri.switchtype; 08885 else 08886 myswitchtype = PRI_SWITCH_GR303_TMC; 08887 /* Make sure this isn't a d-channel */ 08888 matchesdchan=0; 08889 for (x = 0; x < NUM_SPANS; x++) { 08890 for (y = 0; y < NUM_DCHANS; y++) { 08891 if (pris[x].dchannels[y] == tmp->channel) { 08892 matchesdchan = 1; 08893 break; 08894 } 08895 } 08896 } 08897 offset = p.chanpos; 08898 if (!matchesdchan) { 08899 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) { 08900 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype)); 08901 destroy_dahdi_pvt(&tmp); 08902 return NULL; 08903 } 08904 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) { 08905 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype)); 08906 destroy_dahdi_pvt(&tmp); 08907 return NULL; 08908 } 08909 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) { 08910 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan)); 08911 destroy_dahdi_pvt(&tmp); 08912 return NULL; 08913 } 08914 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) { 08915 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial); 08916 destroy_dahdi_pvt(&tmp); 08917 return NULL; 08918 } 08919 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) { 08920 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext); 08921 destroy_dahdi_pvt(&tmp); 08922 return NULL; 08923 } 08924 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) { 08925 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused); 08926 destroy_dahdi_pvt(&tmp); 08927 return NULL; 08928 } 08929 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) { 08930 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle); 08931 destroy_dahdi_pvt(&tmp); 08932 return NULL; 08933 } 08934 if (pris[span].numchans >= MAX_CHANNELS) { 08935 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, 08936 pris[span].trunkgroup); 08937 destroy_dahdi_pvt(&tmp); 08938 return NULL; 08939 } 08940 08941 pris[span].sig = chan_sig; 08942 pris[span].nodetype = conf->pri.nodetype; 08943 pris[span].switchtype = myswitchtype; 08944 pris[span].nsf = conf->pri.nsf; 08945 pris[span].dialplan = conf->pri.dialplan; 08946 pris[span].localdialplan = conf->pri.localdialplan; 08947 pris[span].pvts[pris[span].numchans++] = tmp; 08948 pris[span].minunused = conf->pri.minunused; 08949 pris[span].minidle = conf->pri.minidle; 08950 pris[span].overlapdial = conf->pri.overlapdial; 08951 #ifdef HAVE_PRI_INBANDDISCONNECT 08952 pris[span].inbanddisconnect = conf->pri.inbanddisconnect; 08953 #endif 08954 pris[span].facilityenable = conf->pri.facilityenable; 08955 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial)); 08956 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext)); 08957 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix)); 08958 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix)); 08959 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix)); 08960 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix)); 08961 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix)); 08962 pris[span].resetinterval = conf->pri.resetinterval; 08963 08964 tmp->pri = &pris[span]; 08965 tmp->prioffset = offset; 08966 tmp->call = NULL; 08967 } else { 08968 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset); 08969 destroy_dahdi_pvt(&tmp); 08970 return NULL; 08971 } 08972 } 08973 } else { 08974 tmp->prioffset = 0; 08975 } 08976 #endif 08977 } else { 08978 chan_sig = tmp->sig; 08979 if (tmp->subs[SUB_REAL].dfd > -1) { 08980 memset(&p, 0, sizeof(p)); 08981 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 08982 } 08983 } 08984 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */ 08985 switch (chan_sig) { 08986 case SIG_FXSKS: 08987 case SIG_FXSLS: 08988 case SIG_EM: 08989 case SIG_EM_E1: 08990 case SIG_EMWINK: 08991 case SIG_FEATD: 08992 case SIG_FEATDMF: 08993 case SIG_FEATDMF_TA: 08994 case SIG_FEATB: 08995 case SIG_E911: 08996 case SIG_SF: 08997 case SIG_SFWINK: 08998 case SIG_FGC_CAMA: 08999 case SIG_FGC_CAMAMF: 09000 case SIG_SF_FEATD: 09001 case SIG_SF_FEATDMF: 09002 case SIG_SF_FEATB: 09003 p.starttime = 250; 09004 break; 09005 } 09006 09007 if (tmp->radio) { 09008 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */ 09009 p.channo = channel; 09010 p.rxwinktime = 1; 09011 p.rxflashtime = 1; 09012 p.starttime = 1; 09013 p.debouncetime = 5; 09014 } 09015 if (!tmp->radio) { 09016 p.channo = channel; 09017 /* Override timing settings based on config file */ 09018 if (conf->timing.prewinktime >= 0) 09019 p.prewinktime = conf->timing.prewinktime; 09020 if (conf->timing.preflashtime >= 0) 09021 p.preflashtime = conf->timing.preflashtime; 09022 if (conf->timing.winktime >= 0) 09023 p.winktime = conf->timing.winktime; 09024 if (conf->timing.flashtime >= 0) 09025 p.flashtime = conf->timing.flashtime; 09026 if (conf->timing.starttime >= 0) 09027 p.starttime = conf->timing.starttime; 09028 if (conf->timing.rxwinktime >= 0) 09029 p.rxwinktime = conf->timing.rxwinktime; 09030 if (conf->timing.rxflashtime >= 0) 09031 p.rxflashtime = conf->timing.rxflashtime; 09032 if (conf->timing.debouncetime >= 0) 09033 p.debouncetime = conf->timing.debouncetime; 09034 } 09035 09036 /* dont set parms on a pseudo-channel (or CRV) */ 09037 if (tmp->subs[SUB_REAL].dfd >= 0) 09038 { 09039 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p); 09040 if (res < 0) { 09041 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno)); 09042 destroy_dahdi_pvt(&tmp); 09043 return NULL; 09044 } 09045 } 09046 #if 1 09047 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) { 09048 memset(&bi, 0, sizeof(bi)); 09049 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 09050 if (!res) { 09051 bi.txbufpolicy = conf->chan.buf_policy; 09052 bi.rxbufpolicy = conf->chan.buf_policy; 09053 bi.numbufs = conf->chan.buf_no; 09054 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 09055 if (res < 0) { 09056 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno)); 09057 } 09058 } else 09059 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno)); 09060 } 09061 #endif 09062 tmp->immediate = conf->chan.immediate; 09063 tmp->transfertobusy = conf->chan.transfertobusy; 09064 if (chan_sig & __DAHDI_SIG_FXS) { 09065 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk; 09066 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon; 09067 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas; 09068 } 09069 tmp->sig = chan_sig; 09070 tmp->outsigmod = conf->chan.outsigmod; 09071 tmp->ringt_base = ringt_base; 09072 tmp->firstradio = 0; 09073 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS)) 09074 tmp->permcallwaiting = conf->chan.callwaiting; 09075 else 09076 tmp->permcallwaiting = 0; 09077 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */ 09078 tmp->destroy = 0; 09079 tmp->drings = conf->chan.drings; 09080 09081 /* 10 is a nice default. */ 09082 if (tmp->drings.ringnum[0].range == 0) 09083 tmp->drings.ringnum[0].range = 10; 09084 if (tmp->drings.ringnum[1].range == 0) 09085 tmp->drings.ringnum[1].range = 10; 09086 if (tmp->drings.ringnum[2].range == 0) 09087 tmp->drings.ringnum[2].range = 10; 09088 09089 tmp->usedistinctiveringdetection = usedistinctiveringdetection; 09090 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid; 09091 tmp->threewaycalling = conf->chan.threewaycalling; 09092 tmp->adsi = conf->chan.adsi; 09093 tmp->use_smdi = conf->chan.use_smdi; 09094 tmp->permhidecallerid = conf->chan.hidecallerid; 09095 tmp->callreturn = conf->chan.callreturn; 09096 tmp->echocancel = conf->chan.echocancel; 09097 tmp->echotraining = conf->chan.echotraining; 09098 tmp->pulse = conf->chan.pulse; 09099 if (tmp->echocancel.head.tap_length) { 09100 tmp->echocanbridged = conf->chan.echocanbridged; 09101 } else { 09102 if (conf->chan.echocanbridged) 09103 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n"); 09104 tmp->echocanbridged = 0; 09105 } 09106 tmp->busydetect = conf->chan.busydetect; 09107 tmp->busycount = conf->chan.busycount; 09108 tmp->busy_tonelength = conf->chan.busy_tonelength; 09109 tmp->busy_quietlength = conf->chan.busy_quietlength; 09110 tmp->callprogress = conf->chan.callprogress; 09111 tmp->cancallforward = conf->chan.cancallforward; 09112 tmp->dtmfrelax = conf->chan.dtmfrelax; 09113 tmp->callwaiting = tmp->permcallwaiting; 09114 tmp->hidecallerid = tmp->permhidecallerid; 09115 tmp->channel = channel; 09116 tmp->stripmsd = conf->chan.stripmsd; 09117 tmp->use_callerid = conf->chan.use_callerid; 09118 tmp->cid_signalling = conf->chan.cid_signalling; 09119 tmp->cid_start = conf->chan.cid_start; 09120 tmp->dahditrcallerid = conf->chan.dahditrcallerid; 09121 tmp->restrictcid = conf->chan.restrictcid; 09122 tmp->use_callingpres = conf->chan.use_callingpres; 09123 tmp->priexclusive = conf->chan.priexclusive; 09124 if (tmp->usedistinctiveringdetection) { 09125 if (!tmp->use_callerid) { 09126 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n"); 09127 tmp->use_callerid = 1; 09128 } 09129 } 09130 09131 if (tmp->cid_signalling == CID_SIG_SMDI) { 09132 if (!tmp->use_smdi) { 09133 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n"); 09134 tmp->use_smdi = 1; 09135 } 09136 } 09137 if (tmp->use_smdi) { 09138 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port); 09139 if (!(tmp->smdi_iface)) { 09140 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n"); 09141 tmp->use_smdi = 0; 09142 } 09143 } 09144 09145 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode)); 09146 tmp->amaflags = conf->chan.amaflags; 09147 if (!here) { 09148 tmp->confno = -1; 09149 tmp->propconfno = -1; 09150 } 09151 tmp->canpark = conf->chan.canpark; 09152 tmp->transfer = conf->chan.transfer; 09153 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext)); 09154 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language)); 09155 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret)); 09156 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest)); 09157 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context)); 09158 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num)); 09159 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot)); 09160 tmp->cid_ton = 0; 09161 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name)); 09162 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox)); 09163 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) { 09164 char *mailbox, *context; 09165 mailbox = context = ast_strdupa(tmp->mailbox); 09166 strsep(&context, "@"); 09167 if (ast_strlen_zero(context)) 09168 context = "default"; 09169 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL, 09170 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 09171 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 09172 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, 09173 AST_EVENT_IE_END); 09174 } 09175 tmp->msgstate = -1; 09176 tmp->group = conf->chan.group; 09177 tmp->callgroup = conf->chan.callgroup; 09178 tmp->pickupgroup= conf->chan.pickupgroup; 09179 if (conf->chan.vars) { 09180 tmp->vars = conf->chan.vars; 09181 } 09182 tmp->cid_rxgain = conf->chan.cid_rxgain; 09183 tmp->rxgain = conf->chan.rxgain; 09184 tmp->txgain = conf->chan.txgain; 09185 tmp->tonezone = conf->chan.tonezone; 09186 tmp->onhooktime = time(NULL); 09187 if (tmp->subs[SUB_REAL].dfd > -1) { 09188 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law); 09189 if (tmp->dsp) 09190 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax); 09191 update_conf(tmp); 09192 if (!here) { 09193 if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI) && (chan_sig != SIG_SS7)) 09194 /* Hang it up to be sure it's good */ 09195 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 09196 } 09197 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone); 09198 #ifdef HAVE_PRI 09199 /* the dchannel is down so put the channel in alarm */ 09200 if (tmp->pri && !pri_is_up(tmp->pri)) 09201 tmp->inalarm = 1; 09202 #endif 09203 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) { 09204 tmp->inalarm = 1; 09205 handle_alarms(tmp, res); 09206 } 09207 } 09208 09209 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 09210 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 09211 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 09212 tmp->sendcalleridafter = conf->chan.sendcalleridafter; 09213 if (!here) { 09214 tmp->locallyblocked = tmp->remotelyblocked = 0; 09215 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7)) 09216 tmp->inservice = 0; 09217 else /* We default to in service on protocols that don't have a reset */ 09218 tmp->inservice = 1; 09219 } 09220 } 09221 if (tmp && !here) { 09222 /* nothing on the iflist */ 09223 if (!*wlist) { 09224 *wlist = tmp; 09225 tmp->prev = NULL; 09226 tmp->next = NULL; 09227 *wend = tmp; 09228 } else { 09229 /* at least one member on the iflist */ 09230 struct dahdi_pvt *working = *wlist; 09231 09232 /* check if we maybe have to put it on the begining */ 09233 if (working->channel > tmp->channel) { 09234 tmp->next = *wlist; 09235 tmp->prev = NULL; 09236 (*wlist)->prev = tmp; 09237 *wlist = tmp; 09238 } else { 09239 /* go through all the members and put the member in the right place */ 09240 while (working) { 09241 /* in the middle */ 09242 if (working->next) { 09243 if (working->channel < tmp->channel && working->next->channel > tmp->channel) { 09244 tmp->next = working->next; 09245 tmp->prev = working; 09246 working->next->prev = tmp; 09247 working->next = tmp; 09248 break; 09249 } 09250 } else { 09251 /* the last */ 09252 if (working->channel < tmp->channel) { 09253 working->next = tmp; 09254 tmp->next = NULL; 09255 tmp->prev = working; 09256 *wend = tmp; 09257 break; 09258 } 09259 } 09260 working = working->next; 09261 } 09262 } 09263 } 09264 } 09265 return tmp; 09266 }
| static void mwi_event_cb | ( | const struct ast_event * | event, | |
| void * | userdata | |||
| ) | [static] |
Definition at line 294 of file chan_dahdi.c.
Referenced by mkintf().
00295 { 00296 /* This module does not handle MWI in an event-based manner. However, it 00297 * subscribes to MWI for each mailbox that is configured so that the core 00298 * knows that we care about it. Then, chan_dahdi will get the MWI from the 00299 * event cache instead of checking the mailbox directly. */ 00300 }
| static void* mwi_send_thread | ( | void * | data | ) | [static] |
Definition at line 7913 of file chan_dahdi.c.
References ast_calloc, ast_cond_signal(), ast_free, AST_LAW, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), mwi_thread_data::buf, CID_MWI_TYPE_MDMF_FULL, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_get_event(), dahdi_set_hook(), dahdi_subchannel::dfd, errno, handle_init_event(), has_voicemail(), LOG_WARNING, MAX_CALLERID_SIZE, MWI_SEND_CLEANUP, MWI_SEND_DONE, MWI_SEND_PAUSE, MWI_SEND_SA, MWI_SEND_SA_WAIT, MWI_SEND_SPILL, mwi_thread_lock, dahdi_pvt::mwisendactive, mwi_thread_data::pvt, quit, SUB_REAL, dahdi_pvt::subs, and vmwi_generate().
Referenced by do_monitor().
07914 { 07915 struct mwi_thread_data *mtd = data; 07916 struct timeval timeout_basis, suspend, now; 07917 int x, i, res; 07918 int num_read; 07919 enum mwisend_states mwi_send_state = MWI_SEND_SPILL; /*Assume FSK only */ 07920 07921 ast_mutex_lock(&mwi_thread_lock); 07922 mwi_thread_count++; 07923 ast_mutex_unlock(&mwi_thread_lock); 07924 07925 /* Determine how this spill is to be sent */ 07926 if(mwisend_rpas) { 07927 mwi_send_state = MWI_SEND_SA; 07928 } 07929 07930 gettimeofday(&timeout_basis, NULL); 07931 07932 mtd->pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE); 07933 if (!mtd->pvt->cidspill) { 07934 mtd->pvt->mwisendactive = 0; 07935 ast_free(mtd); 07936 return NULL; 07937 } 07938 x = DAHDI_FLUSH_BOTH; 07939 res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 07940 x = 3000; 07941 ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x); 07942 mtd->pvt->cidlen = vmwi_generate(mtd->pvt->cidspill, has_voicemail(mtd->pvt), CID_MWI_TYPE_MDMF_FULL, 07943 AST_LAW(mtd->pvt), mtd->pvt->cid_name, mtd->pvt->cid_num, 0); 07944 mtd->pvt->cidpos = 0; 07945 07946 while (MWI_SEND_DONE != mwi_send_state) { 07947 num_read = 0; 07948 gettimeofday(&now, NULL); 07949 if ( 10 < (now.tv_sec - timeout_basis.tv_sec)) { 07950 ast_log(LOG_WARNING, "MWI Send TIMEOUT in state %d\n", mwi_send_state); 07951 goto quit; 07952 } 07953 07954 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07955 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) { 07956 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07957 goto quit; 07958 } 07959 07960 if (i & DAHDI_IOMUX_SIGEVENT) { 07961 /* If we get an event, screen out events that we do not act on. 07962 * Otherwise, let handle_init_event determine what is needed 07963 */ 07964 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd); 07965 switch (res) { 07966 case DAHDI_EVENT_RINGEROFF: 07967 if(mwi_send_state == MWI_SEND_SA_WAIT) { 07968 if (dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) { 07969 ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s\n", strerror(errno)); 07970 goto quit; 07971 } 07972 mwi_send_state = MWI_SEND_PAUSE; 07973 gettimeofday(&suspend, NULL); 07974 } 07975 break; 07976 case DAHDI_EVENT_RINGERON: 07977 case DAHDI_EVENT_HOOKCOMPLETE: 07978 break; 07979 default: 07980 /* Got to the default init event handler */ 07981 if (0 < handle_init_event(mtd->pvt, res)) { 07982 /* I've spawned a thread, get out */ 07983 goto quit; 07984 } 07985 break; 07986 } 07987 } else if (i & DAHDI_IOMUX_READ) { 07988 if ((num_read = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) { 07989 if (errno != ELAST) { 07990 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07991 goto quit; 07992 } 07993 break; 07994 } 07995 } 07996 /* Perform mwi send action */ 07997 switch ( mwi_send_state) { 07998 case MWI_SEND_SA: 07999 /* Send the Ring Pulse Signal Alert */ 08000 res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence); 08001 if (res) { 08002 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno)); 08003 goto quit; 08004 } 08005 dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RING); 08006 mwi_send_state = MWI_SEND_SA_WAIT; 08007 break; 08008 case MWI_SEND_SA_WAIT: /* do nothing until I get RINGEROFF event */ 08009 break; 08010 case MWI_SEND_PAUSE: /* Wait between alert and spill - min of 500 mS*/ 08011 gettimeofday(&now, NULL); 08012 if ((int)(now.tv_sec - suspend.tv_sec) * 1000000 + (int)now.tv_usec - (int)suspend.tv_usec > 500000) { 08013 mwi_send_state = MWI_SEND_SPILL; 08014 } 08015 break; 08016 case MWI_SEND_SPILL: 08017 /* We read some number of bytes. Write an equal amount of data */ 08018 if(0 < num_read) { 08019 if (num_read > mtd->pvt->cidlen - mtd->pvt->cidpos) 08020 num_read = mtd->pvt->cidlen - mtd->pvt->cidpos; 08021 res = write(mtd->pvt->subs[SUB_REAL].dfd, mtd->pvt->cidspill + mtd->pvt->cidpos, num_read); 08022 if (res > 0) { 08023 mtd->pvt->cidpos += res; 08024 if (mtd->pvt->cidpos >= mtd->pvt->cidlen) { 08025 ast_free(mtd->pvt->cidspill); 08026 mtd->pvt->cidspill = NULL; 08027 mtd->pvt->cidpos = 0; 08028 mtd->pvt->cidlen = 0; 08029 mwi_send_state = MWI_SEND_CLEANUP; 08030 } 08031 } else { 08032 ast_log(LOG_WARNING, "MWI Send Write failed: %s\n", strerror(errno)); 08033 goto quit; 08034 } 08035 } 08036 break; 08037 case MWI_SEND_CLEANUP: 08038 /* For now, do nothing */ 08039 mwi_send_state = MWI_SEND_DONE; 08040 break; 08041 default: 08042 /* Should not get here, punt*/ 08043 goto quit; 08044 break; 08045 } 08046 } 08047 08048 quit: 08049 if(mtd->pvt->cidspill) { 08050 ast_free(mtd->pvt->cidspill); 08051 mtd->pvt->cidspill = NULL; 08052 } 08053 mtd->pvt->mwisendactive = 0; 08054 ast_free(mtd); 08055 08056 ast_mutex_lock(&mwi_thread_lock); 08057 mwi_thread_count--; 08058 ast_cond_signal(&mwi_thread_complete); 08059 ast_mutex_unlock(&mwi_thread_lock); 08060 08061 return NULL; 08062 }
| static void* mwi_thread | ( | void * | data | ) | [static] |
Definition at line 7770 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(), chan, 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().
07771 { 07772 struct mwi_thread_data *mtd = data; 07773 struct callerid_state *cs; 07774 pthread_t threadid; 07775 int samples = 0; 07776 char *name, *number; 07777 int flags; 07778 int i, res; 07779 unsigned int spill_done = 0; 07780 int spill_result = -1; 07781 07782 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) { 07783 mtd->pvt->mwimonitoractive = 0; 07784 07785 return NULL; 07786 } 07787 07788 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt)); 07789 07790 bump_gains(mtd->pvt); 07791 07792 for (;;) { 07793 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07794 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) { 07795 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07796 goto quit; 07797 } 07798 07799 if (i & DAHDI_IOMUX_SIGEVENT) { 07800 struct ast_channel *chan; 07801 07802 /* If we get an event, screen out events that we do not act on. 07803 * Otherwise, cancel and go to the simple switch to let it deal with it. 07804 */ 07805 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd); 07806 07807 switch (res) { 07808 case DAHDI_EVENT_NEONMWI_ACTIVE: 07809 case DAHDI_EVENT_NEONMWI_INACTIVE: 07810 case DAHDI_EVENT_NONE: 07811 case DAHDI_EVENT_BITSCHANGED: 07812 break; 07813 case DAHDI_EVENT_NOALARM: 07814 mtd->pvt->inalarm = 0; 07815 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel); 07816 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 07817 "Channel: %d\r\n", mtd->pvt->channel); 07818 break; 07819 case DAHDI_EVENT_ALARM: 07820 mtd->pvt->inalarm = 1; 07821 res = get_alarms(mtd->pvt); 07822 handle_alarms(mtd->pvt, res); 07823 break; /* What to do on channel alarm ???? -- fall thru intentionally?? */ 07824 default: 07825 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to ss_thread\n", res, event2str(res)); 07826 callerid_free(cs); 07827 07828 restore_gains(mtd->pvt); 07829 mtd->pvt->ringt = mtd->pvt->ringt_base; 07830 07831 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) { 07832 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 07833 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel); 07834 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07835 if (res < 0) 07836 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel); 07837 ast_hangup(chan); 07838 goto quit; 07839 } 07840 goto quit_no_clean; 07841 07842 } else { 07843 ast_log(LOG_WARNING, "Could not create channel to handle call\n"); 07844 } 07845 } 07846 } else if (i & DAHDI_IOMUX_READ) { 07847 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) { 07848 if (errno != ELAST) { 07849 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07850 goto quit; 07851 } 07852 break; 07853 } 07854 samples += res; 07855 if (!spill_done) { 07856 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) { 07857 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno)); 07858 break; 07859 } else if (spill_result) { 07860 spill_done = 1; 07861 } 07862 } else { 07863 /* keep reading data until the energy level drops below the threshold 07864 so we don't get another 'trigger' on the remaining carrier signal 07865 */ 07866 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel) 07867 break; 07868 } 07869 if (samples > (8000 * 4)) /*Termination case - time to give up*/ 07870 break; 07871 } 07872 } 07873 07874 if (spill_result == 1) { 07875 callerid_get(cs, &name, &number, &flags); 07876 if (flags & CID_MSGWAITING) { 07877 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel); 07878 notify_message(mtd->pvt->mailbox, 1); 07879 } else if (flags & CID_NOMSGWAITING) { 07880 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel); 07881 notify_message(mtd->pvt->mailbox, 0); 07882 } else { 07883 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel); 07884 } 07885 } 07886 07887 07888 quit: 07889 callerid_free(cs); 07890 07891 restore_gains(mtd->pvt); 07892 07893 quit_no_clean: 07894 mtd->pvt->mwimonitoractive = 0; 07895 07896 ast_free(mtd); 07897 07898 return NULL; 07899 }
| static int my_dahdi_write | ( | struct dahdi_pvt * | p, | |
| unsigned char * | buf, | |||
| int | len, | |||
| int | idx, | |||
| int | linear | |||
| ) | [static] |
Definition at line 5962 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().
05963 { 05964 int sent=0; 05965 int size; 05966 int res; 05967 int fd; 05968 fd = p->subs[idx].dfd; 05969 while (len) { 05970 size = len; 05971 if (size > (linear ? READ_SIZE * 2 : READ_SIZE)) 05972 size = (linear ? READ_SIZE * 2 : READ_SIZE); 05973 res = write(fd, buf, size); 05974 if (res != size) { 05975 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 05976 return sent; 05977 } 05978 len -= size; 05979 buf += size; 05980 } 05981 return sent; 05982 }
| static int my_getsigstr | ( | struct ast_channel * | chan, | |
| char * | str, | |||
| const char * | term, | |||
| int | ms | |||
| ) | [static] |
Definition at line 6483 of file chan_dahdi.c.
References ast_waitfordigit().
Referenced by ss_thread().
06484 { 06485 char c; 06486 06487 *str = 0; /* start with empty output buffer */ 06488 for (;;) 06489 { 06490 /* Wait for the first digit (up to specified ms). */ 06491 c = ast_waitfordigit(chan, ms); 06492 /* if timeout, hangup or error, return as such */ 06493 if (c < 1) 06494 return c; 06495 *str++ = c; 06496 *str = 0; 06497 if (strchr(term, c)) 06498 return 1; 06499 } 06500 }
| 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 2284 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().
02285 { 02286 char s[sizeof(mwimonitornotify) + 80]; 02287 struct ast_event *event; 02288 char *mailbox, *context; 02289 02290 /* Strip off @default */ 02291 context = mailbox = ast_strdupa(mailbox_full); 02292 strsep(&context, "@"); 02293 if (ast_strlen_zero(context)) 02294 context = "default"; 02295 02296 if (!(event = ast_event_new(AST_EVENT_MWI, 02297 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 02298 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 02299 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 02300 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 02301 AST_EVENT_IE_END))) { 02302 return; 02303 } 02304 02305 ast_event_queue_and_cache(event); 02306 02307 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) { 02308 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot); 02309 ast_safe_system(s); 02310 } 02311 }
| static unsigned int parse_pointcode | ( | const char * | pcstring | ) | [static] |
Definition at line 8674 of file chan_dahdi.c.
Referenced by process_dahdi().
| static int pri_active_dchan_fd | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3334 of file chan_dahdi.c.
References dahdi_pri::dchans, dahdi_pri::fds, NUM_DCHANS, and dahdi_pri::pri.
Referenced by pri_find_principle().
03335 { 03336 int x = -1; 03337 03338 for (x = 0; x < NUM_DCHANS; x++) { 03339 if ((pri->dchans[x] == pri->pri)) 03340 break; 03341 } 03342 03343 return pri->fds[x]; 03344 }
| static int pri_assign_bearer | ( | struct dahdi_pvt * | crv, | |
| struct dahdi_pri * | pri, | |||
| struct dahdi_pvt * | bearer | |||
| ) | [static] |
Definition at line 3304 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().
03305 { 03306 bearer->owner = &inuse; 03307 bearer->realcall = crv; 03308 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd; 03309 if (crv->subs[SUB_REAL].owner) 03310 ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd); 03311 crv->bearer = bearer; 03312 crv->call = bearer->call; 03313 crv->pri = pri; 03314 return 0; 03315 }
| static int pri_check_restart | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 10775 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().
10776 { 10777 do { 10778 pri->resetpos++; 10779 } while ((pri->resetpos < pri->numchans) && 10780 (!pri->pvts[pri->resetpos] || 10781 pri->pvts[pri->resetpos]->call || 10782 pri->pvts[pri->resetpos]->resetting)); 10783 if (pri->resetpos < pri->numchans) { 10784 /* Mark the channel as resetting and restart it */ 10785 pri->pvts[pri->resetpos]->resetting = 1; 10786 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos])); 10787 } else { 10788 pri->resetting = 0; 10789 time(&pri->lastreset); 10790 } 10791 return 0; 10792 }
| static int pri_create_spanmap | ( | int | span, | |
| int | trunkgroup, | |||
| int | logicalspan | |||
| ) | [static] |
Definition at line 8659 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, dahdi_pri::mastertrunkgroup, dahdi_pri::prilogicalspan, and pris.
Referenced by setup_dahdi().
08660 { 08661 if (pris[span].mastertrunkgroup) { 08662 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); 08663 return -1; 08664 } 08665 pris[span].mastertrunkgroup = trunkgroup; 08666 pris[span].prilogicalspan = logicalspan; 08667 return 0; 08668 }
| static int pri_create_trunkgroup | ( | int | trunkgroup, | |
| int * | channels | |||
| ) | [static] |
Definition at line 8596 of file chan_dahdi.c.
References ast_log(), DCHAN_PROVISIONED, dahdi_pri::dchanavail, dahdi_pri::dchannels, errno, LOG_WARNING, NUM_DCHANS, NUM_SPANS, dahdi_pri::offset, pris, pvts, dahdi_pri::span, and dahdi_pri::trunkgroup.
Referenced by setup_dahdi().
08597 { 08598 struct dahdi_spaninfo si; 08599 struct dahdi_params p; 08600 int fd; 08601 int span; 08602 int ospan=0; 08603 int x,y; 08604 for (x = 0; x < NUM_SPANS; x++) { 08605 if (pris[x].trunkgroup == trunkgroup) { 08606 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]); 08607 return -1; 08608 } 08609 } 08610 for (y = 0; y < NUM_DCHANS; y++) { 08611 if (!channels[y]) 08612 break; 08613 memset(&si, 0, sizeof(si)); 08614 memset(&p, 0, sizeof(p)); 08615 fd = open("/dev/dahdi/channel", O_RDWR); 08616 if (fd < 0) { 08617 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno)); 08618 return -1; 08619 } 08620 x = channels[y]; 08621 if (ioctl(fd, DAHDI_SPECIFY, &x)) { 08622 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno)); 08623 close(fd); 08624 return -1; 08625 } 08626 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) { 08627 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno)); 08628 return -1; 08629 } 08630 if (ioctl(fd, DAHDI_SPANSTAT, &si)) { 08631 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno)); 08632 close(fd); 08633 return -1; 08634 } 08635 span = p.spanno - 1; 08636 if (pris[span].trunkgroup) { 08637 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup); 08638 close(fd); 08639 return -1; 08640 } 08641 if (pris[span].pvts[0]) { 08642 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1); 08643 close(fd); 08644 return -1; 08645 } 08646 if (!y) { 08647 pris[span].trunkgroup = trunkgroup; 08648 pris[span].offset = channels[y] - p.chanpos; 08649 ospan = span; 08650 } 08651 pris[ospan].dchannels[y] = channels[y]; 08652 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED; 08653 pris[span].span = span + 1; 08654 close(fd); 08655 } 08656 return 0; 08657 }
| static void* pri_dchannel | ( | void * | vpri | ) | [static] |
Definition at line 10869 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_CONTROL_BUSY, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, ast_dsp_set_features(), ast_exists_extension(), AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF, 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_SOFTHANGUP_DEV, 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_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, 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().
10870 { 10871 struct dahdi_pri *pri = vpri; 10872 pri_event *e; 10873 struct pollfd fds[NUM_DCHANS]; 10874 int res; 10875 int chanpos = 0; 10876 int x; 10877 int haveidles; 10878 int activeidles; 10879 int nextidle = -1; 10880 struct ast_channel *c; 10881 struct timeval tv, lowest, *next; 10882 struct timeval lastidle = ast_tvnow(); 10883 int doidling=0; 10884 char *cc; 10885 char idlen[80]; 10886 struct ast_channel *idle; 10887 pthread_t p; 10888 time_t t; 10889 int i, which=-1; 10890 int numdchans; 10891 int cause=0; 10892 struct dahdi_pvt *crv; 10893 pthread_t threadid; 10894 char ani2str[6]; 10895 char plancallingnum[256]; 10896 char plancallingani[256]; 10897 char calledtonstr[10]; 10898 10899 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 10900 10901 gettimeofday(&lastidle, NULL); 10902 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) { 10903 /* Need to do idle dialing, check to be sure though */ 10904 cc = strchr(pri->idleext, '@'); 10905 if (cc) { 10906 *cc = '\0'; 10907 cc++; 10908 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext)); 10909 #if 0 10910 /* Extensions may not be loaded yet */ 10911 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL)) 10912 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext); 10913 else 10914 #endif 10915 doidling = 1; 10916 } else 10917 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext); 10918 } 10919 for (;;) { 10920 for (i = 0; i < NUM_DCHANS; i++) { 10921 if (!pri->dchannels[i]) 10922 break; 10923 fds[i].fd = pri->fds[i]; 10924 fds[i].events = POLLIN | POLLPRI; 10925 fds[i].revents = 0; 10926 } 10927 numdchans = i; 10928 time(&t); 10929 ast_mutex_lock(&pri->lock); 10930 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) { 10931 if (pri->resetting && pri_is_up(pri)) { 10932 if (pri->resetpos < 0) 10933 pri_check_restart(pri); 10934 } else { 10935 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) { 10936 pri->resetting = 1; 10937 pri->resetpos = -1; 10938 } 10939 } 10940 } 10941 /* Look for any idle channels if appropriate */ 10942 if (doidling && pri_is_up(pri)) { 10943 nextidle = -1; 10944 haveidles = 0; 10945 activeidles = 0; 10946 for (x = pri->numchans; x >= 0; x--) { 10947 if (pri->pvts[x] && !pri->pvts[x]->owner && 10948 !pri->pvts[x]->call) { 10949 if (haveidles < pri->minunused) { 10950 haveidles++; 10951 } else if (!pri->pvts[x]->resetting) { 10952 nextidle = x; 10953 break; 10954 } 10955 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) 10956 activeidles++; 10957 } 10958 if (nextidle > -1) { 10959 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) { 10960 /* Don't create a new idle call more than once per second */ 10961 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial); 10962 idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause); 10963 if (idle) { 10964 pri->pvts[nextidle]->isidlecall = 1; 10965 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) { 10966 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name); 10967 dahdi_hangup(idle); 10968 } 10969 } else 10970 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen); 10971 lastidle = ast_tvnow(); 10972 } 10973 } else if ((haveidles < pri->minunused) && 10974 (activeidles > pri->minidle)) { 10975 /* Mark something for hangup if there is something 10976 that can be hungup */ 10977 for (x = pri->numchans; x >= 0; x--) { 10978 /* find a candidate channel */ 10979 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) { 10980 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10981 haveidles++; 10982 /* Stop if we have enough idle channels or 10983 can't spare any more active idle ones */ 10984 if ((haveidles >= pri->minunused) || 10985 (activeidles <= pri->minidle)) 10986 break; 10987 } 10988 } 10989 } 10990 } 10991 /* Start with reasonable max */ 10992 lowest = ast_tv(60, 0); 10993 for (i = 0; i < NUM_DCHANS; i++) { 10994 /* Find lowest available d-channel */ 10995 if (!pri->dchannels[i]) 10996 break; 10997 if ((next = pri_schedule_next(pri->dchans[i]))) { 10998 /* We need relative time here */ 10999 tv = ast_tvsub(*next, ast_tvnow()); 11000 if (tv.tv_sec < 0) { 11001 tv = ast_tv(0,0); 11002 } 11003 if (doidling || pri->resetting) { 11004 if (tv.tv_sec > 1) { 11005 tv = ast_tv(1, 0); 11006 } 11007 } else { 11008 if (tv.tv_sec > 60) { 11009 tv = ast_tv(60, 0); 11010 } 11011 } 11012 } else if (doidling || pri->resetting) { 11013 /* Make sure we stop at least once per second if we're 11014 monitoring idle channels */ 11015 tv = ast_tv(1,0); 11016 } else { 11017 /* Don't poll for more than 60 seconds */ 11018 tv = ast_tv(60, 0); 11019 } 11020 if (!i || ast_tvcmp(tv, lowest) < 0) { 11021 lowest = tv; 11022 } 11023 } 11024 ast_mutex_unlock(&pri->lock); 11025 11026 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 11027 pthread_testcancel(); 11028 e = NULL; 11029 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000); 11030 pthread_testcancel(); 11031 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 11032 11033 ast_mutex_lock(&pri->lock); 11034 if (!res) { 11035 for (which = 0; which < NUM_DCHANS; which++) { 11036 if (!pri->dchans[which]) 11037 break; 11038 /* Just a timeout, run the scheduler */ 11039 e = pri_schedule_run(pri->dchans[which]); 11040 if (e) 11041 break; 11042 } 11043 } else if (res > -1) { 11044 for (which = 0; which < NUM_DCHANS; which++) { 11045 if (!pri->dchans[which]) 11046 break; 11047 if (fds[which].revents & POLLPRI) { 11048 /* Check for an event */ 11049 x = 0; 11050 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x); 11051 if (x) { 11052 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); 11053 manager_event(EVENT_FLAG_SYSTEM, "PRIEvent", 11054 "PRIEvent: %s\r\n" 11055 "PRIEventCode: %d\r\n" 11056 "D-channel: %s\r\n" 11057 "Span: %d\r\n", 11058 event2str(x), 11059 x, 11060 pri_order(which), 11061 pri->span 11062 ); 11063 } 11064 /* Keep track of alarm state */ 11065 if (x == DAHDI_EVENT_ALARM) { 11066 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP); 11067 pri_find_dchan(pri); 11068 } else if (x == DAHDI_EVENT_NOALARM) { 11069 pri->dchanavail[which] |= DCHAN_NOTINALARM; 11070 pri_restart(pri->dchans[which]); 11071 } 11072 11073 ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span); 11074 } else if (fds[which].revents & POLLIN) { 11075 e = pri_check_event(pri->dchans[which]); 11076 } 11077 if (e) 11078 break; 11079 } 11080 } else if (errno != EINTR) 11081 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno)); 11082 11083 if (e) { 11084 if (pri->debug) 11085 pri_dump_event(pri->dchans[which], e); 11086 11087 if (e->e != PRI_EVENT_DCHAN_DOWN) { 11088 if (!(pri->dchanavail[which] & DCHAN_UP)) { 11089 ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span); 11090 } 11091 pri->dchanavail[which] |= DCHAN_UP; 11092 } else if (pri->sig != SIG_BRI_PTMP) { 11093 if (pri->dchanavail[which] & DCHAN_UP) { 11094 ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span); 11095 } 11096 pri->dchanavail[which] &= ~DCHAN_UP; 11097 } 11098 11099 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which])) 11100 /* Must be an NFAS group that has the secondary dchan active */ 11101 pri->pri = pri->dchans[which]; 11102 11103 switch (e->e) { 11104 case PRI_EVENT_DCHAN_UP: 11105 if (!pri->pri) pri_find_dchan(pri); 11106 11107 /* Note presense of D-channel */ 11108 time(&pri->lastreset); 11109 11110 /* Restart in 5 seconds */ 11111 if (pri->resetinterval > -1) { 11112 pri->lastreset -= pri->resetinterval; 11113 pri->lastreset += 5; 11114 } 11115 pri->resetting = 0; 11116 /* Take the channels from inalarm condition */ 11117 for (i = 0; i < pri->numchans; i++) 11118 if (pri->pvts[i]) { 11119 pri->pvts[i]->inalarm = 0; 11120 } 11121 break; 11122 case PRI_EVENT_DCHAN_DOWN: 11123 pri_find_dchan(pri); 11124 if (!pri_is_up(pri)) { 11125 pri->resetting = 0; 11126 /* Hangup active channels and put them in alarm mode */ 11127 for (i = 0; i < pri->numchans; i++) { 11128 struct dahdi_pvt *p = pri->pvts[i]; 11129 if (p) { 11130 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 11131 /* T309 is not enabled : hangup calls when alarm occurs */ 11132 if (p->call) { 11133 if (p->pri && p->pri->pri) { 11134 pri_hangup(p->pri->pri, p->call, -1); 11135 pri_destroycall(p->pri->pri, p->call); 11136 p->call = NULL; 11137 } else 11138 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n"); 11139 } 11140 if (p->realcall) { 11141 pri_hangup_all(p->realcall, pri); 11142 } else if (p->owner) 11143 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11144 } 11145 p->inalarm = 1; 11146 } 11147 } 11148 } 11149 break; 11150 case PRI_EVENT_RESTART: 11151 if (e->restart.channel > -1) { 11152 chanpos = pri_find_principle(pri, e->restart.channel); 11153 if (chanpos < 0) 11154 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 11155 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 11156 else { 11157 ast_verb(3, "B-channel %d/%d restarted on span %d\n", 11158 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 11159 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11160 if (pri->pvts[chanpos]->call) { 11161 pri_destroycall(pri->pri, pri->pvts[chanpos]->call); 11162 pri->pvts[chanpos]->call = NULL; 11163 } 11164 /* Force soft hangup if appropriate */ 11165 if (pri->pvts[chanpos]->realcall) 11166 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11167 else if (pri->pvts[chanpos]->owner) 11168 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11169 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11170 } 11171 } else { 11172 ast_verb(3, "Restart on requested on entire span %d\n", pri->span); 11173 for (x = 0; x < pri->numchans; x++) 11174 if (pri->pvts[x]) { 11175 ast_mutex_lock(&pri->pvts[x]->lock); 11176 if (pri->pvts[x]->call) { 11177 pri_destroycall(pri->pri, pri->pvts[x]->call); 11178 pri->pvts[x]->call = NULL; 11179 } 11180 if (pri->pvts[chanpos]->realcall) 11181 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11182 else if (pri->pvts[x]->owner) 11183 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11184 ast_mutex_unlock(&pri->pvts[x]->lock); 11185 } 11186 } 11187 break; 11188 case PRI_EVENT_KEYPAD_DIGIT: 11189 chanpos = pri_find_principle(pri, e->digit.channel); 11190 if (chanpos < 0) { 11191 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 11192 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span); 11193 } else { 11194 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call); 11195 if (chanpos > -1) { 11196 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11197 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */ 11198 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) { 11199 /* how to do that */ 11200 int digitlen = strlen(e->digit.digits); 11201 char digit; 11202 int i; 11203 for (i = 0; i < digitlen; i++) { 11204 digit = e->digit.digits[i]; 11205 { 11206 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 11207 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11208 } 11209 } 11210 } 11211 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11212 } 11213 } 11214 break; 11215 11216 case PRI_EVENT_INFO_RECEIVED: 11217 chanpos = pri_find_principle(pri, e->ring.channel); 11218 if (chanpos < 0) { 11219 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 11220 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11221 } else { 11222 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call); 11223 if (chanpos > -1) { 11224 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11225 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */ 11226 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) { 11227 /* how to do that */ 11228 int digitlen = strlen(e->ring.callednum); 11229 char digit; 11230 int i; 11231 for (i = 0; i < digitlen; i++) { 11232 digit = e->ring.callednum[i]; 11233 { 11234 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 11235 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11236 } 11237 } 11238 } 11239 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11240 } 11241 } 11242 break; 11243 case PRI_EVENT_RING: 11244 crv = NULL; 11245 if (e->ring.channel == -1) 11246 chanpos = pri_find_empty_chan(pri, 1); 11247 else 11248 chanpos = pri_find_principle(pri, e->ring.channel); 11249 /* if no channel specified find one empty */ 11250 if (chanpos < 0) { 11251 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 11252 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11253 } else { 11254 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11255 if (pri->pvts[chanpos]->owner) { 11256 if (pri->pvts[chanpos]->call == e->ring.call) { 11257 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 11258 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11259 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11260 break; 11261 } else { 11262 /* This is where we handle initial glare */ 11263 ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n", 11264 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11265 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11266 chanpos = -1; 11267 } 11268 } 11269 if (chanpos > -1) 11270 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11271 } 11272 if ((chanpos < 0) && (e->ring.flexible)) 11273 chanpos = pri_find_empty_chan(pri, 1); 11274 if (chanpos > -1) { 11275 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11276 if (pri->switchtype == PRI_SWITCH_GR303_TMC) { 11277 /* Should be safe to lock CRV AFAIK while bearer is still locked */ 11278 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL)); 11279 if (crv) 11280 ast_mutex_lock(&crv->lock); 11281 if (!crv || crv->owner) { 11282 pri->pvts[chanpos]->call = NULL; 11283 if (crv) { 11284 if (crv->owner) 11285 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11286 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); 11287 } else 11288 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); 11289 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE); 11290 if (crv) 11291 ast_mutex_unlock(&crv->lock); 11292 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11293 break; 11294 } 11295 } 11296 pri->pvts[chanpos]->call = e->ring.call; 11297 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan); 11298 if (pri->pvts[chanpos]->use_callerid) { 11299 ast_shrink_phone_number(plancallingnum); 11300 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num)); 11301 #ifdef PRI_ANI 11302 if (!ast_strlen_zero(e->ring.callingani)) { 11303 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani); 11304 ast_shrink_phone_number(plancallingani); 11305 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani)); 11306 } else { 11307 pri->pvts[chanpos]->cid_ani[0] = '\0'; 11308 } 11309 #endif 11310 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name)); 11311 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */ 11312 } else { 11313 pri->pvts[chanpos]->cid_num[0] = '\0'; 11314 pri->pvts[chanpos]->cid_ani[0] = '\0'; 11315 pri->pvts[chanpos]->cid_name[0] = '\0'; 11316 pri->pvts[chanpos]->cid_ton = 0; 11317 } 11318 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri, 11319 e->ring.redirectingnum, e->ring.callingplanrdnis); 11320 /* If immediate=yes go to s|1 */ 11321 if (pri->pvts[chanpos]->immediate) { 11322 ast_verb(3, "Going to extension s|1 because of immediate=yes\n"); 11323 pri->pvts[chanpos]->exten[0] = 's'; 11324 pri->pvts[chanpos]->exten[1] = '\0'; 11325 } 11326 /* Get called number */ 11327 else if (!ast_strlen_zero(e->ring.callednum)) { 11328 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten)); 11329 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 11330 } else if (pri->overlapdial) 11331 pri->pvts[chanpos]->exten[0] = '\0'; 11332 else { 11333 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */ 11334 pri->pvts[chanpos]->exten[0] = 's'; 11335 pri->pvts[chanpos]->exten[1] = '\0'; 11336 } 11337 /* Set DNID on all incoming calls -- even immediate */ 11338 if (!ast_strlen_zero(e->ring.callednum)) 11339 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 11340 /* No number yet, but received "sending complete"? */ 11341 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) { 11342 ast_verb(3, "Going to extension s|1 because of Complete received\n"); 11343 pri->pvts[chanpos]->exten[0] = 's'; 11344 pri->pvts[chanpos]->exten[1] = '\0'; 11345 } 11346 11347 /* Make sure extension exists (or in overlap dial mode, can exist) */ 11348 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) || 11349 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 11350 /* Setup law */ 11351 int law; 11352 if (pri->switchtype != PRI_SWITCH_GR303_TMC) { 11353 /* Set to audio mode at this point */ 11354 law = 1; 11355 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1) 11356 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno)); 11357 } 11358 if (e->ring.layer1 == PRI_LAYER_1_ALAW) 11359 law = DAHDI_LAW_ALAW; 11360 else 11361 law = DAHDI_LAW_MULAW; 11362 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law); 11363 if (res < 0) 11364 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel); 11365 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law); 11366 if (res < 0) 11367 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel); 11368 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 11369 /* Just announce proceeding */ 11370 pri->pvts[chanpos]->proceeding = 1; 11371 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0); 11372 } else { 11373 if (pri->switchtype != PRI_SWITCH_GR303_TMC) 11374 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 11375 else 11376 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 11377 } 11378 /* Get the use_callingpres state */ 11379 pri->pvts[chanpos]->callingpres = e->ring.callingpres; 11380 11381 /* Start PBX */ 11382 if (!e->ring.complete 11383 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) 11384 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 11385 /* 11386 * Release the PRI lock while we create the channel 11387 * so other threads can send D channel messages. 11388 */ 11389 ast_mutex_unlock(&pri->lock); 11390 if (crv) { 11391 /* Set bearer and such */ 11392 pri_assign_bearer(crv, pri, pri->pvts[chanpos]); 11393 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 11394 pri->pvts[chanpos]->owner = &inuse; 11395 ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel); 11396 } else { 11397 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 11398 } 11399 ast_mutex_lock(&pri->lock); 11400 if (c) { 11401 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 11402 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 11403 } 11404 if (e->ring.ani2 >= 0) { 11405 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2); 11406 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 11407 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2; 11408 } 11409 11410 #ifdef SUPPORT_USERUSER 11411 if (!ast_strlen_zero(e->ring.useruserinfo)) { 11412 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 11413 } 11414 #endif 11415 11416 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 11417 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 11418 if (e->ring.redirectingreason >= 0) 11419 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 11420 } 11421 if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) { 11422 ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n", 11423 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"), 11424 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11425 } else { 11426 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 11427 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11428 if (c) 11429 ast_hangup(c); 11430 else { 11431 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 11432 pri->pvts[chanpos]->call = NULL; 11433 } 11434 } 11435 } else { 11436 /* 11437 * Release the PRI lock while we create the channel 11438 * so other threads can send D channel messages. 11439 */ 11440 ast_mutex_unlock(&pri->lock); 11441 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype); 11442 ast_mutex_lock(&pri->lock); 11443 if (c) { 11444 /* 11445 * It is reasonably safe to set the following 11446 * channel variables while the PRI and DAHDI private 11447 * structures are locked. The PBX has not been 11448 * started yet and it is unlikely that any other task 11449 * will do anything with the channel we have just 11450 * created. 11451 */ 11452 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 11453 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 11454 } 11455 if (e->ring.ani2 >= 0) { 11456 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2); 11457 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 11458 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2; 11459 } 11460 11461 #ifdef SUPPORT_USERUSER 11462 if (!ast_strlen_zero(e->ring.useruserinfo)) { 11463 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 11464 } 11465 #endif 11466 11467 if (e->ring.redirectingreason >= 0) 11468 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 11469 11470 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 11471 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 11472 } 11473 if (c && !ast_pbx_start(c)) { 11474 ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n", 11475 plancallingnum, pri->pvts[chanpos]->exten, 11476 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11477 11478 dahdi_enable_ec(pri->pvts[chanpos]); 11479 } else { 11480 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 11481 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11482 if (c) { 11483 ast_hangup(c); 11484 } else { 11485 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 11486 pri->pvts[chanpos]->call = NULL; 11487 } 11488 } 11489 } 11490 } else { 11491 ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n", 11492 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 11493 pri->pvts[chanpos]->prioffset, pri->span); 11494 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED); 11495 pri->pvts[chanpos]->call = NULL; 11496 pri->pvts[chanpos]->exten[0] = '\0'; 11497 } 11498 if (crv) 11499 ast_mutex_unlock(&crv->lock); 11500 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11501 } else { 11502 if (e->ring.flexible) 11503 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION); 11504 else 11505 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL); 11506 } 11507 break; 11508 case PRI_EVENT_RINGING: 11509 chanpos = pri_find_principle(pri, e->ringing.channel); 11510 if (chanpos < 0) { 11511 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 11512 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 11513 } else { 11514 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call); 11515 if (chanpos < 0) { 11516 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 11517 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 11518 } else { 11519 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11520 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 11521 dahdi_enable_ec(pri->pvts[chanpos]); 11522 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1; 11523 pri->pvts[chanpos]->alerting = 1; 11524 } else 11525 ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n"); 11526 11527 #ifdef PRI_PROGRESS_MASK 11528 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) { 11529 #else 11530 if (e->ringing.progress == 8) { 11531 #endif 11532 /* Now we can do call progress detection */ 11533 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11534 /* RINGING detection isn't required because we got ALERTING signal */ 11535 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING); 11536 pri->pvts[chanpos]->dsp_features = 0; 11537 } 11538 } 11539 11540 #ifdef SUPPORT_USERUSER 11541 if (!ast_strlen_zero(e->ringing.useruserinfo)) { 11542 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11543 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11544 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo); 11545 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11546 } 11547 #endif 11548 11549 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11550 } 11551 } 11552 break; 11553 case PRI_EVENT_PROGRESS: 11554 /* Get chan value if e->e is not PRI_EVNT_RINGING */ 11555 chanpos = pri_find_principle(pri, e->proceeding.channel); 11556 if (chanpos > -1) { 11557 #ifdef PRI_PROGRESS_MASK 11558 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) { 11559 #else 11560 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) { 11561 #endif 11562 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, }; 11563 11564 if (e->proceeding.cause > -1) { 11565 ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause); 11566 11567 /* Work around broken, out of spec USER_BUSY cause in a progress message */ 11568 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) { 11569 if (pri->pvts[chanpos]->owner) { 11570 ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n"); 11571 11572 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause; 11573 f.subclass = AST_CONTROL_BUSY; 11574 } 11575 } 11576 } 11577 11578 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11579 ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n", 11580 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 11581 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11582 #ifdef PRI_PROGRESS_MASK 11583 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 11584 #else 11585 if (e->proceeding.progress == 8) { 11586 #endif 11587 /* Now we can do call progress detection */ 11588 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11589 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 11590 pri->pvts[chanpos]->dsp_features = 0; 11591 } 11592 /* Bring voice path up */ 11593 f.subclass = AST_CONTROL_PROGRESS; 11594 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11595 } 11596 pri->pvts[chanpos]->progress = 1; 11597 pri->pvts[chanpos]->dialing = 0; 11598 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11599 } 11600 } 11601 break; 11602 case PRI_EVENT_PROCEEDING: 11603 chanpos = pri_find_principle(pri, e->proceeding.channel); 11604 if (chanpos > -1) { 11605 if (!pri->pvts[chanpos]->proceeding) { 11606 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, }; 11607 11608 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11609 ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n", 11610 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 11611 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11612 #ifdef PRI_PROGRESS_MASK 11613 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 11614 #else 11615 if (e->proceeding.progress == 8) { 11616 #endif 11617 /* Now we can do call progress detection */ 11618 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11619 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 11620 pri->pvts[chanpos]->dsp_features = 0; 11621 } 11622 /* Bring voice path up */ 11623 f.subclass = AST_CONTROL_PROGRESS; 11624 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11625 } 11626 pri->pvts[chanpos]->proceeding = 1; 11627 pri->pvts[chanpos]->dialing = 0; 11628 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11629 } 11630 } 11631 break; 11632 case PRI_EVENT_FACNAME: 11633 chanpos = pri_find_principle(pri, e->facname.channel); 11634 if (chanpos < 0) { 11635 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 11636 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 11637 } else { 11638 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call); 11639 if (chanpos < 0) { 11640 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 11641 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 11642 } else { 11643 /* Re-use *69 field for PRI */ 11644 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11645 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num)); 11646 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name)); 11647 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1; 11648 dahdi_enable_ec(pri->pvts[chanpos]); 11649 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11650 } 11651 } 11652 break; 11653 case PRI_EVENT_ANSWER: 11654 chanpos = pri_find_principle(pri, e->answer.channel); 11655 if (chanpos < 0) { 11656 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 11657 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 11658 } else { 11659 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call); 11660 if (chanpos < 0) { 11661 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 11662 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 11663 } else { 11664 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11665 /* Now we can do call progress detection */ 11666 11667 /* We changed this so it turns on the DSP no matter what... progress or no progress. 11668 * By this time, we need DTMF detection and other features that were previously disabled 11669 * -- Matt F */ 11670 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11671 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 11672 pri->pvts[chanpos]->dsp_features = 0; 11673 } 11674 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) { 11675 ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n"); 11676 x = DAHDI_START; 11677 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 11678 if (res < 0) { 11679 if (errno != EINPROGRESS) { 11680 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 11681 } 11682 } 11683 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 11684 pri->pvts[chanpos]->dialing = 1; 11685 /* Send any "w" waited stuff */ 11686 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop); 11687 if (res < 0) { 11688 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno)); 11689 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 11690 } else 11691 ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr); 11692 11693 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 11694 } else if (pri->pvts[chanpos]->confirmanswer) { 11695 ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel); 11696 } else { 11697 pri->pvts[chanpos]->dialing = 0; 11698 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1; 11699 /* Enable echo cancellation if it's not on already */ 11700 dahdi_enable_ec(pri->pvts[chanpos]); 11701 } 11702 11703 #ifdef SUPPORT_USERUSER 11704 if (!ast_strlen_zero(e->answer.useruserinfo)) { 11705 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11706 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11707 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo); 11708 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11709 } 11710 #endif 11711 11712 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11713 } 11714 } 11715 break; 11716 case PRI_EVENT_HANGUP: 11717 chanpos = pri_find_principle(pri, e->hangup.channel); 11718 if (chanpos < 0) { 11719 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 11720 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11721 } else { 11722 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 11723 if (chanpos > -1) { 11724 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11725 if (!pri->pvts[chanpos]->alreadyhungup) { 11726 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */ 11727 pri->pvts[chanpos]->alreadyhungup = 1; 11728 if (pri->pvts[chanpos]->realcall) 11729 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11730 else if (pri->pvts[chanpos]->owner) { 11731 /* Queue a BUSY instead of a hangup if our cause is appropriate */ 11732 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 11733 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP) 11734 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11735 else { 11736 switch (e->hangup.cause) { 11737 case PRI_CAUSE_USER_BUSY: 11738 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 11739 break; 11740 case PRI_CAUSE_CALL_REJECTED: 11741 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 11742 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 11743 case PRI_CAUSE_SWITCH_CONGESTION: 11744 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 11745 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 11746 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 11747 break; 11748 default: 11749 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11750 } 11751 } 11752 } 11753 ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n", 11754 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause); 11755 } else { 11756 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 11757 pri->pvts[chanpos]->call = NULL; 11758 } 11759 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 11760 ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 11761 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11762 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 11763 pri->pvts[chanpos]->resetting = 1; 11764 } 11765 if (e->hangup.aoc_units > -1) 11766 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 11767 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 11768 11769 #ifdef SUPPORT_USERUSER 11770 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) { 11771 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11772 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11773 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 11774 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11775 } 11776 #endif 11777 11778 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11779 } else { 11780 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 11781 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11782 } 11783 } 11784 break; 11785 #ifndef PRI_EVENT_HANGUP_REQ 11786 #error please update libpri 11787 #endif 11788 case PRI_EVENT_HANGUP_REQ: 11789 chanpos = pri_find_principle(pri, e->hangup.channel); 11790 if (chanpos < 0) { 11791 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 11792 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11793 } else { 11794 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 11795 if (chanpos > -1) { 11796 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11797 if (pri->pvts[chanpos]->realcall) 11798 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11799 else if (pri->pvts[chanpos]->owner) { 11800 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 11801 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP) 11802 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11803 else { 11804 switch (e->hangup.cause) { 11805 case PRI_CAUSE_USER_BUSY: 11806 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 11807 break; 11808 case PRI_CAUSE_CALL_REJECTED: 11809 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 11810 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 11811 case PRI_CAUSE_SWITCH_CONGESTION: 11812 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 11813 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 11814 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 11815 break; 11816 default: 11817 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11818 } 11819 } 11820 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); 11821 if (e->hangup.aoc_units > -1) 11822 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 11823 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 11824 } else { 11825 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 11826 pri->pvts[chanpos]->call = NULL; 11827 } 11828 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 11829 ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n", 11830 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11831 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 11832 pri->pvts[chanpos]->resetting = 1; 11833 } 11834 11835 #ifdef SUPPORT_USERUSER 11836 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 11837 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11838 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11839 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 11840 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11841 } 11842 #endif 11843 11844 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11845 } else { 11846 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); 11847 } 11848 } 11849 break; 11850 case PRI_EVENT_HANGUP_ACK: 11851 chanpos = pri_find_principle(pri, e->hangup.channel); 11852 if (chanpos < 0) { 11853 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 11854 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11855 } else { 11856 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 11857 if (chanpos > -1) { 11858 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11859 pri->pvts[chanpos]->call = NULL; 11860 pri->pvts[chanpos]->resetting = 0; 11861 if (pri->pvts[chanpos]->owner) { 11862 ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11863 } 11864 11865 #ifdef SUPPORT_USERUSER 11866 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 11867 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11868 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11869 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 11870 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11871 } 11872 #endif 11873 11874 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11875 } 11876 } 11877 break; 11878 case PRI_EVENT_CONFIG_ERR: 11879 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err); 11880 break; 11881 case PRI_EVENT_RESTART_ACK: 11882 chanpos = pri_find_principle(pri, e->restartack.channel); 11883 if (chanpos < 0) { 11884 /* Sometime switches (e.g. I421 / British Telecom) don't give us the 11885 channel number, so we have to figure it out... This must be why 11886 everybody resets exactly a channel at a time. */ 11887 for (x = 0; x < pri->numchans; x++) { 11888 if (pri->pvts[x] && pri->pvts[x]->resetting) { 11889 chanpos = x; 11890 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11891 ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 11892 pri->pvts[chanpos]->prioffset, pri->span); 11893 if (pri->pvts[chanpos]->realcall) 11894 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11895 else if (pri->pvts[chanpos]->owner) { 11896 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 11897 pri->pvts[chanpos]->prioffset, pri->span); 11898 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11899 } 11900 pri->pvts[chanpos]->resetting = 0; 11901 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 11902 pri->pvts[chanpos]->prioffset, pri->span); 11903 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11904 if (pri->resetting) 11905 pri_check_restart(pri); 11906 break; 11907 } 11908 } 11909 if (chanpos < 0) { 11910 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 11911 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 11912 } 11913 } else { 11914 if (pri->pvts[chanpos]) { 11915 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11916 if (pri->pvts[chanpos]->realcall) 11917 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11918 else if (pri->pvts[chanpos]->owner) { 11919 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n", 11920 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 11921 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11922 } 11923 pri->pvts[chanpos]->resetting = 0; 11924 pri->pvts[chanpos]->inservice = 1; 11925 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 11926 pri->pvts[chanpos]->prioffset, pri->span); 11927 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11928 if (pri->resetting) 11929 pri_check_restart(pri); 11930 } 11931 } 11932 break; 11933 case PRI_EVENT_SETUP_ACK: 11934 chanpos = pri_find_principle(pri, e->setup_ack.channel); 11935 if (chanpos < 0) { 11936 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 11937 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span); 11938 } else { 11939 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call); 11940 if (chanpos > -1) { 11941 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11942 pri->pvts[chanpos]->setup_ack = 1; 11943 /* Send any queued digits */ 11944 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) { 11945 ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]); 11946 pri_information(pri->pri, pri->pvts[chanpos]->call, 11947 pri->pvts[chanpos]->dialdest[x]); 11948 } 11949 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11950 } else 11951 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel); 11952 } 11953 break; 11954 case PRI_EVENT_NOTIFY: 11955 chanpos = pri_find_principle(pri, e->notify.channel); 11956 if (chanpos < 0) { 11957 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n", 11958 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span); 11959 } else { 11960 struct ast_frame f = { AST_FRAME_CONTROL, }; 11961 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11962 switch (e->notify.info) { 11963 case PRI_NOTIFY_REMOTE_HOLD: 11964 f.subclass = AST_CONTROL_HOLD; 11965 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11966 break; 11967 case PRI_NOTIFY_REMOTE_RETRIEVAL: 11968 f.subclass = AST_CONTROL_UNHOLD; 11969 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11970 break; 11971 } 11972 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11973 } 11974 break; 11975 default: 11976 ast_debug(1, "Event: %d\n", e->e); 11977 } 11978 } 11979 ast_mutex_unlock(&pri->lock); 11980 } 11981 /* Never reached */ 11982 return NULL; 11983 }
Definition at line 10522 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 3346 of file chan_dahdi.c.
References ast_log(), DCHAN_AVAILABLE, dahdi_pri::dchanavail, dahdi_pri::dchannels, dahdi_pri::dchans, LOG_NOTICE, LOG_WARNING, NUM_DCHANS, and dahdi_pri::pri.
Referenced by pri_dchannel().
03347 { 03348 int oldslot = -1; 03349 struct pri *old; 03350 int newslot = -1; 03351 int x; 03352 old = pri->pri; 03353 for (x = 0; x < NUM_DCHANS; x++) { 03354 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0)) 03355 newslot = x; 03356 if (pri->dchans[x] == old) { 03357 oldslot = x; 03358 } 03359 } 03360 if (newslot < 0) { 03361 newslot = 0; 03362 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n", 03363 pri->dchannels[newslot]); 03364 } 03365 if (old && (oldslot != newslot)) 03366 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n", 03367 pri->dchannels[oldslot], pri->dchannels[newslot]); 03368 pri->pri = pri->dchans[newslot]; 03369 return 0; 03370 }
| static int pri_find_empty_chan | ( | struct dahdi_pri * | pri, | |
| int | backwards | |||
| ) | [static] |
Definition at line 9424 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().
09425 { 09426 int x; 09427 if (backwards) 09428 x = pri->numchans; 09429 else 09430 x = 0; 09431 for (;;) { 09432 if (backwards && (x < 0)) 09433 break; 09434 if (!backwards && (x >= pri->numchans)) 09435 break; 09436 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) { 09437 ast_debug(1, "Found empty available channel %d/%d\n", 09438 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset); 09439 return x; 09440 } 09441 if (backwards) 09442 x--; 09443 else 09444 x++; 09445 } 09446 return -1; 09447 }
| static int pri_find_principle | ( | struct dahdi_pri * | pri, | |
| int | channel | |||
| ) | [static] |
Definition at line 10535 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().
10536 { 10537 int x; 10538 int span = PRI_SPAN(channel); 10539 int spanfd; 10540 struct dahdi_params param; 10541 int principle = -1; 10542 int explicit = PRI_EXPLICIT(channel); 10543 channel = PRI_CHANNEL(channel); 10544 10545 if (!explicit) { 10546 spanfd = pri_active_dchan_fd(pri); 10547 memset(¶m, 0, sizeof(param)); 10548 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m)) 10549 return -1; 10550 span = pris[param.spanno - 1].prilogicalspan; 10551 } 10552 10553 for (x = 0; x < pri->numchans; x++) { 10554 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) { 10555 principle = x; 10556 break; 10557 } 10558 } 10559 10560 return principle; 10561 }
| static int pri_fixup_principle | ( | struct dahdi_pri * | pri, | |
| int | principle, | |||
| q931_call * | c | |||
| ) | [static] |
Definition at line 10563 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().
10564 { 10565 int x; 10566 struct dahdi_pvt *crv; 10567 if (!c) { 10568 if (principle < 0) 10569 return -1; 10570 return principle; 10571 } 10572 if ((principle > -1) && 10573 (principle < pri->numchans) && 10574 (pri->pvts[principle]) && 10575 (pri->pvts[principle]->call == c)) 10576 return principle; 10577 /* First, check for other bearers */ 10578 for (x = 0; x < pri->numchans; x++) { 10579 if (!pri->pvts[x]) 10580 continue; 10581 if (pri->pvts[x]->call == c) { 10582 /* Found our call */ 10583 if (principle != x) { 10584 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x]; 10585 10586 ast_verb(3, "Moving call from channel %d to channel %d\n", 10587 old->channel, new->channel); 10588 if (new->owner) { 10589 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n", 10590 old->channel, new->channel, new->channel); 10591 return -1; 10592 } 10593 /* Fix it all up now */ 10594 new->owner = old->owner; 10595 old->owner = NULL; 10596 if (new->owner) { 10597 ast_string_field_build(new->owner, name, 10598 "DAHDI/%d:%d-%d", pri->trunkgroup, 10599 new->channel, 1); 10600 new->owner->tech_pvt = new; 10601 ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd); 10602 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner; 10603 old->subs[SUB_REAL].owner = NULL; 10604 } else 10605 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); 10606 new->call = old->call; 10607 old->call = NULL; 10608 10609 /* Copy any DSP that may be present */ 10610 new->dsp = old->dsp; 10611 new->dsp_features = old->dsp_features; 10612 old->dsp = NULL; 10613 old->dsp_features = 0; 10614 } 10615 return principle; 10616 } 10617 } 10618 /* Now check for a CRV with no bearer */ 10619 crv = pri->crvs; 10620 while (crv) { 10621 if (crv->call == c) { 10622 /* This is our match... Perform some basic checks */ 10623 if (crv->bearer) 10624 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n"); 10625 else if (pri->pvts[principle]->owner) 10626 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n"); 10627 else { 10628 /* Looks good. Drop the pseudo channel now, clear up the assignment, and 10629 wakeup the potential sleeper */ 10630 dahdi_close_sub(crv, SUB_REAL); 10631 pri->pvts[principle]->call = crv->call; 10632 pri_assign_bearer(crv, pri, pri->pvts[principle]); 10633 ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n", 10634 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset, 10635 pri->trunkgroup, crv->channel); 10636 wakeup_sub(crv, SUB_REAL, pri); 10637 } 10638 return principle; 10639 } 10640 crv = crv->next; 10641 } 10642 ast_log(LOG_WARNING, "Call specified, but not found?\n"); 10643 return -1; 10644 }
Definition at line 1227 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(), and dahdi_write().
01228 { 01229 int res; 01230 /* Grab the lock first */ 01231 do { 01232 res = ast_mutex_trylock(&pri->lock); 01233 if (res) { 01234 DEADLOCK_AVOIDANCE(&pvt->lock); 01235 } 01236 } while (res); 01237 /* Then break the poll */ 01238 if (pri->master != AST_PTHREADT_NULL) 01239 pthread_kill(pri->master, SIGURG); 01240 return 0; 01241 }
Definition at line 10794 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().
10795 { 10796 int x; 10797 int redo; 10798 ast_mutex_unlock(&pri->lock); 10799 ast_mutex_lock(&p->lock); 10800 do { 10801 redo = 0; 10802 for (x = 0; x < 3; x++) { 10803 while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) { 10804 redo++; 10805 DEADLOCK_AVOIDANCE(&p->lock); 10806 } 10807 if (p->subs[x].owner) { 10808 ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED); 10809 ast_channel_unlock(p->subs[x].owner); 10810 } 10811 } 10812 } while (redo); 10813 ast_mutex_unlock(&p->lock); 10814 ast_mutex_lock(&pri->lock); 10815 return 0; 10816 }
| static int pri_is_up | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3294 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, and NUM_DCHANS.
Referenced by mkintf(), and pri_dchannel().
03295 { 03296 int x; 03297 for (x = 0; x < NUM_DCHANS; x++) { 03298 if (pri->dchanavail[x] == DCHAN_AVAILABLE) 03299 return 1; 03300 } 03301 return 0; 03302 }
| static char* pri_order | ( | int | level | ) | [static] |
Definition at line 3317 of file chan_dahdi.c.
Referenced by handle_pri_show_span(), and pri_dchannel().
| static void pri_rel | ( | struct dahdi_pri * | pri | ) | [inline, static] |
Definition at line 455 of file chan_dahdi.c.
References ast_mutex_unlock(), and dahdi_pri::lock.
Referenced by dahdi_answer(), dahdi_call(), dahdi_digit_begin(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_send_keypad_facility_exec(), and dahdi_write().
00456 { 00457 ast_mutex_unlock(&pri->lock); 00458 }
| static int pri_resolve_span | ( | int * | span, | |
| int | channel, | |||
| int | offset, | |||
| struct dahdi_spaninfo * | si | |||
| ) | [static] |
Definition at line 8550 of file chan_dahdi.c.
References ast_log(), DCHAN_PROVISIONED, dahdi_pri::dchanavail, dahdi_pri::dchannels, LOG_WARNING, dahdi_pri::mastertrunkgroup, NUM_SPANS, dahdi_pri::offset, pris, and dahdi_pri::span.
Referenced by mkintf().
08551 { 08552 int x; 08553 int trunkgroup; 08554 /* Get appropriate trunk group if there is one */ 08555 trunkgroup = pris[*span].mastertrunkgroup; 08556 if (trunkgroup) { 08557 /* Select a specific trunk group */ 08558 for (x = 0; x < NUM_SPANS; x++) { 08559 if (pris[x].trunkgroup == trunkgroup) { 08560 *span = x; 08561 return 0; 08562 } 08563 } 08564 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup); 08565 *span = -1; 08566 } else { 08567 if (pris[*span].trunkgroup) { 08568 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup); 08569 *span = -1; 08570 } else if (pris[*span].mastertrunkgroup) { 08571 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup); 08572 *span = -1; 08573 } else { 08574 if (si->totalchans == 31) { 08575 /* E1 */ 08576 pris[*span].dchannels[0] = 16 + offset; 08577 } else if (si->totalchans == 24) { 08578 /* T1 or J1 */ 08579 pris[*span].dchannels[0] = 24 + offset; 08580 } else if (si->totalchans == 3) { 08581 /* BRI */ 08582 pris[*span].dchannels[0] = 3 + offset; 08583 } else { 08584 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); 08585 *span = -1; 08586 return 0; 08587 } 08588 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED; 08589 pris[*span].offset = offset; 08590 pris[*span].span = *span + 1; 08591 } 08592 } 08593 return 0; 08594 }
| static int process_dahdi | ( | struct dahdi_chan_conf * | confp, | |
| const char * | cat, | |||
| struct ast_variable * | v, | |||
| int | reload, | |||
| int | options | |||
| ) | [static] |
Definition at line 14240 of file chan_dahdi.c.
References dahdi_pvt::accountcode, dahdi_pvt::adsi, dahdi_pvt::amaflags, dahdi_pvt::answeronpolarityswitch, ast_callerid_split(), ast_cdr_amaflags2int(), ast_copy_string(), ast_get_group(), ast_jb_read_conf(), ast_log(), ast_strdupa, ast_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, CALLPROGRESS_FAX_INCOMING, CALLPROGRESS_FAX_OUTGOING, CALLPROGRESS_PROGRESS, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, dahdi_pvt::cancallforward, dahdi_pvt::canpark, dahdi_chan_conf::chan, CHAN_PSEUDO, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_rxgain, CID_SIG_BELL, CID_SIG_DTMF, CID_SIG_SMDI, CID_SIG_V23, CID_SIG_V23_JP, dahdi_pvt::cid_signalling, dahdi_pvt::cid_start, CID_START_POLARITY, CID_START_POLARITY_IN, CID_START_RING, dahdi_pvt::context, ringContextData::contextData, dahdi_chan_conf_default(), DAHDI_OVERLAPDIAL_BOTH, DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_NONE, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_pvt::dahditrcallerid, dahdi_pri::dialplan, dahdi_pvt::drings, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echotraining, errno, dahdi_pri::facilityenable, 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(), LINKSET_FLAG_EXPLICITACM, dahdi_pri::localdialplan, dahdi_pri::localprefix, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, MAX_CHANLIST_LEN, 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_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_pvt::radio, distRingData::range, READ_SIZE, dahdi_pri::resetinterval, dahdi_pvt::restrictcid, distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::rxgain, dahdi_pvt::sendcalleridafter, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SFWINK, SIG_SS7, dahdi_chan_conf::smdi_port, dahdi_chan_conf::ss7, SS7_NAI_DYNAMIC, 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, ast_variable::value, and dahdi_pvt::vars.
Referenced by setup_dahdi().
14241 { 14242 struct dahdi_pvt *tmp; 14243 int y; 14244 int found_pseudo = 0; 14245 char dahdichan[MAX_CHANLIST_LEN] = {}; 14246 14247 for (; v; v = v->next) { 14248 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 14249 continue; 14250 14251 /* must have parkinglot in confp before build_channels is called */ 14252 if (!strcasecmp(v->name, "parkinglot")) { 14253 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot)); 14254 } 14255 14256 /* Create the interface list */ 14257 if (!strcasecmp(v->name, "channel") 14258 #ifdef HAVE_PRI 14259 || !strcasecmp(v->name, "crv") 14260 #endif 14261 ) { 14262 int iscrv; 14263 if (options & PROC_DAHDI_OPT_NOCHAN) { 14264 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value); 14265 continue; 14266 } 14267 iscrv = !strcasecmp(v->name, "crv"); 14268 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo)) 14269 return -1; 14270 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value); 14271 } else if (!strcasecmp(v->name, "buffers")) { 14272 int res; 14273 char policy[21] = ""; 14274 14275 res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy); 14276 if (res != 2) { 14277 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n"); 14278 confp->chan.buf_no = numbufs; 14279 continue; 14280 } 14281 if (confp->chan.buf_no < 0) 14282 confp->chan.buf_no = numbufs; 14283 if (!strcasecmp(policy, "full")) { 14284 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL; 14285 } else if (!strcasecmp(policy, "immediate")) { 14286 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE; 14287 } else { 14288 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy); 14289 } 14290 } else if (!strcasecmp(v->name, "dahdichan")) { 14291 ast_copy_string(dahdichan, v->value, sizeof(dahdichan)); 14292 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) { 14293 usedistinctiveringdetection = ast_true(v->value); 14294 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) { 14295 distinctiveringaftercid = ast_true(v->value); 14296 } else if (!strcasecmp(v->name, "dring1context")) { 14297 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData)); 14298 } else if (!strcasecmp(v->name, "dring2context")) { 14299 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData)); 14300 } else if (!strcasecmp(v->name, "dring3context")) { 14301 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData)); 14302 } else if (!strcasecmp(v->name, "dring1range")) { 14303 confp->chan.drings.ringnum[0].range = atoi(v->value); 14304 } else if (!strcasecmp(v->name, "dring2range")) { 14305 confp->chan.drings.ringnum[1].range = atoi(v->value); 14306 } else if (!strcasecmp(v->name, "dring3range")) { 14307 confp->chan.drings.ringnum[2].range = atoi(v->value); 14308 } else if (!strcasecmp(v->name, "dring1")) { 14309 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]); 14310 } else if (!strcasecmp(v->name, "dring2")) { 14311 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]); 14312 } else if (!strcasecmp(v->name, "dring3")) { 14313 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]); 14314 } else if (!strcasecmp(v->name, "usecallerid")) { 14315 confp->chan.use_callerid = ast_true(v->value); 14316 } else if (!strcasecmp(v->name, "cidsignalling")) { 14317 if (!strcasecmp(v->value, "bell")) 14318 confp->chan.cid_signalling = CID_SIG_BELL; 14319 else if (!strcasecmp(v->value, "v23")) 14320 confp->chan.cid_signalling = CID_SIG_V23; 14321 else if (!strcasecmp(v->value, "dtmf")) 14322 confp->chan.cid_signalling = CID_SIG_DTMF; 14323 else if (!strcasecmp(v->value, "smdi")) 14324 confp->chan.cid_signalling = CID_SIG_SMDI; 14325 else if (!strcasecmp(v->value, "v23_jp")) 14326 confp->chan.cid_signalling = CID_SIG_V23_JP; 14327 else if (ast_true(v->value)) 14328 confp->chan.cid_signalling = CID_SIG_BELL; 14329 } else if (!strcasecmp(v->name, "cidstart")) { 14330 if (!strcasecmp(v->value, "ring")) 14331 confp->chan.cid_start = CID_START_RING; 14332 else if (!strcasecmp(v->value, "polarity_in")) 14333 confp->chan.cid_start = CID_START_POLARITY_IN; 14334 else if (!strcasecmp(v->value, "polarity")) 14335 confp->chan.cid_start = CID_START_POLARITY; 14336 else if (ast_true(v->value)) 14337 confp->chan.cid_start = CID_START_RING; 14338 } else if (!strcasecmp(v->name, "threewaycalling")) { 14339 confp->chan.threewaycalling = ast_true(v->value); 14340 } else if (!strcasecmp(v->name, "cancallforward")) { 14341 confp->chan.cancallforward = ast_true(v->value); 14342 } else if (!strcasecmp(v->name, "relaxdtmf")) { 14343 if (ast_true(v->value)) 14344 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 14345 else 14346 confp->chan.dtmfrelax = 0; 14347 } else if (!strcasecmp(v->name, "mailbox")) { 14348 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox)); 14349 } else if (!strcasecmp(v->name, "hasvoicemail")) { 14350 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) { 14351 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox)); 14352 } 14353 } else if (!strcasecmp(v->name, "adsi")) { 14354 confp->chan.adsi = ast_true(v->value); 14355 } else if (!strcasecmp(v->name, "usesmdi")) { 14356 confp->chan.use_smdi = ast_true(v->value); 14357 } else if (!strcasecmp(v->name, "smdiport")) { 14358 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port)); 14359 } else if (!strcasecmp(v->name, "transfer")) { 14360 confp->chan.transfer = ast_true(v->value); 14361 } else if (!strcasecmp(v->name, "canpark")) { 14362 confp->chan.canpark = ast_true(v->value); 14363 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) { 14364 confp->chan.echocanbridged = ast_true(v->value); 14365 } else if (!strcasecmp(v->name, "busydetect")) { 14366 confp->chan.busydetect = ast_true(v->value); 14367 } else if (!strcasecmp(v->name, "busycount")) { 14368 confp->chan.busycount = atoi(v->value); 14369 } else if (!strcasecmp(v->name, "busypattern")) { 14370 if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) { 14371 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno); 14372 } 14373 } else if (!strcasecmp(v->name, "callprogress")) { 14374 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS; 14375 if (ast_true(v->value)) 14376 confp->chan.callprogress |= CALLPROGRESS_PROGRESS; 14377 } else if (!strcasecmp(v->name, "faxdetect")) { 14378 confp->chan.callprogress &= ~CALLPROGRESS_FAX; 14379 if (!strcasecmp(v->value, "incoming")) { 14380 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING; 14381 } else if (!strcasecmp(v->value, "outgoing")) { 14382 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING; 14383 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) 14384 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING; 14385 } else if (!strcasecmp(v->name, "echocancel")) { 14386 process_echocancel(confp, v->value, v->lineno); 14387 } else if (!strcasecmp(v->name, "echotraining")) { 14388 if (sscanf(v->value, "%30d", &y) == 1) { 14389 if ((y < 10) || (y > 4000)) { 14390 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno); 14391 } else { 14392 confp->chan.echotraining = y; 14393 } 14394 } else if (ast_true(v->value)) { 14395 confp->chan.echotraining = 400; 14396 } else 14397 confp->chan.echotraining = 0; 14398 } else if (!strcasecmp(v->name, "hidecallerid")) { 14399 confp->chan.hidecallerid = ast_true(v->value); 14400 } else if (!strcasecmp(v->name, "hidecalleridname")) { 14401 confp->chan.hidecalleridname = ast_true(v->value); 14402 } else if (!strcasecmp(v->name, "pulsedial")) { 14403 confp->chan.pulse = ast_true(v->value); 14404 } else if (!strcasecmp(v->name, "callreturn")) { 14405 confp->chan.callreturn = ast_true(v->value); 14406 } else if (!strcasecmp(v->name, "callwaiting")) { 14407 confp->chan.callwaiting = ast_true(v->value); 14408 } else if (!strcasecmp(v->name, "callwaitingcallerid")) { 14409 confp->chan.callwaitingcallerid = ast_true(v->value); 14410 } else if (!strcasecmp(v->name, "context")) { 14411 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context)); 14412 } else if (!strcasecmp(v->name, "language")) { 14413 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language)); 14414 } else if (!strcasecmp(v->name, "progzone")) { 14415 ast_copy_string(progzone, v->value, sizeof(progzone)); 14416 } else if (!strcasecmp(v->name, "mohinterpret") 14417 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) { 14418 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret)); 14419 } else if (!strcasecmp(v->name, "mohsuggest")) { 14420 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest)); 14421 } else if (!strcasecmp(v->name, "parkinglot")) { 14422 ast_copy_string(parkinglot, v->value, sizeof(parkinglot)); 14423 } else if (!strcasecmp(v->name, "stripmsd")) { 14424 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name); 14425 confp->chan.stripmsd = atoi(v->value); 14426 } else if (!strcasecmp(v->name, "jitterbuffers")) { 14427 numbufs = atoi(v->value); 14428 } else if (!strcasecmp(v->name, "group")) { 14429 confp->chan.group = ast_get_group(v->value); 14430 } else if (!strcasecmp(v->name, "callgroup")) { 14431 if (!strcasecmp(v->value, "none")) 14432 confp->chan.callgroup = 0; 14433 else 14434 confp->chan.callgroup = ast_get_group(v->value); 14435 } else if (!strcasecmp(v->name, "pickupgroup")) { 14436 if (!strcasecmp(v->value, "none")) 14437 confp->chan.pickupgroup = 0; 14438 else 14439 confp->chan.pickupgroup = ast_get_group(v->value); 14440 } else if (!strcasecmp(v->name, "setvar")) { 14441 char *varname = ast_strdupa(v->value), *varval = NULL; 14442 struct ast_variable *tmpvar; 14443 if (varname && (varval = strchr(varname, '='))) { 14444 *varval++ = '\0'; 14445 if ((tmpvar = ast_variable_new(varname, varval, ""))) { 14446 tmpvar->next = confp->chan.vars; 14447 confp->chan.vars = tmpvar; 14448 } 14449 } 14450 } else if (!strcasecmp(v->name, "immediate")) { 14451 confp->chan.immediate = ast_true(v->value); 14452 } else if (!strcasecmp(v->name, "transfertobusy")) { 14453 confp->chan.transfertobusy = ast_true(v->value); 14454 } else if (!strcasecmp(v->name, "mwimonitor")) { 14455 confp->chan.mwimonitor_neon = 0; 14456 confp->chan.mwimonitor_fsk = 0; 14457 confp->chan.mwimonitor_rpas = 0; 14458 if (strcasestr(v->value, "fsk")) { 14459 confp->chan.mwimonitor_fsk = 1; 14460 } 14461 if (strcasestr(v->value, "rpas")) { 14462 confp->chan.mwimonitor_rpas = 1; 14463 } 14464 if (strcasestr(v->value, "neon")) { 14465 confp->chan.mwimonitor_neon = 1; 14466 } 14467 /* If set to true or yes, assume that simple fsk is desired */ 14468 if (ast_true(v->value)) { 14469 confp->chan.mwimonitor_fsk = 1; 14470 } 14471 } else if (!strcasecmp(v->name, "cid_rxgain")) { 14472 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) { 14473 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno); 14474 } 14475 } else if (!strcasecmp(v->name, "rxgain")) { 14476 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) { 14477 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno); 14478 } 14479 } else if (!strcasecmp(v->name, "txgain")) { 14480 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) { 14481 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno); 14482 } 14483 } else if (!strcasecmp(v->name, "tonezone")) { 14484 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) { 14485 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno); 14486 } 14487 } else if (!strcasecmp(v->name, "callerid")) { 14488 if (!strcasecmp(v->value, "asreceived")) { 14489 confp->chan.cid_num[0] = '\0'; 14490 confp->chan.cid_name[0] = '\0'; 14491 } else { 14492 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num)); 14493 } 14494 } else if (!strcasecmp(v->name, "fullname")) { 14495 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name)); 14496 } else if (!strcasecmp(v->name, "cid_number")) { 14497 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num)); 14498 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) { 14499 confp->chan.dahditrcallerid = ast_true(v->value); 14500 } else if (!strcasecmp(v->name, "restrictcid")) { 14501 confp->chan.restrictcid = ast_true(v->value); 14502 } else if (!strcasecmp(v->name, "usecallingpres")) { 14503 confp->chan.use_callingpres = ast_true(v->value); 14504 } else if (!strcasecmp(v->name, "accountcode")) { 14505 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode)); 14506 } else if (!strcasecmp(v->name, "amaflags")) { 14507 y = ast_cdr_amaflags2int(v->value); 14508 if (y < 0) 14509 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno); 14510 else 14511 confp->chan.amaflags = y; 14512 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) { 14513 confp->chan.polarityonanswerdelay = atoi(v->value); 14514 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) { 14515 confp->chan.answeronpolarityswitch = ast_true(v->value); 14516 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) { 14517 confp->chan.hanguponpolarityswitch = ast_true(v->value); 14518 } else if (!strcasecmp(v->name, "sendcalleridafter")) { 14519 confp->chan.sendcalleridafter = atoi(v->value); 14520 } else if (!strcasecmp(v->name, "mwimonitornotify")) { 14521 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify)); 14522 } else if (!strcasecmp(v->name, "mwisendtype")) { 14523 if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */ 14524 mwisend_rpas = 1; 14525 } else { 14526 mwisend_rpas = 0; 14527 } 14528 } else if (reload != 1) { 14529 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) { 14530 int orig_radio = confp->chan.radio; 14531 int orig_outsigmod = confp->chan.outsigmod; 14532 int orig_auto = confp->is_sig_auto; 14533 14534 confp->chan.radio = 0; 14535 confp->chan.outsigmod = -1; 14536 confp->is_sig_auto = 0; 14537 if (!strcasecmp(v->value, "em")) { 14538 confp->chan.sig = SIG_EM; 14539 } else if (!strcasecmp(v->value, "em_e1")) { 14540 confp->chan.sig = SIG_EM_E1; 14541 } else if (!strcasecmp(v->value, "em_w")) { 14542 confp->chan.sig = SIG_EMWINK; 14543 } else if (!strcasecmp(v->value, "fxs_ls")) { 14544 confp->chan.sig = SIG_FXSLS; 14545 } else if (!strcasecmp(v->value, "fxs_gs")) { 14546 confp->chan.sig = SIG_FXSGS; 14547 } else if (!strcasecmp(v->value, "fxs_ks")) { 14548 confp->chan.sig = SIG_FXSKS; 14549 } else if (!strcasecmp(v->value, "fxo_ls")) { 14550 confp->chan.sig = SIG_FXOLS; 14551 } else if (!strcasecmp(v->value, "fxo_gs")) { 14552 confp->chan.sig = SIG_FXOGS; 14553 } else if (!strcasecmp(v->value, "fxo_ks")) { 14554 confp->chan.sig = SIG_FXOKS; 14555 } else if (!strcasecmp(v->value, "fxs_rx")) { 14556 confp->chan.sig = SIG_FXSKS; 14557 confp->chan.radio = 1; 14558 } else if (!strcasecmp(v->value, "fxo_rx")) { 14559 confp->chan.sig = SIG_FXOLS; 14560 confp->chan.radio = 1; 14561 } else if (!strcasecmp(v->value, "fxs_tx")) { 14562 confp->chan.sig = SIG_FXSLS; 14563 confp->chan.radio = 1; 14564 } else if (!strcasecmp(v->value, "fxo_tx")) { 14565 confp->chan.sig = SIG_FXOGS; 14566 confp->chan.radio = 1; 14567 } else if (!strcasecmp(v->value, "em_rx")) { 14568 confp->chan.sig = SIG_EM; 14569 confp->chan.radio = 1; 14570 } else if (!strcasecmp(v->value, "em_tx")) { 14571 confp->chan.sig = SIG_EM; 14572 confp->chan.radio = 1; 14573 } else if (!strcasecmp(v->value, "em_rxtx")) { 14574 confp->chan.sig = SIG_EM; 14575 confp->chan.radio = 2; 14576 } else if (!strcasecmp(v->value, "em_txrx")) { 14577 confp->chan.sig = SIG_EM; 14578 confp->chan.radio = 2; 14579 } else if (!strcasecmp(v->value, "sf")) { 14580 confp->chan.sig = SIG_SF; 14581 } else if (!strcasecmp(v->value, "sf_w")) { 14582 confp->chan.sig = SIG_SFWINK; 14583 } else if (!strcasecmp(v->value, "sf_featd")) { 14584 confp->chan.sig = SIG_FEATD; 14585 } else if (!strcasecmp(v->value, "sf_featdmf")) { 14586 confp->chan.sig = SIG_FEATDMF; 14587 } else if (!strcasecmp(v->value, "sf_featb")) { 14588 confp->chan.sig = SIG_SF_FEATB; 14589 } else if (!strcasecmp(v->value, "sf")) { 14590 confp->chan.sig = SIG_SF; 14591 } else if (!strcasecmp(v->value, "sf_rx")) { 14592 confp->chan.sig = SIG_SF; 14593 confp->chan.radio = 1; 14594 } else if (!strcasecmp(v->value, "sf_tx")) { 14595 confp->chan.sig = SIG_SF; 14596 confp->chan.radio = 1; 14597 } else if (!strcasecmp(v->value, "sf_rxtx")) { 14598 confp->chan.sig = SIG_SF; 14599 confp->chan.radio = 2; 14600 } else if (!strcasecmp(v->value, "sf_txrx")) { 14601 confp->chan.sig = SIG_SF; 14602 confp->chan.radio = 2; 14603 } else if (!strcasecmp(v->value, "featd")) { 14604 confp->chan.sig = SIG_FEATD; 14605 } else if (!strcasecmp(v->value, "featdmf")) { 14606 confp->chan.sig = SIG_FEATDMF; 14607 } else if (!strcasecmp(v->value, "featdmf_ta")) { 14608 confp->chan.sig = SIG_FEATDMF_TA; 14609 } else if (!strcasecmp(v->value, "e911")) { 14610 confp->chan.sig = SIG_E911; 14611 } else if (!strcasecmp(v->value, "fgccama")) { 14612 confp->chan.sig = SIG_FGC_CAMA; 14613 } else if (!strcasecmp(v->value, "fgccamamf")) { 14614 confp->chan.sig = SIG_FGC_CAMAMF; 14615 } else if (!strcasecmp(v->value, "featb")) { 14616 confp->chan.sig = SIG_FEATB; 14617 #ifdef HAVE_PRI 14618 } else if (!strcasecmp(v->value, "pri_net")) { 14619 confp->chan.sig = SIG_PRI; 14620 confp->pri.nodetype = PRI_NETWORK; 14621 } else if (!strcasecmp(v->value, "pri_cpe")) { 14622 confp->chan.sig = SIG_PRI; 14623 confp->pri.nodetype = PRI_CPE; 14624 } else if (!strcasecmp(v->value, "bri_cpe")) { 14625 confp->chan.sig = SIG_BRI; 14626 confp->pri.nodetype = PRI_CPE; 14627 } else if (!strcasecmp(v->value, "bri_net")) { 14628 confp->chan.sig = SIG_BRI; 14629 confp->pri.nodetype = PRI_NETWORK; 14630 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) { 14631 confp->chan.sig = SIG_BRI_PTMP; 14632 confp->pri.nodetype = PRI_CPE; 14633 } else if (!strcasecmp(v->value, "bri_net_ptmp")) { 14634 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno); 14635 } else if (!strcasecmp(v->value, "gr303fxoks_net")) { 14636 confp->chan.sig = SIG_GR303FXOKS; 14637 confp->pri.nodetype = PRI_NETWORK; 14638 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) { 14639 confp->chan.sig = SIG_GR303FXSKS; 14640 confp->pri.nodetype = PRI_CPE; 14641 #endif 14642 #ifdef HAVE_SS7 14643 } else if (!strcasecmp(v->value, "ss7")) { 14644 confp->chan.sig = SIG_SS7; 14645 #endif 14646 } else if (!strcasecmp(v->value, "auto")) { 14647 confp->is_sig_auto = 1; 14648 } else { 14649 confp->chan.outsigmod = orig_outsigmod; 14650 confp->chan.radio = orig_radio; 14651 confp->is_sig_auto = orig_auto; 14652 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 14653 } 14654 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) { 14655 if (!strcasecmp(v->value, "em")) { 14656 confp->chan.outsigmod = SIG_EM; 14657 } else if (!strcasecmp(v->value, "em_e1")) { 14658 confp->chan.outsigmod = SIG_EM_E1; 14659 } else if (!strcasecmp(v->value, "em_w")) { 14660 confp->chan.outsigmod = SIG_EMWINK; 14661 } else if (!strcasecmp(v->value, "sf")) { 14662 confp->chan.outsigmod = SIG_SF; 14663 } else if (!strcasecmp(v->value, "sf_w")) { 14664 confp->chan.outsigmod = SIG_SFWINK; 14665 } else if (!strcasecmp(v->value, "sf_featd")) { 14666 confp->chan.outsigmod = SIG_FEATD; 14667 } else if (!strcasecmp(v->value, "sf_featdmf")) { 14668 confp->chan.outsigmod = SIG_FEATDMF; 14669 } else if (!strcasecmp(v->value, "sf_featb")) { 14670 confp->chan.outsigmod = SIG_SF_FEATB; 14671 } else if (!strcasecmp(v->value, "sf")) { 14672 confp->chan.outsigmod = SIG_SF; 14673 } else if (!strcasecmp(v->value, "featd")) { 14674 confp->chan.outsigmod = SIG_FEATD; 14675 } else if (!strcasecmp(v->value, "featdmf")) { 14676 confp->chan.outsigmod = SIG_FEATDMF; 14677 } else if (!strcasecmp(v->value, "featdmf_ta")) { 14678 confp->chan.outsigmod = SIG_FEATDMF_TA; 14679 } else if (!strcasecmp(v->value, "e911")) { 14680 confp->chan.outsigmod = SIG_E911; 14681 } else if (!strcasecmp(v->value, "fgccama")) { 14682 confp->chan.outsigmod = SIG_FGC_CAMA; 14683 } else if (!strcasecmp(v->value, "fgccamamf")) { 14684 confp->chan.outsigmod = SIG_FGC_CAMAMF; 14685 } else if (!strcasecmp(v->value, "featb")) { 14686 confp->chan.outsigmod = SIG_FEATB; 14687 } else { 14688 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 14689 } 14690 #ifdef HAVE_PRI 14691 } else if (!strcasecmp(v->name, "pridialplan")) { 14692 if (!strcasecmp(v->value, "national")) { 14693 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1; 14694 } else if (!strcasecmp(v->value, "unknown")) { 14695 confp->pri.dialplan = PRI_UNKNOWN + 1; 14696 } else if (!strcasecmp(v->value, "private")) { 14697 confp->pri.dialplan = PRI_PRIVATE + 1; 14698 } else if (!strcasecmp(v->value, "international")) { 14699 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1; 14700 } else if (!strcasecmp(v->value, "local")) { 14701 confp->pri.dialplan = PRI_LOCAL_ISDN + 1; 14702 } else if (!strcasecmp(v->value, "dynamic")) { 14703 confp->pri.dialplan = -1; 14704 } else if (!strcasecmp(v->value, "redundant")) { 14705 confp->pri.dialplan = -2; 14706 } else { 14707 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 14708 } 14709 } else if (!strcasecmp(v->name, "prilocaldialplan")) { 14710 if (!strcasecmp(v->value, "national")) { 14711 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1; 14712 } else if (!strcasecmp(v->value, "unknown")) { 14713 confp->pri.localdialplan = PRI_UNKNOWN + 1; 14714 } else if (!strcasecmp(v->value, "private")) { 14715 confp->pri.localdialplan = PRI_PRIVATE + 1; 14716 } else if (!strcasecmp(v->value, "international")) { 14717 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1; 14718 } else if (!strcasecmp(v->value, "local")) { 14719 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1; 14720 } else if (!strcasecmp(v->value, "dynamic")) { 14721 confp->pri.localdialplan = -1; 14722 } else if (!strcasecmp(v->value, "redundant")) { 14723 confp->pri.localdialplan = -2; 14724 } else { 14725 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno); 14726 } 14727 } else if (!strcasecmp(v->name, "switchtype")) { 14728 if (!strcasecmp(v->value, "national")) 14729 confp->pri.switchtype = PRI_SWITCH_NI2; 14730 else if (!strcasecmp(v->value, "ni1")) 14731 confp->pri.switchtype = PRI_SWITCH_NI1; 14732 else if (!strcasecmp(v->value, "dms100")) 14733 confp->pri.switchtype = PRI_SWITCH_DMS100; 14734 else if (!strcasecmp(v->value, "4ess")) 14735 confp->pri.switchtype = PRI_SWITCH_ATT4ESS; 14736 else if (!strcasecmp(v->value, "5ess")) 14737 confp->pri.switchtype = PRI_SWITCH_LUCENT5E; 14738 else if (!strcasecmp(v->value, "euroisdn")) 14739 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1; 14740 else if (!strcasecmp(v->value, "qsig")) 14741 confp->pri.switchtype = PRI_SWITCH_QSIG; 14742 else { 14743 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno); 14744 return -1; 14745 } 14746 } else if (!strcasecmp(v->name, "nsf")) { 14747 if (!strcasecmp(v->value, "sdn")) 14748 confp->pri.nsf = PRI_NSF_SDN; 14749 else if (!strcasecmp(v->value, "megacom")) 14750 confp->pri.nsf = PRI_NSF_MEGACOM; 14751 else if (!strcasecmp(v->value, "tollfreemegacom")) 14752 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM; 14753 else if (!strcasecmp(v->value, "accunet")) 14754 confp->pri.nsf = PRI_NSF_ACCUNET; 14755 else if (!strcasecmp(v->value, "none")) 14756 confp->pri.nsf = PRI_NSF_NONE; 14757 else { 14758 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno); 14759 confp->pri.nsf = PRI_NSF_NONE; 14760 } 14761 } else if (!strcasecmp(v->name, "priindication")) { 14762 if (!strcasecmp(v->value, "outofband")) 14763 confp->chan.priindication_oob = 1; 14764 else if (!strcasecmp(v->value, "inband")) 14765 confp->chan.priindication_oob = 0; 14766 else 14767 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n", 14768 v->value, v->lineno); 14769 } else if (!strcasecmp(v->name, "priexclusive")) { 14770 confp->chan.priexclusive = ast_true(v->value); 14771 } else if (!strcasecmp(v->name, "internationalprefix")) { 14772 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix)); 14773 } else if (!strcasecmp(v->name, "nationalprefix")) { 14774 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix)); 14775 } else if (!strcasecmp(v->name, "localprefix")) { 14776 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix)); 14777 } else if (!strcasecmp(v->name, "privateprefix")) { 14778 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix)); 14779 } else if (!strcasecmp(v->name, "unknownprefix")) { 14780 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix)); 14781 } else if (!strcasecmp(v->name, "resetinterval")) { 14782 if (!strcasecmp(v->value, "never")) 14783 confp->pri.resetinterval = -1; 14784 else if (atoi(v->value) >= 60) 14785 confp->pri.resetinterval = atoi(v->value); 14786 else 14787 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n", 14788 v->value, v->lineno); 14789 } else if (!strcasecmp(v->name, "minunused")) { 14790 confp->pri.minunused = atoi(v->value); 14791 } else if (!strcasecmp(v->name, "minidle")) { 14792 confp->pri.minidle = atoi(v->value); 14793 } else if (!strcasecmp(v->name, "idleext")) { 14794 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext)); 14795 } else if (!strcasecmp(v->name, "idledial")) { 14796 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial)); 14797 } else if (!strcasecmp(v->name, "overlapdial")) { 14798 if (ast_true(v->value)) { 14799 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 14800 } else if (!strcasecmp(v->value, "incoming")) { 14801 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING; 14802 } else if (!strcasecmp(v->value, "outgoing")) { 14803 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING; 14804 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) { 14805 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 14806 } else { 14807 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE; 14808 } 14809 #ifdef HAVE_PRI_INBANDDISCONNECT 14810 } else if (!strcasecmp(v->name, "inbanddisconnect")) { 14811 confp->pri.inbanddisconnect = ast_true(v->value); 14812 #endif 14813 } else if (!strcasecmp(v->name, "pritimer")) { 14814 #ifdef PRI_GETSET_TIMERS 14815 char tmp[20]; 14816 char *timerc; 14817 char *c; 14818 int timer; 14819 int timeridx; 14820 14821 ast_copy_string(tmp, v->value, sizeof(tmp)); 14822 c = tmp; 14823 timerc = strsep(&c, ","); 14824 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) { 14825 timeridx = pri_timer2idx(timerc); 14826 timer = atoi(c); 14827 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) { 14828 ast_log(LOG_WARNING, 14829 "'%s' is not a valid ISDN timer at line %d.\n", timerc, 14830 v->lineno); 14831 } else if (!timer) { 14832 ast_log(LOG_WARNING, 14833 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n", 14834 c, timerc, v->lineno); 14835 } else { 14836 pritimers[timeridx] = timer; 14837 } 14838 } else { 14839 ast_log(LOG_WARNING, 14840 "'%s' is not a valid ISDN timer configuration string at line %d.\n", 14841 v->value, v->lineno); 14842 } 14843 14844 } else if (!strcasecmp(v->name, "facilityenable")) { 14845 confp->pri.facilityenable = ast_true(v->value); 14846 #endif /* PRI_GETSET_TIMERS */ 14847 #endif /* HAVE_PRI */ 14848 #ifdef HAVE_SS7 14849 } else if (!strcasecmp(v->name, "ss7type")) { 14850 if (!strcasecmp(v->value, "itu")) { 14851 cur_ss7type = SS7_ITU; 14852 } else if (!strcasecmp(v->value, "ansi")) { 14853 cur_ss7type = SS7_ANSI; 14854 } else 14855 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno); 14856 } else if (!strcasecmp(v->name, "linkset")) { 14857 cur_linkset = atoi(v->value); 14858 } else if (!strcasecmp(v->name, "pointcode")) { 14859 cur_pointcode = parse_pointcode(v->value); 14860 } else if (!strcasecmp(v->name, "adjpointcode")) { 14861 cur_adjpointcode = parse_pointcode(v->value); 14862 } else if (!strcasecmp(v->name, "defaultdpc")) { 14863 cur_defaultdpc = parse_pointcode(v->value); 14864 } else if (!strcasecmp(v->name, "cicbeginswith")) { 14865 cur_cicbeginswith = atoi(v->value); 14866 } else if (!strcasecmp(v->name, "networkindicator")) { 14867 if (!strcasecmp(v->value, "national")) 14868 cur_networkindicator = SS7_NI_NAT; 14869 else if (!strcasecmp(v->value, "national_spare")) 14870 cur_networkindicator = SS7_NI_NAT_SPARE; 14871 else if (!strcasecmp(v->value, "international")) 14872 cur_networkindicator = SS7_NI_INT; 14873 else if (!strcasecmp(v->value, "international_spare")) 14874 cur_networkindicator = SS7_NI_INT_SPARE; 14875 else 14876 cur_networkindicator = -1; 14877 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) { 14878 ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix)); 14879 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) { 14880 ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix)); 14881 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) { 14882 ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix)); 14883 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) { 14884 ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix)); 14885 } else if (!strcasecmp(v->name, "ss7_called_nai")) { 14886 if (!strcasecmp(v->value, "national")) { 14887 confp->ss7.called_nai = SS7_NAI_NATIONAL; 14888 } else if (!strcasecmp(v->value, "international")) { 14889 confp->ss7.called_nai = SS7_NAI_INTERNATIONAL; 14890 } else if (!strcasecmp(v->value, "subscriber")) { 14891 confp->ss7.called_nai = SS7_NAI_SUBSCRIBER; 14892 } else if (!strcasecmp(v->value, "dynamic")) { 14893 confp->ss7.called_nai = SS7_NAI_DYNAMIC; 14894 } else { 14895 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno); 14896 } 14897 } else if (!strcasecmp(v->name, "ss7_calling_nai")) { 14898 if (!strcasecmp(v->value, "national")) { 14899 confp->ss7.calling_nai = SS7_NAI_NATIONAL; 14900 } else if (!strcasecmp(v->value, "international")) { 14901 confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL; 14902 } else if (!strcasecmp(v->value, "subscriber")) { 14903 confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER; 14904 } else if (!strcasecmp(v->value, "dynamic")) { 14905 confp->ss7.calling_nai = SS7_NAI_DYNAMIC; 14906 } else { 14907 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno); 14908 } 14909 } else if (!strcasecmp(v->name, "sigchan")) { 14910 int sigchan, res; 14911 sigchan = atoi(v->value); 14912 res = linkset_addsigchan(sigchan); 14913 if (res < 0) 14914 return -1; 14915 14916 } else if (!strcasecmp(v->name, "ss7_explicitacm")) { 14917 struct dahdi_ss7 *link; 14918 link = ss7_resolve_linkset(cur_linkset); 14919 if (!link) { 14920 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1); 14921 return -1; 14922 } 14923 if (ast_true(v->value)) 14924 link->flags |= LINKSET_FLAG_EXPLICITACM; 14925 14926 #endif /* HAVE_SS7 */ 14927 } else if (!strcasecmp(v->name, "cadence")) { 14928 /* setup to scan our argument */ 14929 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 14930 int i; 14931 struct dahdi_ring_cadence new_cadence; 14932 int cid_location = -1; 14933 int firstcadencepos = 0; 14934 char original_args[80]; 14935 int cadence_is_ok = 1; 14936 14937 ast_copy_string(original_args, v->value, sizeof(original_args)); 14938 /* 16 cadences allowed (8 pairs) */ 14939 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]); 14940 14941 /* Cadence must be even (on/off) */ 14942 if (element_count % 2 == 1) { 14943 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno); 14944 cadence_is_ok = 0; 14945 } 14946 14947 /* Ring cadences cannot be negative */ 14948 for (i = 0; i < element_count; i++) { 14949 if (c[i] == 0) { 14950 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno); 14951 cadence_is_ok = 0; 14952 break; 14953 } else if (c[i] < 0) { 14954 if (i % 2 == 1) { 14955 /* Silence duration, negative possibly okay */ 14956 if (cid_location == -1) { 14957 cid_location = i; 14958 c[i] *= -1; 14959 } else { 14960 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno); 14961 cadence_is_ok = 0; 14962 break; 14963 } 14964 } else { 14965 if (firstcadencepos == 0) { 14966 firstcadencepos = i; /* only recorded to avoid duplicate specification */ 14967 /* duration will be passed negative to the DAHDI driver */ 14968 } else { 14969 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno); 14970 cadence_is_ok = 0; 14971 break; 14972 } 14973 } 14974 } 14975 } 14976 14977 /* Substitute our scanned cadence */ 14978 for (i = 0; i < 16; i++) { 14979 new_cadence.ringcadence[i] = c[i]; 14980 } 14981 14982 if (cadence_is_ok) { 14983 /* ---we scanned it without getting annoyed; now some sanity checks--- */ 14984 if (element_count < 2) { 14985 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno); 14986 } else { 14987 if (cid_location == -1) { 14988 /* user didn't say; default to first pause */ 14989 cid_location = 1; 14990 } else { 14991 /* convert element_index to cidrings value */ 14992 cid_location = (cid_location + 1) / 2; 14993 } 14994 /* ---we like their cadence; try to install it--- */ 14995 if (!user_has_defined_cadences++) 14996 /* this is the first user-defined cadence; clear the default user cadences */ 14997 num_cadence = 0; 14998 if ((num_cadence+1) >= NUM_CADENCE_MAX) 14999 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno); 15000 else { 15001 cadences[num_cadence] = new_cadence; 15002 cidrings[num_cadence++] = cid_location; 15003 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args); 15004 } 15005 } 15006 } 15007 } else if (!strcasecmp(v->name, "ringtimeout")) { 15008 ringt_base = (atoi(v->value) * 8) / READ_SIZE; 15009 } else if (!strcasecmp(v->name, "prewink")) { 15010 confp->timing.prewinktime = atoi(v->value); 15011 } else if (!strcasecmp(v->name, "preflash")) { 15012 confp->timing.preflashtime = atoi(v->value); 15013 } else if (!strcasecmp(v->name, "wink")) { 15014 confp->timing.winktime = atoi(v->value); 15015 } else if (!strcasecmp(v->name, "flash")) { 15016 confp->timing.flashtime = atoi(v->value); 15017 } else if (!strcasecmp(v->name, "start")) { 15018 confp->timing.starttime = atoi(v->value); 15019 } else if (!strcasecmp(v->name, "rxwink")) { 15020 confp->timing.rxwinktime = atoi(v->value); 15021 } else if (!strcasecmp(v->name, "rxflash")) { 15022 confp->timing.rxflashtime = atoi(v->value); 15023 } else if (!strcasecmp(v->name, "debounce")) { 15024 confp->timing.debouncetime = atoi(v->value); 15025 } else if (!strcasecmp(v->name, "toneduration")) { 15026 int toneduration; 15027 int ctlfd; 15028 int res; 15029 struct dahdi_dialparams dps; 15030 15031 ctlfd = open("/dev/dahdi/ctl", O_RDWR); 15032 if (ctlfd == -1) { 15033 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno); 15034 return -1; 15035 } 15036 15037 toneduration = atoi(v->value); 15038 if (toneduration > -1) { 15039 memset(&dps, 0, sizeof(dps)); 15040 15041 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration; 15042 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps); 15043 if (res < 0) { 15044 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno)); 15045 return -1; 15046 } 15047 } 15048 close(ctlfd); 15049 } else if (!strcasecmp(v->name, "defaultcic")) { 15050 ast_copy_string(defaultcic, v->value, sizeof(defaultcic)); 15051 } else if (!strcasecmp(v->name, "defaultozz")) { 15052 ast_copy_string(defaultozz, v->value, sizeof(defaultozz)); 15053 } else if (!strcasecmp(v->name, "mwilevel")) { 15054 mwilevel = atoi(v->value); 15055 } 15056 } else if (!(options & PROC_DAHDI_OPT_NOWARN) ) 15057 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno); 15058 } 15059 if (dahdichan[0]) { 15060 /* The user has set 'dahdichan' */ 15061 /*< \todo pass proper line number instead of 0 */ 15062 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) { 15063 return -1; 15064 } 15065 } 15066 /*< \todo why check for the pseudo in the per-channel section. 15067 * Any actual use for manual setup of the pseudo channel? */ 15068 if (!found_pseudo && reload != 1) { 15069 /* use the default configuration for a channel, so 15070 that any settings from real configured channels 15071 don't "leak" into the pseudo channel config 15072 */ 15073 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 15074 15075 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload); 15076 15077 if (tmp) { 15078 ast_verb(3, "Automatically generated pseudo channel\n"); 15079 } else { 15080 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n"); 15081 } 15082 } 15083 return 0; 15084 }
| static void process_echocancel | ( | struct dahdi_chan_conf * | confp, | |
| const char * | data, | |||
| unsigned int | line | |||
| ) | [static] |
Definition at line 14184 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, dahdi_pvt::params, and parse().
Referenced by process_dahdi().
14185 { 14186 char *parse = ast_strdupa(data); 14187 char *params[DAHDI_MAX_ECHOCANPARAMS + 1]; 14188 unsigned int param_count; 14189 unsigned int x; 14190 14191 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params)))) 14192 return; 14193 14194 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel)); 14195 14196 /* first parameter is tap length, process it here */ 14197 14198 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]); 14199 14200 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024)) 14201 confp->chan.echocancel.head.tap_length = x; 14202 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0]))) 14203 confp->chan.echocancel.head.tap_length = 128; 14204 14205 /* now process any remaining parameters */ 14206 14207 for (x = 1; x < param_count; x++) { 14208 struct { 14209 char *name; 14210 char *value; 14211 } param; 14212 14213 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) { 14214 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]); 14215 continue; 14216 } 14217 14218 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) { 14219 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name); 14220 continue; 14221 } 14222 14223 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name); 14224 14225 if (param.value) { 14226 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) { 14227 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value); 14228 continue; 14229 } 14230 } 14231 confp->chan.echocancel.head.param_count++; 14232 } 14233 }
| static char* redirectingreason2str | ( | int | redirectingreason | ) | [static] |
Definition at line 10818 of file chan_dahdi.c.
Referenced by pri_dchannel().
| static int reload | ( | void | ) | [static] |
Definition at line 15454 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and setup_dahdi().
15455 { 15456 int res = 0; 15457 15458 res = setup_dahdi(1); 15459 if (res) { 15460 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n"); 15461 return -1; 15462 } 15463 return 0; 15464 }
| static int reset_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1934 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().
01935 { 01936 p->confno = -1; 01937 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf)); 01938 if (p->subs[SUB_REAL].dfd > -1) { 01939 struct dahdi_confinfo zi; 01940 01941 memset(&zi, 0, sizeof(zi)); 01942 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi)) 01943 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno)); 01944 } 01945 return 0; 01946 }
| static int restart_monitor | ( | void | ) | [static] |
Definition at line 8523 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().
08524 { 08525 /* If we're supposed to be stopped -- stay stopped */ 08526 if (monitor_thread == AST_PTHREADT_STOP) 08527 return 0; 08528 ast_mutex_lock(&monlock); 08529 if (monitor_thread == pthread_self()) { 08530 ast_mutex_unlock(&monlock); 08531 ast_log(LOG_WARNING, "Cannot kill myself\n"); 08532 return -1; 08533 } 08534 if (monitor_thread != AST_PTHREADT_NULL) { 08535 /* Wake up the thread */ 08536 pthread_kill(monitor_thread, SIGURG); 08537 } else { 08538 /* Start a new monitor */ 08539 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 08540 ast_mutex_unlock(&monlock); 08541 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 08542 return -1; 08543 } 08544 } 08545 ast_mutex_unlock(&monlock); 08546 return 0; 08547 }
| static int restore_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2313 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().
02314 { 02315 int res; 02316 if (p->saveconf.confmode) { 02317 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf); 02318 p->saveconf.confmode = 0; 02319 if (res) { 02320 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno)); 02321 return -1; 02322 } 02323 } 02324 ast_debug(1, "Restored conferencing\n"); 02325 return 0; 02326 }
| static int restore_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2194 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().
02195 { 02196 int res; 02197 02198 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02199 if (res) { 02200 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno)); 02201 return -1; 02202 } 02203 02204 return 0; 02205 }
| static int save_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2240 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().
02241 { 02242 struct dahdi_confinfo c; 02243 int res; 02244 if (p->saveconf.confmode) { 02245 ast_log(LOG_WARNING, "Can't save conference -- already in use\n"); 02246 return -1; 02247 } 02248 p->saveconf.chan = 0; 02249 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf); 02250 if (res) { 02251 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno)); 02252 p->saveconf.confmode = 0; 02253 return -1; 02254 } 02255 memset(&c, 0, sizeof(c)); 02256 c.confmode = DAHDI_CONF_NORMAL; 02257 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c); 02258 if (res) { 02259 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno)); 02260 return -1; 02261 } 02262 ast_debug(1, "Disabled conferencing\n"); 02263 return 0; 02264 }
| static int send_callerid | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2370 of file chan_dahdi.c.
References ast_free, ast_log(), dahdi_pvt::callwaitcas, CIDCW_EXPIRE_SAMPLES, dahdi_pvt::cidcwexpire, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_setlinear(), 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().
02371 { 02372 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */ 02373 int res; 02374 /* Take out of linear mode if necessary */ 02375 if (p->subs[SUB_REAL].linear) { 02376 p->subs[SUB_REAL].linear = 0; 02377 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 02378 } 02379 while (p->cidpos < p->cidlen) { 02380 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos); 02381 if (res < 0) { 02382 if (errno == EAGAIN) 02383 return 0; 02384 else { 02385 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 02386 return -1; 02387 } 02388 } 02389 if (!res) 02390 return 0; 02391 p->cidpos += res; 02392 } 02393 ast_free(p->cidspill); 02394 p->cidspill = NULL; 02395 if (p->callwaitcas) { 02396 /* Wait for CID/CW to expire */ 02397 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES; 02398 } else 02399 restore_conference(p); 02400 return 0; 02401 }
| static int send_cwcidspill | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2330 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().
02331 { 02332 p->callwaitcas = 0; 02333 p->cidcwexpire = 0; 02334 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) 02335 return -1; 02336 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p)); 02337 /* Make sure we account for the end */ 02338 p->cidlen += READ_SIZE * 4; 02339 p->cidpos = 0; 02340 send_callerid(p); 02341 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num); 02342 return 0; 02343 }
| static int set_actual_gain | ( | int | fd, | |
| int | chan, | |||
| float | rxgain, | |||
| float | txgain, | |||
| int | law | |||
| ) | [static] |
Definition at line 2175 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().
02176 { 02177 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law); 02178 }
| static int set_actual_rxgain | ( | int | fd, | |
| int | chan, | |||
| float | gain, | |||
| int | law | |||
| ) | [static] |
Definition at line 2157 of file chan_dahdi.c.
References ast_debug, errno, and fill_rxgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
02158 { 02159 struct dahdi_gains g; 02160 int res; 02161 02162 memset(&g, 0, sizeof(g)); 02163 g.chan = chan; 02164 res = ioctl(fd, DAHDI_GETGAINS, &g); 02165 if (res) { 02166 ast_debug(1, "Failed to read gains: %s\n", strerror(errno)); 02167 return res; 02168 } 02169 02170 fill_rxgain(&g, gain, law); 02171 02172 return ioctl(fd, DAHDI_SETGAINS, &g); 02173 }
| static int set_actual_txgain | ( | int | fd, | |
| int | chan, | |||
| float | gain, | |||
| int | law | |||
| ) | [static] |
Definition at line 2139 of file chan_dahdi.c.
References ast_debug, errno, and fill_txgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
02140 { 02141 struct dahdi_gains g; 02142 int res; 02143 02144 memset(&g, 0, sizeof(g)); 02145 g.chan = chan; 02146 res = ioctl(fd, DAHDI_GETGAINS, &g); 02147 if (res) { 02148 ast_debug(1, "Failed to read gains: %s\n", strerror(errno)); 02149 return res; 02150 } 02151 02152 fill_txgain(&g, gain, law); 02153 02154 return ioctl(fd, DAHDI_SETGAINS, &g); 02155 }
| static int setup_dahdi | ( | int | reload | ) | [static] |
Definition at line 15086 of file chan_dahdi.c.
References ast_category_browse(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEUNCHANGED, dahdi_chan_conf_default(), global_jbconf, iflock, ast_variable::lineno, linksets, LOG_ERROR, LOG_NOTICE, LOG_WARNING, master, ast_variable::name, ast_variable::next, NUM_SPANS, pri_create_spanmap(), pri_create_trunkgroup(), pris, PROC_DAHDI_OPT_NOCHAN, PROC_DAHDI_OPT_NOWARN, process_dahdi(), pvts, restart_monitor(), ss7_linkset(), start_pri(), and ast_variable::value.
Referenced by dahdi_restart(), load_module(), and reload().
15087 { 15088 struct ast_config *cfg, *ucfg; 15089 struct ast_variable *v; 15090 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default(); 15091 struct dahdi_chan_conf conf; 15092 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 15093 const char *cat; 15094 int res; 15095 15096 #ifdef HAVE_PRI 15097 char *c; 15098 int spanno; 15099 int i; 15100 int logicalspan; 15101 int trunkgroup; 15102 int dchannels[NUM_DCHANS]; 15103 #endif 15104 15105 cfg = ast_config_load(config, config_flags); 15106 15107 /* Error if we have no config file */ 15108 if (!cfg) { 15109 ast_log(LOG_ERROR, "Unable to load config %s\n", config); 15110 return 0; 15111 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 15112 ucfg = ast_config_load("users.conf", config_flags); 15113 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) 15114 return 0; 15115 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 15116 cfg = ast_config_load(config, config_flags); 15117 } else { 15118 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 15119 ucfg = ast_config_load("users.conf", config_flags); 15120 } 15121 15122 /* It's a little silly to lock it, but we mind as well just to be sure */ 15123 ast_mutex_lock(&iflock); 15124 #ifdef HAVE_PRI 15125 if (reload != 1) { 15126 /* Process trunkgroups first */ 15127 v = ast_variable_browse(cfg, "trunkgroups"); 15128 while (v) { 15129 if (!strcasecmp(v->name, "trunkgroup")) { 15130 trunkgroup = atoi(v->value); 15131 if (trunkgroup > 0) { 15132 if ((c = strchr(v->value, ','))) { 15133 i = 0; 15134 memset(dchannels, 0, sizeof(dchannels)); 15135 while (c && (i < NUM_DCHANS)) { 15136 dchannels[i] = atoi(c + 1); 15137 if (dchannels[i] < 0) { 15138 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); 15139 } else 15140 i++; 15141 c = strchr(c + 1, ','); 15142 } 15143 if (i) { 15144 if (pri_create_trunkgroup(trunkgroup, dchannels)) { 15145 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); 15146 } else 15147 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"); 15148 } else 15149 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 15150 } else 15151 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 15152 } else 15153 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno); 15154 } else if (!strcasecmp(v->name, "spanmap")) { 15155 spanno = atoi(v->value); 15156 if (spanno > 0) { 15157 if ((c = strchr(v->value, ','))) { 15158 trunkgroup = atoi(c + 1); 15159 if (trunkgroup > 0) { 15160 if ((c = strchr(c + 1, ','))) 15161 logicalspan = atoi(c + 1); 15162 else 15163 logicalspan = 0; 15164 if (logicalspan >= 0) { 15165 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { 15166 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 15167 } else 15168 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 15169 } else 15170 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); 15171 } else 15172 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno); 15173 } else 15174 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno); 15175 } else 15176 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno); 15177 } else { 15178 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); 15179 } 15180 v = v->next; 15181 } 15182 } 15183 #endif 15184 15185 /* Copy the default jb config over global_jbconf */ 15186 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf)); 15187 15188 mwimonitornotify[0] = '\0'; 15189 15190 v = ast_variable_browse(cfg, "channels"); 15191 if ((res = process_dahdi(&base_conf, "", v, reload, 0))) { 15192 ast_mutex_unlock(&iflock); 15193 ast_config_destroy(cfg); 15194 if (ucfg) { 15195 ast_config_destroy(ucfg); 15196 } 15197 return res; 15198 } 15199 15200 /* Now get configuration from all normal sections in chan_dahdi.conf: */ 15201 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) { 15202 /* [channels] and [trunkgroups] are used. Let's also reserve 15203 * [globals] and [general] for future use 15204 */ 15205 if (!strcasecmp(cat, "general") || 15206 !strcasecmp(cat, "trunkgroups") || 15207 !strcasecmp(cat, "globals") || 15208 !strcasecmp(cat, "channels")) { 15209 continue; 15210 } 15211 15212 memcpy(&conf, &base_conf, sizeof(conf)); 15213 15214 if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) { 15215 ast_mutex_unlock(&iflock); 15216 ast_config_destroy(cfg); 15217 if (ucfg) { 15218 ast_config_destroy(cfg); 15219 } 15220 return res; 15221 } 15222 } 15223 15224 ast_config_destroy(cfg); 15225 15226 if (ucfg) { 15227 const char *chans; 15228 15229 process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0); 15230 15231 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) { 15232 if (!strcasecmp(cat, "general")) { 15233 continue; 15234 } 15235 15236 chans = ast_variable_retrieve(ucfg, cat, "dahdichan"); 15237 15238 if (ast_strlen_zero(chans)) { 15239 continue; 15240 } 15241 15242 memcpy(&conf, &base_conf, sizeof(conf)); 15243 15244 if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) { 15245 ast_config_destroy(ucfg); 15246 ast_mutex_unlock(&iflock); 15247 return res; 15248 } 15249 } 15250 ast_config_destroy(ucfg); 15251 } 15252 ast_mutex_unlock(&iflock); 15253 15254 #ifdef HAVE_PRI 15255 if (reload != 1) { 15256 int x; 15257 for (x = 0; x < NUM_SPANS; x++) { 15258 if (pris[x].pvts[0]) { 15259 if (start_pri(pris + x)) { 15260 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1); 15261 return -1; 15262 } else 15263 ast_verb(2, "Starting D-Channel on span %d\n", x + 1); 15264 } 15265 } 15266 } 15267 #endif 15268 #ifdef HAVE_SS7 15269 if (reload != 1) { 15270 int x; 15271 for (x = 0; x < NUM_SPANS; x++) { 15272 if (linksets[x].ss7) { 15273 if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) { 15274 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1); 15275 return -1; 15276 } else 15277 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1); 15278 } 15279 } 15280 } 15281 #endif 15282 /* And start the monitor for the first time */ 15283 restart_monitor(); 15284 return 0; 15285 }
| static int sigtype_to_signalling | ( | int | sigtype | ) | [static] |
Definition at line 8702 of file chan_dahdi.c.
Referenced by mkintf().
| 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 9925 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().
09926 { 09927 if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */ 09928 if (size) { 09929 *buf = '\0'; 09930 } 09931 return; 09932 } 09933 switch (nai) { 09934 case SS7_NAI_INTERNATIONAL: 09935 snprintf(buf, size, "%s%s", ss7->internationalprefix, number); 09936 break; 09937 case SS7_NAI_NATIONAL: 09938 snprintf(buf, size, "%s%s", ss7->nationalprefix, number); 09939 break; 09940 case SS7_NAI_SUBSCRIBER: 09941 snprintf(buf, size, "%s%s", ss7->subscriberprefix, number); 09942 break; 09943 case SS7_NAI_UNKNOWN: 09944 snprintf(buf, size, "%s%s", ss7->unknownprefix, number); 09945 break; 09946 default: 09947 snprintf(buf, size, "%s", number); 09948 break; 09949 } 09950 }
| 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 9744 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().
09745 { 09746 int i; 09747 09748 for (i = 0; i < linkset->numchans; i++) { 09749 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) { 09750 if (state) { 09751 if (state[i]) 09752 linkset->pvts[i]->remotelyblocked = block; 09753 } else 09754 linkset->pvts[i]->remotelyblocked = block; 09755 } 09756 } 09757 }
| static int ss7_find_cic | ( | struct dahdi_ss7 * | linkset, | |
| int | cic, | |||
| unsigned int | dpc | |||
| ) | [static] |
Definition at line 9699 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 1250 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().
01251 { 01252 int res; 01253 /* Grab the lock first */ 01254 do { 01255 res = ast_mutex_trylock(&pri->lock); 01256 if (res) { 01257 DEADLOCK_AVOIDANCE(&pvt->lock); 01258 } 01259 } while (res); 01260 /* Then break the poll */ 01261 if (pri->master != AST_PTHREADT_NULL) 01262 pthread_kill(pri->master, SIGURG); 01263 return 0; 01264 }
| static void ss7_handle_cqm | ( | struct dahdi_ss7 * | linkset, | |
| int | startcic, | |||
| int | endcic, | |||
| unsigned int | dpc | |||
| ) | [static] |
Definition at line 9712 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().
09713 { 09714 unsigned char status[32]; 09715 struct dahdi_pvt *p = NULL; 09716 int i, offset; 09717 09718 for (i = 0; i < linkset->numchans; i++) { 09719 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) { 09720 p = linkset->pvts[i]; 09721 offset = p->cic - startcic; 09722 status[offset] = 0; 09723 if (p->locallyblocked) 09724 status[offset] |= (1 << 0) | (1 << 4); 09725 if (p->remotelyblocked) 09726 status[offset] |= (1 << 1) | (1 << 5); 09727 if (p->ss7call) { 09728 if (p->outgoing) 09729 status[offset] |= (1 << 3); 09730 else 09731 status[offset] |= (1 << 2); 09732 } else 09733 status[offset] |= 0x3 << 2; 09734 } 09735 } 09736 09737 if (p) 09738 isup_cqr(linkset->ss7, startcic, endcic, dpc, status); 09739 else 09740 ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n"); 09741 09742 }
| static void ss7_inservice | ( | struct dahdi_ss7 * | linkset, | |
| int | startcic, | |||
| int | endcic, | |||
| unsigned int | dpc | |||
| ) | [static] |
Definition at line 9759 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 9956 of file chan_dahdi.c.
References ast_channel::_softhangup, dahdi_pvt::alerting, dahdi_pvt::alreadyhungup, AST_CAUSE_UNALLOCATED, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, ast_copy_string(), ast_debug, ast_dsp_set_features(), ast_exists_extension(), AST_FRAME_CONTROL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SOFTHANGUP_DEV, 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, LINKSTATE_STARTING, LINKSTATE_UP, 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_inservice(), ss7_pres_scr2cid_pres(), ss7_reset_linkset(), ss7_start_call(), dahdi_pvt::ss7call, dahdi_ss7::state, SUB_REAL, dahdi_pvt::subs, tv, and dahdi_pvt::use_callerid.
Referenced by setup_dahdi().
09957 { 09958 int res, i; 09959 struct timeval *next = NULL, tv; 09960 struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data; 09961 struct ss7 *ss7 = linkset->ss7; 09962 ss7_event *e = NULL; 09963 struct dahdi_pvt *p; 09964 int chanpos; 09965 struct pollfd pollers[NUM_DCHANS]; 09966 int cic; 09967 unsigned int dpc; 09968 int nextms = 0; 09969 09970 ss7_start(ss7); 09971 09972 while(1) { 09973 ast_mutex_lock(&linkset->lock); 09974 if ((next = ss7_schedule_next(ss7))) { 09975 tv = ast_tvnow(); 09976 tv.tv_sec = next->tv_sec - tv.tv_sec; 09977 tv.tv_usec = next->tv_usec - tv.tv_usec; 09978 if (tv.tv_usec < 0) { 09979 tv.tv_usec += 1000000; 09980 tv.tv_sec -= 1; 09981 } 09982 if (tv.tv_sec < 0) { 09983 tv.tv_sec = 0; 09984 tv.tv_usec = 0; 09985 } 09986 nextms = tv.tv_sec * 1000; 09987 nextms += tv.tv_usec / 1000; 09988 } 09989 ast_mutex_unlock(&linkset->lock); 09990 09991 for (i = 0; i < linkset->numsigchans; i++) { 09992 pollers[i].fd = linkset->fds[i]; 09993 pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]); 09994 pollers[i].revents = 0; 09995 } 09996 09997 res = poll(pollers, linkset->numsigchans, nextms); 09998 if ((res < 0) && (errno != EINTR)) { 09999 ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno)); 10000 } else if (!res) { 10001 ast_mutex_lock(&linkset->lock); 10002 ss7_schedule_run(ss7); 10003 ast_mutex_unlock(&linkset->lock); 10004 continue; 10005 } 10006 10007 ast_mutex_lock(&linkset->lock); 10008 for (i = 0; i < linkset->numsigchans; i++) { 10009 if (pollers[i].revents & POLLPRI) { 10010 int x; 10011 if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) { 10012 ast_log(LOG_ERROR, "Error in exception retrieval!\n"); 10013 } 10014 switch (x) { 10015 case DAHDI_EVENT_OVERRUN: 10016 ast_debug(1, "Overrun detected!\n"); 10017 break; 10018 case DAHDI_EVENT_BADFCS: 10019 ast_debug(1, "Bad FCS\n"); 10020 break; 10021 case DAHDI_EVENT_ABORT: 10022 ast_debug(1, "HDLC Abort\n"); 10023 break; 10024 case DAHDI_EVENT_ALARM: 10025 ast_log(LOG_ERROR, "Alarm on link!\n"); 10026 linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM); 10027 linkset->linkstate[i] &= ~LINKSTATE_UP; 10028 ss7_link_alarm(ss7, pollers[i].fd); 10029 break; 10030 case DAHDI_EVENT_NOALARM: 10031 ast_log(LOG_ERROR, "Alarm cleared on link\n"); 10032 linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN); 10033 linkset->linkstate[i] |= LINKSTATE_STARTING; 10034 ss7_link_noalarm(ss7, pollers[i].fd); 10035 break; 10036 default: 10037 ast_log(LOG_ERROR, "Got exception %d!\n", x); 10038 break; 10039 } 10040 } 10041 10042 if (pollers[i].revents & POLLIN) { 10043 ast_mutex_lock(&linkset->lock); 10044 res = ss7_read(ss7, pollers[i].fd); 10045 ast_mutex_unlock(&linkset->lock); 10046 } 10047 10048 if (pollers[i].revents & POLLOUT) { 10049 ast_mutex_lock(&linkset->lock); 10050 res = ss7_write(ss7, pollers[i].fd); 10051 ast_mutex_unlock(&linkset->lock); 10052 if (res < 0) { 10053 ast_debug(1, "Error in write %s\n", strerror(errno)); 10054 } 10055 } 10056 } 10057 10058 while ((e = ss7_check_event(ss7))) { 10059 switch (e->e) { 10060 case SS7_EVENT_UP: 10061 if (linkset->state != LINKSET_STATE_UP) { 10062 ast_verbose("--- SS7 Up ---\n"); 10063 ss7_reset_linkset(linkset); 10064 } 10065 linkset->state = LINKSET_STATE_UP; 10066 break; 10067 case SS7_EVENT_DOWN: 10068 ast_verbose("--- SS7 Down ---\n"); 10069 linkset->state = LINKSET_STATE_DOWN; 10070 for (i = 0; i < linkset->numchans; i++) { 10071 struct dahdi_pvt *p = linkset->pvts[i]; 10072 if (p) 10073 p->inalarm = 1; 10074 } 10075 break; 10076 case MTP2_LINK_UP: 10077 ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data); 10078 break; 10079 case MTP2_LINK_DOWN: 10080 ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data); 10081 break; 10082 case ISUP_EVENT_CPG: 10083 chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc); 10084 if (chanpos < 0) { 10085 ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic); 10086 break; 10087 } 10088 p = linkset->pvts[chanpos]; 10089 ast_mutex_lock(&p->lock); 10090 switch (e->cpg.event) { 10091 case CPG_EVENT_ALERTING: 10092 p->alerting = 1; 10093 p->subs[SUB_REAL].needringing = 1; 10094 break; 10095 case CPG_EVENT_PROGRESS: 10096 case CPG_EVENT_INBANDINFO: 10097 { 10098 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, }; 10099 ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic); 10100 dahdi_queue_frame(p, &f, linkset); 10101 p->progress = 1; 10102 p->dialing = 0; 10103 if (p->dsp && p->dsp_features) { 10104 ast_dsp_set_features(p->dsp, p->dsp_features); 10105 p->dsp_features = 0; 10106 } 10107 } 10108 break; 10109 default: 10110 ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event); 10111 } 10112 10113 ast_mutex_unlock(&p->lock); 10114 break; 10115 case ISUP_EVENT_RSC: 10116 ast_verbose("Resetting CIC %d\n", e->rsc.cic); 10117 chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc); 10118 if (chanpos < 0) { 10119 ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic); 10120 break; 10121 } 10122 p = linkset->pvts[chanpos]; 10123 ast_mutex_lock(&p->lock); 10124 p->inservice = 1; 10125 p->remotelyblocked = 0; 10126 dpc = p->dpc; 10127 isup_set_call_dpc(e->rsc.call, dpc); 10128 if (p->ss7call) 10129 p->ss7call = NULL; 10130 if (p->owner) 10131 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10132 ast_mutex_unlock(&p->lock); 10133 isup_rlc(ss7, e->rsc.call); 10134 break; 10135 case ISUP_EVENT_GRS: 10136 ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic); 10137 chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc); 10138 if (chanpos < 0) { 10139 ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic); 10140 break; 10141 } 10142 p = linkset->pvts[chanpos]; 10143 isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc); 10144 ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0); 10145 break; 10146 case ISUP_EVENT_CQM: 10147 ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic); 10148 ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc); 10149 break; 10150 case ISUP_EVENT_GRA: 10151 ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic); 10152 ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc); 10153 ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1); 10154 break; 10155 case ISUP_EVENT_IAM: 10156 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); 10157 chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc); 10158 if (chanpos < 0) { 10159 ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic); 10160 isup_rel(ss7, e->iam.call, -1); 10161 break; 10162 } 10163 p = linkset->pvts[chanpos]; 10164 ast_mutex_lock(&p->lock); 10165 if (p->owner) { 10166 if (p->ss7call == e->iam.call) { 10167 ast_mutex_unlock(&p->lock); 10168 ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic); 10169 break; 10170 } else { 10171 ast_mutex_unlock(&p->lock); 10172 ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic); 10173 break; 10174 } 10175 } 10176 10177 dpc = p->dpc; 10178 p->ss7call = e->iam.call; 10179 isup_set_call_dpc(p->ss7call, dpc); 10180 10181 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) { 10182 ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai); 10183 p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind); 10184 } else 10185 p->cid_num[0] = 0; 10186 10187 if (p->immediate) { 10188 p->exten[0] = 's'; 10189 p->exten[1] = '\0'; 10190 } else if (!ast_strlen_zero(e->iam.called_party_num)) { 10191 char *st; 10192 ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai); 10193 st = strchr(p->exten, '#'); 10194 if (st) 10195 *st = '\0'; 10196 } else 10197 p->exten[0] = '\0'; 10198 10199 p->cid_ani[0] = '\0'; 10200 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name))) 10201 ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name)); 10202 else 10203 p->cid_name[0] = '\0'; 10204 10205 p->cid_ani2 = e->iam.oli_ani2; 10206 p->cid_ton = 0; 10207 ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number)); 10208 ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number)); 10209 p->gen_add_type = e->iam.gen_add_type; 10210 p->gen_add_nai = e->iam.gen_add_nai; 10211 p->gen_add_pres_ind = e->iam.gen_add_pres_ind; 10212 p->gen_add_num_plan = e->iam.gen_add_num_plan; 10213 ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number)); 10214 p->gen_dig_type = e->iam.gen_dig_type; 10215 p->gen_dig_scheme = e->iam.gen_dig_scheme; 10216 ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number)); 10217 ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num)); 10218 ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num)); 10219 ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name)); 10220 p->calling_party_cat = e->iam.calling_party_cat; 10221 10222 /* Set DNID */ 10223 if (!ast_strlen_zero(e->iam.called_party_num)) 10224 ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai); 10225 10226 if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) { 10227 10228 if (e->iam.cot_check_required) { 10229 dahdi_loopback(p, 1); 10230 } else 10231 ss7_start_call(p, linkset); 10232 } else { 10233 ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten); 10234 p->alreadyhungup = 1; 10235 isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED); 10236 } 10237 ast_mutex_unlock(&p->lock); 10238 break; 10239 case ISUP_EVENT_COT: 10240 chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc); 10241 if (chanpos < 0) { 10242 ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic); 10243 isup_rel(ss7, e->cot.call, -1); 10244 break; 10245 } 10246 p = linkset->pvts[chanpos]; 10247 10248 ast_mutex_lock(&p->lock); 10249 10250 if (p->loopedback) { 10251 dahdi_loopback(p, 0); 10252 ss7_start_call(p, linkset); 10253 } 10254 10255 ast_mutex_unlock(&p->lock); 10256 10257 break; 10258 case ISUP_EVENT_CCR: 10259 ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic); 10260 chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc); 10261 if (chanpos < 0) { 10262 ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic); 10263 break; 10264 } 10265 10266 p = linkset->pvts[chanpos]; 10267 10268 ast_mutex_lock(&p->lock); 10269 dahdi_loopback(p, 1); 10270 ast_mutex_unlock(&p->lock); 10271 10272 isup_lpa(linkset->ss7, e->ccr.cic, p->dpc); 10273 break; 10274 case ISUP_EVENT_CVT: 10275 ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic); 10276 chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc); 10277 if (chanpos < 0) { 10278 ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic); 10279 break; 10280 } 10281 10282 p = linkset->pvts[chanpos]; 10283 10284 ast_mutex_lock(&p->lock); 10285 dahdi_loopback(p, 1); 10286 ast_mutex_unlock(&p->lock); 10287 10288 isup_cvr(linkset->ss7, e->cvt.cic, p->dpc); 10289 break; 10290 case ISUP_EVENT_REL: 10291 chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc); 10292 if (chanpos < 0) { 10293 ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic); 10294 break; 10295 } 10296 p = linkset->pvts[chanpos]; 10297 ast_mutex_lock(&p->lock); 10298 if (p->owner) { 10299 p->owner->hangupcause = e->rel.cause; 10300 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10301 } else if (!p->restartpending) 10302 ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic); 10303 10304 /* End the loopback if we have one */ 10305 dahdi_loopback(p, 0); 10306 10307 isup_rlc(ss7, e->rel.call); 10308 p->ss7call = NULL; 10309 10310 ast_mutex_unlock(&p->lock); 10311 break; 10312 case ISUP_EVENT_ACM: 10313 chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc); 10314 if (chanpos < 0) { 10315 ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic); 10316 isup_rel(ss7, e->acm.call, -1); 10317 break; 10318 } else { 10319 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, }; 10320 10321 p = linkset->pvts[chanpos]; 10322 10323 ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic); 10324 10325 if (e->acm.call_ref_ident > 0) { 10326 p->rlt = 1; /* Setting it but not using it here*/ 10327 } 10328 10329 ast_mutex_lock(&p->lock); 10330 dahdi_queue_frame(p, &f, linkset); 10331 p->proceeding = 1; 10332 p->dialing = 0; 10333 /* Send alerting if subscriber is free */ 10334 if (e->acm.called_party_status_ind == 1) { 10335 p->alerting = 1; 10336 p->subs[SUB_REAL].needringing = 1; 10337 } 10338 ast_mutex_unlock(&p->lock); 10339 } 10340 break; 10341 case ISUP_EVENT_CGB: 10342 chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc); 10343 if (chanpos < 0) { 10344 ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic); 10345 break; 10346 } 10347 p = linkset->pvts[chanpos]; 10348 ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1); 10349 isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type); 10350 break; 10351 case ISUP_EVENT_CGU: 10352 chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc); 10353 if (chanpos < 0) { 10354 ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic); 10355 break; 10356 } 10357 p = linkset->pvts[chanpos]; 10358 ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0); 10359 isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type); 10360 break; 10361 case ISUP_EVENT_UCIC: 10362 chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc); 10363 if (chanpos < 0) { 10364 ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic); 10365 break; 10366 } 10367 p = linkset->pvts[chanpos]; 10368 ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic); 10369 ast_mutex_lock(&p->lock); 10370 p->remotelyblocked = 1; 10371 p->inservice = 0; 10372 ast_mutex_unlock(&p->lock); //doesn't require a SS7 acknowledgement 10373 break; 10374 case ISUP_EVENT_BLO: 10375 chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc); 10376 if (chanpos < 0) { 10377 ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic); 10378 break; 10379 } 10380 p = linkset->pvts[chanpos]; 10381 ast_debug(1, "Blocking CIC %d\n", e->blo.cic); 10382 ast_mutex_lock(&p->lock); 10383 p->remotelyblocked = 1; 10384 ast_mutex_unlock(&p->lock); 10385 isup_bla(linkset->ss7, e->blo.cic, p->dpc); 10386 break; 10387 case ISUP_EVENT_BLA: 10388 chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc); 10389 if (chanpos < 0) { 10390 ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic); 10391 break; 10392 } 10393 ast_debug(1, "Blocking CIC %d\n", e->bla.cic); 10394 p = linkset->pvts[chanpos]; 10395 ast_mutex_lock(&p->lock); 10396 p->locallyblocked = 1; 10397 ast_mutex_unlock(&p->lock); 10398 break; 10399 case ISUP_EVENT_UBL: 10400 chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc); 10401 if (chanpos < 0) { 10402 ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic); 10403 break; 10404 } 10405 p = linkset->pvts[chanpos]; 10406 ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic); 10407 ast_mutex_lock(&p->lock); 10408 p->remotelyblocked = 0; 10409 ast_mutex_unlock(&p->lock); 10410 isup_uba(linkset->ss7, e->ubl.cic, p->dpc); 10411 break; 10412 case ISUP_EVENT_UBA: 10413 chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc); 10414 if (chanpos < 0) { 10415 ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic); 10416 break; 10417 } 10418 p = linkset->pvts[chanpos]; 10419 ast_debug(1, "Unblocking CIC %d\n", e->uba.cic); 10420 ast_mutex_lock(&p->lock); 10421 p->locallyblocked = 0; 10422 ast_mutex_unlock(&p->lock); 10423 break; 10424 case ISUP_EVENT_CON: 10425 case ISUP_EVENT_ANM: 10426 if (e->e == ISUP_EVENT_CON) 10427 cic = e->con.cic; 10428 else 10429 cic = e->anm.cic; 10430 10431 chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc); 10432 if (chanpos < 0) { 10433 ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic); 10434 isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1); 10435 break; 10436 } else { 10437 p = linkset->pvts[chanpos]; 10438 ast_mutex_lock(&p->lock); 10439 p->subs[SUB_REAL].needanswer = 1; 10440 if (p->dsp && p->dsp_features) { 10441 ast_dsp_set_features(p->dsp, p->dsp_features); 10442 p->dsp_features = 0; 10443 } 10444 dahdi_enable_ec(p); 10445 ast_mutex_unlock(&p->lock); 10446 } 10447 break; 10448 case ISUP_EVENT_RLC: 10449 chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc); 10450 if (chanpos < 0) { 10451 ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic); 10452 break; 10453 } else { 10454 p = linkset->pvts[chanpos]; 10455 ast_mutex_lock(&p->lock); 10456 if (p->alreadyhungup) 10457 p->ss7call = NULL; 10458 else 10459 ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL. Ignoring.\n"); 10460 ast_mutex_unlock(&p->lock); 10461 } 10462 break; 10463 case ISUP_EVENT_FAA: 10464 chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc); 10465 if (chanpos < 0) { 10466 ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic); 10467 break; 10468 } else { 10469 p = linkset->pvts[chanpos]; 10470 ast_debug(1, "FAA received on CIC %d\n", e->faa.cic); 10471 ast_mutex_lock(&p->lock); 10472 if (p->alreadyhungup){ 10473 p->ss7call = NULL; 10474 ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR. Ignoring.\n"); 10475 } 10476 ast_mutex_unlock(&p->lock); 10477 } 10478 break; 10479 default: 10480 ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e)); 10481 break; 10482 } 10483 } 10484 ast_mutex_unlock(&linkset->lock); 10485 } 10486 10487 return 0; 10488 }
| static int ss7_pres_scr2cid_pres | ( | char | presentation_ind, | |
| char | screening_ind | |||
| ) | [static] |
Definition at line 9951 of file chan_dahdi.c.
Referenced by ss7_linkset().
| static void ss7_rel | ( | struct dahdi_ss7 * | ss7 | ) | [inline, static] |
Definition at line 1245 of file chan_dahdi.c.
References ast_mutex_unlock(), and dahdi_ss7::lock.
Referenced by dahdi_answer(), dahdi_call(), dahdi_hangup(), and dahdi_indicate().
01246 { 01247 ast_mutex_unlock(&ss7->lock); 01248 }
| static void ss7_reset_linkset | ( | struct dahdi_ss7 * | linkset | ) | [static] |
Definition at line 9769 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().
09770 { 09771 int i, startcic = -1, endcic, dpc; 09772 09773 if (linkset->numchans <= 0) 09774 return; 09775 09776 startcic = linkset->pvts[0]->cic; 09777 /* DB: CIC's DPC fix */ 09778 dpc = linkset->pvts[0]->dpc; 09779 09780 for (i = 0; i < linkset->numchans; i++) { 09781 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)) { 09782 continue; 09783 } else { 09784 endcic = linkset->pvts[i]->cic; 09785 ast_verbose("Resetting CICs %d to %d\n", startcic, endcic); 09786 isup_grs(linkset->ss7, startcic, endcic, dpc); 09787 09788 /* DB: CIC's DPC fix */ 09789 if (linkset->pvts[i+1]) { 09790 startcic = linkset->pvts[i+1]->cic; 09791 dpc = linkset->pvts[i+1]->dpc; 09792 } 09793 } 09794 } 09795 }
| static struct dahdi_ss7* ss7_resolve_linkset | ( | int | linkset | ) | [static, read] |
Definition at line 8688 of file chan_dahdi.c.
References linksets, and NUM_SPANS.
Referenced by linkset_addsigchan(), mkintf(), and process_dahdi().
Definition at line 9809 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().
09810 { 09811 struct ss7 *ss7 = linkset->ss7; 09812 int res; 09813 int law = 1; 09814 struct ast_channel *c; 09815 char tmp[256]; 09816 09817 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1) 09818 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno)); 09819 09820 if (linkset->type == SS7_ITU) 09821 law = DAHDI_LAW_ALAW; 09822 else 09823 law = DAHDI_LAW_MULAW; 09824 09825 res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law); 09826 if (res < 0) 09827 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel); 09828 09829 if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) { 09830 p->proceeding = 1; 09831 isup_acm(ss7, p->ss7call); 09832 } 09833 09834 ast_mutex_unlock(&linkset->lock); 09835 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0); 09836 09837 if (!c) { 09838 ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic); 09839 /* Holding this lock is assumed entering the function */ 09840 ast_mutex_lock(&linkset->lock); 09841 return; 09842 } else 09843 ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic); 09844 09845 dahdi_enable_ec(p); 09846 09847 /* We only reference these variables in the context of the ss7_linkset function 09848 * when receiving either and IAM or a COT message. Since they are only accessed 09849 * from this context, we should be safe to unlock around them */ 09850 09851 ast_mutex_unlock(&p->lock); 09852 09853 if (!ast_strlen_zero(p->charge_number)) { 09854 pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number); 09855 /* Clear this after we set it */ 09856 p->charge_number[0] = 0; 09857 } 09858 if (!ast_strlen_zero(p->gen_add_number)) { 09859 pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number); 09860 /* Clear this after we set it */ 09861 p->gen_add_number[0] = 0; 09862 } 09863 if (!ast_strlen_zero(p->jip_number)) { 09864 pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number); 09865 /* Clear this after we set it */ 09866 p->jip_number[0] = 0; 09867 } 09868 if (!ast_strlen_zero(p->gen_dig_number)) { 09869 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number); 09870 /* Clear this after we set it */ 09871 p->gen_dig_number[0] = 0; 09872 } 09873 if (!ast_strlen_zero(p->orig_called_num)) { 09874 pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num); 09875 /* Clear this after we set it */ 09876 p->orig_called_num[0] = 0; 09877 } 09878 09879 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type); 09880 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp); 09881 /* Clear this after we set it */ 09882 p->gen_dig_type = 0; 09883 09884 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme); 09885 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp); 09886 /* Clear this after we set it */ 09887 p->gen_dig_scheme = 0; 09888 09889 if (!ast_strlen_zero(p->lspi_ident)) { 09890 pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident); 09891 /* Clear this after we set it */ 09892 p->lspi_ident[0] = 0; 09893 } 09894 09895 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident); 09896 pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp); 09897 /* Clear this after we set it */ 09898 p->call_ref_ident = 0; 09899 09900 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc); 09901 pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp); 09902 /* Clear this after we set it */ 09903 p->call_ref_pc = 0; 09904 09905 snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat); 09906 pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp); 09907 /* Clear this after we set it */ 09908 p->calling_party_cat = 0; 09909 09910 if (!ast_strlen_zero(p->redirecting_num)) { 09911 pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num); 09912 /* Clear this after we set it */ 09913 p->redirecting_num[0] = 0; 09914 } 09915 if (!ast_strlen_zero(p->generic_name)) { 09916 pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name); 09917 /* Clear this after we set it */ 09918 p->generic_name[0] = 0; 09919 } 09920 09921 ast_mutex_lock(&p->lock); 09922 ast_mutex_lock(&linkset->lock); 09923 }
| static void * ss_thread | ( | void * | data | ) | [static] |
Definition at line 6542 of file chan_dahdi.c.
References ast_channel::_state, alloc_sub(), ARRAY_LEN, ast_bridged_channel(), ast_canmatch_extension(), AST_CAUSE_UNALLOCATED, 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_FRAME_CONTROL, AST_FRAME_DTMF, ast_free, ast_frfree, ast_hangup(), ast_ignore_pattern(), AST_LAW, ast_log(), ast_masq_park_call(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_mutex_lock(), ast_mutex_unlock(), ast_parking_ext(), ast_pbx_run(), ast_pickup_call(), ast_pickup_ext(), ast_queue_control(), ast_read(), ast_safe_sleep(), ast_say_digit_str(), ast_set_callerid(), ast_setstate(), ast_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, chan, 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_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, f, ast_frame::frametype, ast_smdi_md_message::fwd_st, ast_channel::hangupcause, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::hardwaredtmf, dahdi_pvt::hidecallerid, dahdi_pvt::immediate, ISTRUNK, dahdi_pvt::lastcid_num, len(), dahdi_subchannel::linear, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pvt::mwimonitor_rpas, my_getsigstr(), name, NEED_MFDETECT, notify_message(), dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pvt::pri, 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, 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().
06543 { 06544 struct ast_channel *chan = data; 06545 struct dahdi_pvt *p = chan->tech_pvt; 06546 char exten[AST_MAX_EXTENSION] = ""; 06547 char exten2[AST_MAX_EXTENSION] = ""; 06548 unsigned char buf[256]; 06549 char dtmfcid[300]; 06550 char dtmfbuf[300]; 06551 struct callerid_state *cs = NULL; 06552 char *name = NULL, *number = NULL; 06553 int distMatches; 06554 int curRingData[3]; 06555 int receivedRingT; 06556 int counter1; 06557 int counter; 06558 int samples = 0; 06559 struct ast_smdi_md_message *smdi_msg = NULL; 06560 int flags; 06561 int i; 06562 int timeout; 06563 int getforward = 0; 06564 char *s1, *s2; 06565 int len = 0; 06566 int res; 06567 int idx; 06568 06569 ast_mutex_lock(&ss_thread_lock); 06570 ss_thread_count++; 06571 ast_mutex_unlock(&ss_thread_lock); 06572 /* in the bizarre case where the channel has become a zombie before we 06573 even get started here, abort safely 06574 */ 06575 if (!p) { 06576 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name); 06577 ast_hangup(chan); 06578 goto quit; 06579 } 06580 ast_verb(3, "Starting simple switch on '%s'\n", chan->name); 06581 idx = dahdi_get_index(chan, p, 1); 06582 if (idx < 0) { 06583 ast_log(LOG_WARNING, "Huh?\n"); 06584 ast_hangup(chan); 06585 goto quit; 06586 } 06587 if (p->dsp) 06588 ast_dsp_digitreset(p->dsp); 06589 switch (p->sig) { 06590 #ifdef HAVE_PRI 06591 case SIG_PRI: 06592 case SIG_BRI: 06593 case SIG_BRI_PTMP: 06594 /* Now loop looking for an extension */ 06595 ast_copy_string(exten, p->exten, sizeof(exten)); 06596 len = strlen(exten); 06597 res = 0; 06598 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 06599 if (len && !ast_ignore_pattern(chan->context, exten)) 06600 tone_zone_play_tone(p->subs[idx].dfd, -1); 06601 else 06602 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 06603 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) 06604 timeout = matchdigittimeout; 06605 else 06606 timeout = gendigittimeout; 06607 res = ast_waitfordigit(chan, timeout); 06608 if (res < 0) { 06609 ast_debug(1, "waitfordigit returned < 0...\n"); 06610 ast_hangup(chan); 06611 goto quit; 06612 } else if (res) { 06613 exten[len++] = res; 06614 exten[len] = '\0'; 06615 } else 06616 break; 06617 } 06618 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */ 06619 if (ast_strlen_zero(exten)) { 06620 ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n"); 06621 exten[0] = 's'; 06622 exten[1] = '\0'; 06623 } 06624 tone_zone_play_tone(p->subs[idx].dfd, -1); 06625 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) { 06626 /* Start the real PBX */ 06627 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06628 if (p->dsp) ast_dsp_digitreset(p->dsp); 06629 dahdi_enable_ec(p); 06630 ast_setstate(chan, AST_STATE_RING); 06631 res = ast_pbx_run(chan); 06632 if (res) { 06633 ast_log(LOG_WARNING, "PBX exited non-zero!\n"); 06634 } 06635 } else { 06636 ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context); 06637 chan->hangupcause = AST_CAUSE_UNALLOCATED; 06638 ast_hangup(chan); 06639 p->exten[0] = '\0'; 06640 /* Since we send release complete here, we won't get one */ 06641 p->call = NULL; 06642 } 06643 goto quit; 06644 break; 06645 #endif 06646 case SIG_FEATD: 06647 case SIG_FEATDMF: 06648 case SIG_FEATDMF_TA: 06649 case SIG_E911: 06650 case SIG_FGC_CAMAMF: 06651 case SIG_FEATB: 06652 case SIG_EMWINK: 06653 case SIG_SF_FEATD: 06654 case SIG_SF_FEATDMF: 06655 case SIG_SF_FEATB: 06656 case SIG_SFWINK: 06657 if (dahdi_wink(p, idx)) 06658 goto quit; 06659 /* Fall through */ 06660 case SIG_EM: 06661 case SIG_EM_E1: 06662 case SIG_SF: 06663 case SIG_FGC_CAMA: 06664 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 06665 if (p->dsp) 06666 ast_dsp_digitreset(p->dsp); 06667 /* set digit mode appropriately */ 06668 if (p->dsp) { 06669 if (NEED_MFDETECT(p)) 06670 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 06671 else 06672 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 06673 } 06674 memset(dtmfbuf, 0, sizeof(dtmfbuf)); 06675 /* Wait for the first digit only if immediate=no */ 06676 if (!p->immediate) 06677 /* Wait for the first digit (up to 5 seconds). */ 06678 res = ast_waitfordigit(chan, 5000); 06679 else 06680 res = 0; 06681 if (res > 0) { 06682 /* save first char */ 06683 dtmfbuf[0] = res; 06684 switch (p->sig) { 06685 case SIG_FEATD: 06686 case SIG_SF_FEATD: 06687 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06688 if (res > 0) 06689 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06690 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06691 break; 06692 case SIG_FEATDMF_TA: 06693 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06694 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06695 if (dahdi_wink(p, idx)) goto quit; 06696 dtmfbuf[0] = 0; 06697 /* Wait for the first digit (up to 5 seconds). */ 06698 res = ast_waitfordigit(chan, 5000); 06699 if (res <= 0) break; 06700 dtmfbuf[0] = res; 06701 /* fall through intentionally */ 06702 case SIG_FEATDMF: 06703 case SIG_E911: 06704 case SIG_FGC_CAMAMF: 06705 case SIG_SF_FEATDMF: 06706 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06707 /* if international caca, do it again to get real ANO */ 06708 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14)) 06709 { 06710 if (dahdi_wink(p, idx)) goto quit; 06711 dtmfbuf[0] = 0; 06712 /* Wait for the first digit (up to 5 seconds). */ 06713 res = ast_waitfordigit(chan, 5000); 06714 if (res <= 0) break; 06715 dtmfbuf[0] = res; 06716 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06717 } 06718 if (res > 0) { 06719 /* if E911, take off hook */ 06720 if (p->sig == SIG_E911) 06721 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06722 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000); 06723 } 06724 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06725 break; 06726 case SIG_FEATB: 06727 case SIG_SF_FEATB: 06728 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06729 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06730 break; 06731 case SIG_EMWINK: 06732 /* if we received a '*', we are actually receiving Feature Group D 06733 dial syntax, so use that mode; otherwise, fall through to normal 06734 mode 06735 */ 06736 if (res == '*') { 06737 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06738 if (res > 0) 06739 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06740 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06741 break; 06742 } 06743 default: 06744 /* If we got the first digit, get the rest */ 06745 len = 1; 06746 dtmfbuf[len] = '\0'; 06747 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06748 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06749 timeout = matchdigittimeout; 06750 } else { 06751 timeout = gendigittimeout; 06752 } 06753 res = ast_waitfordigit(chan, timeout); 06754 if (res < 0) { 06755 ast_debug(1, "waitfordigit returned < 0...\n"); 06756 ast_hangup(chan); 06757 goto quit; 06758 } else if (res) { 06759 dtmfbuf[len++] = res; 06760 dtmfbuf[len] = '\0'; 06761 } else { 06762 break; 06763 } 06764 } 06765 break; 06766 } 06767 } 06768 if (res == -1) { 06769 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno)); 06770 ast_hangup(chan); 06771 goto quit; 06772 } else if (res < 0) { 06773 ast_debug(1, "Got hung up before digits finished\n"); 06774 ast_hangup(chan); 06775 goto quit; 06776 } 06777 06778 if (p->sig == SIG_FGC_CAMA) { 06779 char anibuf[100]; 06780 06781 if (ast_safe_sleep(chan,1000) == -1) { 06782 ast_hangup(chan); 06783 goto quit; 06784 } 06785 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06786 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 06787 res = my_getsigstr(chan, anibuf, "#", 10000); 06788 if ((res > 0) && (strlen(anibuf) > 2)) { 06789 if (anibuf[strlen(anibuf) - 1] == '#') 06790 anibuf[strlen(anibuf) - 1] = 0; 06791 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2); 06792 } 06793 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 06794 } 06795 06796 ast_copy_string(exten, dtmfbuf, sizeof(exten)); 06797 if (ast_strlen_zero(exten)) 06798 ast_copy_string(exten, "s", sizeof(exten)); 06799 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) { 06800 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */ 06801 if (exten[0] == '*') { 06802 char *stringp=NULL; 06803 ast_copy_string(exten2, exten, sizeof(exten2)); 06804 /* Parse out extension and callerid */ 06805 stringp=exten2 +1; 06806 s1 = strsep(&stringp, "*"); 06807 s2 = strsep(&stringp, "*"); 06808 if (s2) { 06809 if (!ast_strlen_zero(p->cid_num)) 06810 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 06811 else 06812 ast_set_callerid(chan, s1, NULL, s1); 06813 ast_copy_string(exten, s2, sizeof(exten)); 06814 } else 06815 ast_copy_string(exten, s1, sizeof(exten)); 06816 } else if (p->sig == SIG_FEATD) 06817 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 06818 } 06819 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 06820 if (exten[0] == '*') { 06821 char *stringp=NULL; 06822 ast_copy_string(exten2, exten, sizeof(exten2)); 06823 /* Parse out extension and callerid */ 06824 stringp=exten2 +1; 06825 s1 = strsep(&stringp, "#"); 06826 s2 = strsep(&stringp, "#"); 06827 if (s2) { 06828 if (!ast_strlen_zero(p->cid_num)) 06829 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 06830 else 06831 if (*(s1 + 2)) 06832 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2); 06833 ast_copy_string(exten, s2 + 1, sizeof(exten)); 06834 } else 06835 ast_copy_string(exten, s1 + 2, sizeof(exten)); 06836 } else 06837 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 06838 } 06839 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) { 06840 if (exten[0] == '*') { 06841 char *stringp=NULL; 06842 ast_copy_string(exten2, exten, sizeof(exten2)); 06843 /* Parse out extension and callerid */ 06844 stringp=exten2 +1; 06845 s1 = strsep(&stringp, "#"); 06846 s2 = strsep(&stringp, "#"); 06847 if (s2 && (*(s2 + 1) == '0')) { 06848 if (*(s2 + 2)) 06849 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2); 06850 } 06851 if (s1) ast_copy_string(exten, s1, sizeof(exten)); 06852 else ast_copy_string(exten, "911", sizeof(exten)); 06853 } else 06854 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel); 06855 } 06856 if (p->sig == SIG_FEATB) { 06857 if (exten[0] == '*') { 06858 char *stringp=NULL; 06859 ast_copy_string(exten2, exten, sizeof(exten2)); 06860 /* Parse out extension and callerid */ 06861 stringp=exten2 +1; 06862 s1 = strsep(&stringp, "#"); 06863 ast_copy_string(exten, exten2 + 1, sizeof(exten)); 06864 } else 06865 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel); 06866 } 06867 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 06868 dahdi_wink(p, idx); 06869 /* some switches require a minimum guard time between 06870 the last FGD wink and something that answers 06871 immediately. This ensures it */ 06872 if (ast_safe_sleep(chan,100)) goto quit; 06873 } 06874 dahdi_enable_ec(p); 06875 if (NEED_MFDETECT(p)) { 06876 if (p->dsp) { 06877 if (!p->hardwaredtmf) 06878 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 06879 else { 06880 ast_dsp_free(p->dsp); 06881 p->dsp = NULL; 06882 } 06883 } 06884 } 06885 06886 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) { 06887 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06888 if (p->dsp) ast_dsp_digitreset(p->dsp); 06889 res = ast_pbx_run(chan); 06890 if (res) { 06891 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 06892 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06893 } 06894 goto quit; 06895 } else { 06896 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context); 06897 sleep(2); 06898 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO); 06899 if (res < 0) 06900 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel); 06901 else 06902 sleep(1); 06903 res = ast_streamfile(chan, "ss-noservice", chan->language); 06904 if (res >= 0) 06905 ast_waitstream(chan, ""); 06906 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06907 ast_hangup(chan); 06908 goto quit; 06909 } 06910 break; 06911 case SIG_FXOLS: 06912 case SIG_FXOGS: 06913 case SIG_FXOKS: 06914 /* Read the first digit */ 06915 timeout = firstdigittimeout; 06916 /* If starting a threeway call, never timeout on the first digit so someone 06917 can use flash-hook as a "hold" feature */ 06918 if (p->subs[SUB_THREEWAY].owner) 06919 timeout = 999999; 06920 while (len < AST_MAX_EXTENSION-1) { 06921 /* Read digit unless it's supposed to be immediate, in which case the 06922 only answer is 's' */ 06923 if (p->immediate) 06924 res = 's'; 06925 else 06926 res = ast_waitfordigit(chan, timeout); 06927 timeout = 0; 06928 if (res < 0) { 06929 ast_debug(1, "waitfordigit returned < 0...\n"); 06930 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 06931 ast_hangup(chan); 06932 goto quit; 06933 } else if (res) { 06934 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout); 06935 exten[len++]=res; 06936 exten[len] = '\0'; 06937 } 06938 if (!ast_ignore_pattern(chan->context, exten)) 06939 tone_zone_play_tone(p->subs[idx].dfd, -1); 06940 else 06941 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 06942 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) { 06943 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 06944 if (getforward) { 06945 /* Record this as the forwarding extension */ 06946 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 06947 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel); 06948 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 06949 if (res) 06950 break; 06951 usleep(500000); 06952 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 06953 sleep(1); 06954 memset(exten, 0, sizeof(exten)); 06955 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 06956 len = 0; 06957 getforward = 0; 06958 } else { 06959 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 06960 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06961 if (!ast_strlen_zero(p->cid_num)) { 06962 if (!p->hidecallerid) 06963 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 06964 else 06965 ast_set_callerid(chan, NULL, NULL, p->cid_num); 06966 } 06967 if (!ast_strlen_zero(p->cid_name)) { 06968 if (!p->hidecallerid) 06969 ast_set_callerid(chan, NULL, p->cid_name, NULL); 06970 } 06971 ast_setstate(chan, AST_STATE_RING); 06972 dahdi_enable_ec(p); 06973 res = ast_pbx_run(chan); 06974 if (res) { 06975 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 06976 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06977 } 06978 goto quit; 06979 } 06980 } else { 06981 /* It's a match, but they just typed a digit, and there is an ambiguous match, 06982 so just set the timeout to matchdigittimeout and wait some more */ 06983 timeout = matchdigittimeout; 06984 } 06985 } else if (res == 0) { 06986 ast_debug(1, "not enough digits (and no ambiguous match)...\n"); 06987 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06988 dahdi_wait_event(p->subs[idx].dfd); 06989 ast_hangup(chan); 06990 goto quit; 06991 } else if (p->callwaiting && !strcmp(exten, "*70")) { 06992 ast_verb(3, "Disabling call waiting on %s\n", chan->name); 06993 /* Disable call waiting if enabled */ 06994 p->callwaiting = 0; 06995 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 06996 if (res) { 06997 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 06998 chan->name, strerror(errno)); 06999 } 07000 len = 0; 07001 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len); 07002 memset(exten, 0, sizeof(exten)); 07003 timeout = firstdigittimeout; 07004 07005 } else if (!strcmp(exten,ast_pickup_ext())) { 07006 /* Scan all channels and see if there are any 07007 * ringing channels that have call groups 07008 * that equal this channels pickup group 07009 */ 07010 if (idx == SUB_REAL) { 07011 /* Switch us from Third call to Call Wait */ 07012 if (p->subs[SUB_THREEWAY].owner) { 07013 /* If you make a threeway call and the *8# a call, it should actually 07014 look like a callwait */ 07015 alloc_sub(p, SUB_CALLWAIT); 07016 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 07017 unalloc_sub(p, SUB_THREEWAY); 07018 } 07019 dahdi_enable_ec(p); 07020 if (ast_pickup_call(chan)) { 07021 ast_debug(1, "No call pickup possible...\n"); 07022 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07023 dahdi_wait_event(p->subs[idx].dfd); 07024 } 07025 ast_hangup(chan); 07026 goto quit; 07027 } else { 07028 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n"); 07029 ast_hangup(chan); 07030 goto quit; 07031 } 07032 07033 } else if (!p->hidecallerid && !strcmp(exten, "*67")) { 07034 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name); 07035 /* Disable Caller*ID if enabled */ 07036 p->hidecallerid = 1; 07037 if (chan->cid.cid_num) 07038 ast_free(chan->cid.cid_num); 07039 chan->cid.cid_num = NULL; 07040 if (chan->cid.cid_name) 07041 ast_free(chan->cid.cid_name); 07042 chan->cid.cid_name = NULL; 07043 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07044 if (res) { 07045 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07046 chan->name, strerror(errno)); 07047 } 07048 len = 0; 07049 memset(exten, 0, sizeof(exten)); 07050 timeout = firstdigittimeout; 07051 } else if (p->callreturn && !strcmp(exten, "*69")) { 07052 res = 0; 07053 if (!ast_strlen_zero(p->lastcid_num)) { 07054 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language); 07055 } 07056 if (!res) 07057 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07058 break; 07059 } else if (!strcmp(exten, "*78")) { 07060 dahdi_dnd(p, 1); 07061 /* Do not disturb */ 07062 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07063 getforward = 0; 07064 memset(exten, 0, sizeof(exten)); 07065 len = 0; 07066 } else if (!strcmp(exten, "*79")) { 07067 dahdi_dnd(p, 0); 07068 /* Do not disturb */ 07069 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07070 getforward = 0; 07071 memset(exten, 0, sizeof(exten)); 07072 len = 0; 07073 } else if (p->cancallforward && !strcmp(exten, "*72")) { 07074 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07075 getforward = 1; 07076 memset(exten, 0, sizeof(exten)); 07077 len = 0; 07078 } else if (p->cancallforward && !strcmp(exten, "*73")) { 07079 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel); 07080 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07081 memset(p->call_forward, 0, sizeof(p->call_forward)); 07082 getforward = 0; 07083 memset(exten, 0, sizeof(exten)); 07084 len = 0; 07085 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 07086 p->subs[SUB_THREEWAY].owner && 07087 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 07088 /* This is a three way call, the main call being a real channel, 07089 and we're parking the first call. */ 07090 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL); 07091 ast_verb(3, "Parking call to '%s'\n", chan->name); 07092 break; 07093 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) { 07094 ast_verb(3, "Blacklisting number %s\n", p->lastcid_num); 07095 res = ast_db_put("blacklist", p->lastcid_num, "1"); 07096 if (!res) { 07097 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07098 memset(exten, 0, sizeof(exten)); 07099 len = 0; 07100 } 07101 } else if (p->hidecallerid && !strcmp(exten, "*82")) { 07102 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name); 07103 /* Enable Caller*ID if enabled */ 07104 p->hidecallerid = 0; 07105 if (chan->cid.cid_num) 07106 ast_free(chan->cid.cid_num); 07107 chan->cid.cid_num = NULL; 07108 if (chan->cid.cid_name) 07109 ast_free(chan->cid.cid_name); 07110 chan->cid.cid_name = NULL; 07111 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 07112 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07113 if (res) { 07114 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07115 chan->name, strerror(errno)); 07116 } 07117 len = 0; 07118 memset(exten, 0, sizeof(exten)); 07119 timeout = firstdigittimeout; 07120 } else if (!strcmp(exten, "*0")) { 07121 struct ast_channel *nbridge = 07122 p->subs[SUB_THREEWAY].owner; 07123 struct dahdi_pvt *pbridge = NULL; 07124 /* set up the private struct of the bridged one, if any */ 07125 if (nbridge && ast_bridged_channel(nbridge)) 07126 pbridge = ast_bridged_channel(nbridge)->tech_pvt; 07127 if (nbridge && pbridge && 07128 (nbridge->tech == &dahdi_tech) && 07129 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) && 07130 ISTRUNK(pbridge)) { 07131 int func = DAHDI_FLASH; 07132 /* Clear out the dial buffer */ 07133 p->dop.dialstr[0] = '\0'; 07134 /* flash hookswitch */ 07135 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 07136 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 07137 nbridge->name, strerror(errno)); 07138 } 07139 swap_subs(p, SUB_REAL, SUB_THREEWAY); 07140 unalloc_sub(p, SUB_THREEWAY); 07141 p->owner = p->subs[SUB_REAL].owner; 07142 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 07143 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 07144 ast_hangup(chan); 07145 goto quit; 07146 } else { 07147 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07148 dahdi_wait_event(p->subs[idx].dfd); 07149 tone_zone_play_tone(p->subs[idx].dfd, -1); 07150 swap_subs(p, SUB_REAL, SUB_THREEWAY); 07151 unalloc_sub(p, SUB_THREEWAY); 07152 p->owner = p->subs[SUB_REAL].owner; 07153 ast_hangup(chan); 07154 goto quit; 07155 } 07156 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) && 07157 ((exten[0] != '*') || (strlen(exten) > 2))) { 07158 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); 07159 break; 07160 } 07161 if (!timeout) 07162 timeout = gendigittimeout; 07163 if (len && !ast_ignore_pattern(chan->context, exten)) 07164 tone_zone_play_tone(p->subs[idx].dfd, -1); 07165 } 07166 break; 07167 case SIG_FXSLS: 07168 case SIG_FXSGS: 07169 case SIG_FXSKS: 07170 #ifdef HAVE_PRI 07171 if (p->pri) { 07172 /* This is a GR-303 trunk actually. Wait for the first ring... */ 07173 struct ast_frame *f; 07174 int res; 07175 time_t start; 07176 07177 time(&start); 07178 ast_setstate(chan, AST_STATE_RING); 07179 while (time(NULL) < start + 3) { 07180 res = ast_waitfor(chan, 1000); 07181 if (res) { 07182 f = ast_read(chan); 07183 if (!f) { 07184 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n"); 07185 ast_hangup(chan); 07186 goto quit; 07187 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) { 07188 res = 1; 07189 } else 07190 res = 0; 07191 ast_frfree(f); 07192 if (res) { 07193 ast_debug(1, "Got ring!\n"); 07194 res = 0; 07195 break; 07196 } 07197 } 07198 } 07199 } 07200 #endif 07201 /* check for SMDI messages */ 07202 if (p->use_smdi && p->smdi_iface) { 07203 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); 07204 07205 if (smdi_msg != NULL) { 07206 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten)); 07207 07208 if (smdi_msg->type == 'B') 07209 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b"); 07210 else if (smdi_msg->type == 'N') 07211 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u"); 07212 07213 ast_debug(1, "Received SMDI message on %s\n", chan->name); 07214 } else { 07215 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n"); 07216 } 07217 } 07218 07219 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) { 07220 number = smdi_msg->calling_st; 07221 07222 /* If we want caller id, we're in a prering state due to a polarity reversal 07223 * and we're set to use a polarity reversal to trigger the start of caller id, 07224 * grab the caller id and wait for ringing to start... */ 07225 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) { 07226 /* If set to use DTMF CID signalling, listen for DTMF */ 07227 if (p->cid_signalling == CID_SIG_DTMF) { 07228 int k = 0; 07229 cs = NULL; 07230 ast_debug(1, "Receiving DTMF cid on " 07231 "channel %s\n", chan->name); 07232 dahdi_setlinear(p->subs[idx].dfd, 0); 07233 res = 2000; 07234 for (;;) { 07235 struct ast_frame *f; 07236 res = ast_waitfor(chan, res); 07237 if (res <= 0) { 07238 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 07239 "Exiting simple switch\n"); 07240 ast_hangup(chan); 07241 goto quit; 07242 } 07243 f = ast_read(chan); 07244 if (!f) 07245 break; 07246 if (f->frametype == AST_FRAME_DTMF) { 07247 dtmfbuf[k++] = f->subclass; 07248 ast_debug(1, "CID got digit '%c'\n", f->subclass); 07249 res = 2000; 07250 } 07251 ast_frfree(f); 07252 if (chan->_state == AST_STATE_RING || 07253 chan->_state == AST_STATE_RINGING) 07254 break; /* Got ring */ 07255 } 07256 dtmfbuf[k] = '\0'; 07257 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 07258 /* Got cid and ring. */ 07259 ast_debug(1, "CID got string '%s'\n", dtmfbuf); 07260 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 07261 ast_debug(1, "CID is '%s', flags %d\n", 07262 dtmfcid, flags); 07263 /* If first byte is NULL, we have no cid */ 07264 if (!ast_strlen_zero(dtmfcid)) 07265 number = dtmfcid; 07266 else 07267 number = NULL; 07268 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 07269 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { 07270 cs = callerid_new(p->cid_signalling); 07271 if (cs) { 07272 samples = 0; 07273 #if 1 07274 bump_gains(p); 07275 #endif 07276 /* Take out of linear mode for Caller*ID processing */ 07277 dahdi_setlinear(p->subs[idx].dfd, 0); 07278 07279 /* First we wait and listen for the Caller*ID */ 07280 for (;;) { 07281 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07282 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 07283 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07284 callerid_free(cs); 07285 ast_hangup(chan); 07286 goto quit; 07287 } 07288 if (i & DAHDI_IOMUX_SIGEVENT) { 07289 res = dahdi_get_event(p->subs[idx].dfd); 07290 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07291 07292 if (p->cid_signalling == CID_SIG_V23_JP) { 07293 if (res == DAHDI_EVENT_RINGBEGIN) { 07294 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07295 usleep(1); 07296 } 07297 } else { 07298 res = 0; 07299 break; 07300 } 07301 } else if (i & DAHDI_IOMUX_READ) { 07302 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 07303 if (res < 0) { 07304 if (errno != ELAST) { 07305 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07306 callerid_free(cs); 07307 ast_hangup(chan); 07308 goto quit; 07309 } 07310 break; 07311 } 07312 samples += res; 07313 07314 if (p->cid_signalling == CID_SIG_V23_JP) { 07315 res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); 07316 } else { 07317 res = callerid_feed(cs, buf, res, AST_LAW(p)); 07318 } 07319 07320 if (res < 0) { 07321 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name); 07322 break; 07323 } else if (res) 07324 break; 07325 else if (samples > (8000 * 10)) 07326 break; 07327 } 07328 } 07329 if (res == 1) { 07330 callerid_get(cs, &name, &number, &flags); 07331 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 07332 } 07333 07334 if (p->cid_signalling == CID_SIG_V23_JP) { 07335 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 07336 usleep(1); 07337 res = 4000; 07338 } else { 07339 07340 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 07341 res = 2000; 07342 } 07343 07344 for (;;) { 07345 struct ast_frame *f; 07346 res = ast_waitfor(chan, res); 07347 if (res <= 0) { 07348 ast_log(LOG_WARNING, "CID timed out waiting for ring. " 07349 "Exiting simple switch\n"); 07350 ast_hangup(chan); 07351 goto quit; 07352 } 07353 if (!(f = ast_read(chan))) { 07354 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); 07355 ast_hangup(chan); 07356 goto quit; 07357 } 07358 ast_frfree(f); 07359 if (chan->_state == AST_STATE_RING || 07360 chan->_state == AST_STATE_RINGING) 07361 break; /* Got ring */ 07362 } 07363 07364 /* We must have a ring by now, so, if configured, lets try to listen for 07365 * distinctive ringing */ 07366 if (p->usedistinctiveringdetection) { 07367 len = 0; 07368 distMatches = 0; 07369 /* Clear the current ring data array so we dont have old data in it. */ 07370 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 07371 curRingData[receivedRingT] = 0; 07372 receivedRingT = 0; 07373 counter = 0; 07374 counter1 = 0; 07375 /* Check to see if context is what it should be, if not set to be. */ 07376 if (strcmp(p->context,p->defcontext) != 0) { 07377 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 07378 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 07379 } 07380 07381 for (;;) { 07382 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07383 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 07384 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07385 callerid_free(cs); 07386 ast_hangup(chan); 07387 goto quit; 07388 } 07389 if (i & DAHDI_IOMUX_SIGEVENT) { 07390 res = dahdi_get_event(p->subs[idx].dfd); 07391 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07392 res = 0; 07393 /* Let us detect distinctive ring */ 07394 07395 curRingData[receivedRingT] = p->ringt; 07396 07397 if (p->ringt < p->ringt_base/2) 07398 break; 07399 /* Increment the ringT counter so we can match it against 07400 values in chan_dahdi.conf for distinctive ring */ 07401 if (++receivedRingT == ARRAY_LEN(curRingData)) 07402 break; 07403 } else if (i & DAHDI_IOMUX_READ) { 07404 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 07405 if (res < 0) { 07406 if (errno != ELAST) { 07407 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07408 callerid_free(cs); 07409 ast_hangup(chan); 07410 goto quit; 07411 } 07412 break; 07413 } 07414 if (p->ringt) 07415 p->ringt--; 07416 if (p->ringt == 1) { 07417 res = -1; 07418 break; 07419 } 07420 } 07421 } 07422 /* this only shows up if you have n of the dring patterns filled in */ 07423 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 07424 for (counter = 0; counter < 3; counter++) { 07425 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 07426 channel */ 07427 distMatches = 0; 07428 for (counter1 = 0; counter1 < 3; counter1++) { 07429 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 07430 if (p->drings.ringnum[counter].ring[counter1] == -1) { 07431 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 07432 curRingData[counter1]); 07433 distMatches++; 07434 } 07435 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 07436 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 07437 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 07438 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 07439 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 07440 distMatches++; 07441 } 07442 } 07443 07444 if (distMatches == 3) { 07445 /* The ring matches, set the context to whatever is for distinctive ring.. */ 07446 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 07447 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 07448 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 07449 break; 07450 } 07451 } 07452 } 07453 /* Restore linear mode (if appropriate) for Caller*ID processing */ 07454 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 07455 #if 1 07456 restore_gains(p); 07457 #endif 07458 } else 07459 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 07460 } else { 07461 ast_log(LOG_WARNING, "Channel %s in prering " 07462 "state, but I have nothing to do. " 07463 "Terminating simple switch, should be " 07464 "restarted by the actual ring.\n", 07465 chan->name); 07466 ast_hangup(chan); 07467 goto quit; 07468 } 07469 } else if (p->use_callerid && p->cid_start == CID_START_RING) { 07470 if (p->cid_signalling == CID_SIG_DTMF) { 07471 int k = 0; 07472 cs = NULL; 07473 dahdi_setlinear(p->subs[idx].dfd, 0); 07474 res = 2000; 07475 for (;;) { 07476 struct ast_frame *f; 07477 res = ast_waitfor(chan, res); 07478 if (res <= 0) { 07479 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 07480 "Exiting simple switch\n"); 07481 ast_hangup(chan); 07482 return NULL; 07483 } 07484 f = ast_read(chan); 07485 if (f->frametype == AST_FRAME_DTMF) { 07486 dtmfbuf[k++] = f->subclass; 07487 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass); 07488 res = 2000; 07489 } 07490 ast_frfree(f); 07491 07492 if (p->ringt_base == p->ringt) 07493 break; 07494 07495 } 07496 dtmfbuf[k] = '\0'; 07497 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 07498 /* Got cid and ring. */ 07499 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 07500 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 07501 dtmfcid, flags); 07502 /* If first byte is NULL, we have no cid */ 07503 if (!ast_strlen_zero(dtmfcid)) 07504 number = dtmfcid; 07505 else 07506 number = NULL; 07507 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 07508 } else { 07509 /* FSK Bell202 callerID */ 07510 cs = callerid_new(p->cid_signalling); 07511 if (cs) { 07512 #if 1 07513 bump_gains(p); 07514 #endif 07515 samples = 0; 07516 len = 0; 07517 distMatches = 0; 07518 /* Clear the current ring data array so we dont have old data in it. */ 07519 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 07520 curRingData[receivedRingT] = 0; 07521 receivedRingT = 0; 07522 counter = 0; 07523 counter1 = 0; 07524 /* Check to see if context is what it should be, if not set to be. */ 07525 if (strcmp(p->context,p->defcontext) != 0) { 07526 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 07527 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 07528 } 07529 07530 /* Take out of linear mode for Caller*ID processing */ 07531 dahdi_setlinear(p->subs[idx].dfd, 0); 07532 for (;;) { 07533 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07534 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 07535 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07536 callerid_free(cs); 07537 ast_hangup(chan); 07538 goto quit; 07539 } 07540 if (i & DAHDI_IOMUX_SIGEVENT) { 07541 res = dahdi_get_event(p->subs[idx].dfd); 07542 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07543 /* If we get a PR event, they hung up while processing calerid */ 07544 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { 07545 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); 07546 p->polarity = POLARITY_IDLE; 07547 callerid_free(cs); 07548 ast_hangup(chan); 07549 goto quit; 07550 } 07551 res = 0; 07552 /* Let us detect callerid when the telco uses distinctive ring */ 07553 07554 curRingData[receivedRingT] = p->ringt; 07555 07556 if (p->ringt < p->ringt_base/2) 07557 break; 07558 /* Increment the ringT counter so we can match it against 07559 values in chan_dahdi.conf for distinctive ring */ 07560 if (++receivedRingT == ARRAY_LEN(curRingData)) 07561 break; 07562 } else if (i & DAHDI_IOMUX_READ) { 07563 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 07564 if (res < 0) { 07565 if (errno != ELAST) { 07566 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07567 callerid_free(cs); 07568 ast_hangup(chan); 07569 goto quit; 07570 } 07571 break; 07572 } 07573 if (p->ringt) 07574 p->ringt--; 07575 if (p->ringt == 1) { 07576 res = -1; 07577 break; 07578 } 07579 samples += res; 07580 res = callerid_feed(cs, buf, res, AST_LAW(p)); 07581 if (res < 0) { 07582 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno)); 07583 break; 07584 } else if (res) 07585 break; 07586 else if (samples > (8000 * 10)) 07587 break; 07588 } 07589 } 07590 if (res == 1) { 07591 callerid_get(cs, &name, &number, &flags); 07592 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 07593 } 07594 if (distinctiveringaftercid == 1) { 07595 /* Clear the current ring data array so we dont have old data in it. */ 07596 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) { 07597 curRingData[receivedRingT] = 0; 07598 } 07599 receivedRingT = 0; 07600 ast_verb(3, "Detecting post-CID distinctive ring\n"); 07601 for (;;) { 07602 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07603 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 07604 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07605 callerid_free(cs); 07606 ast_hangup(chan); 07607 goto quit; 07608 } 07609 if (i & DAHDI_IOMUX_SIGEVENT) { 07610 res = dahdi_get_event(p->subs[idx].dfd); 07611 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07612 res = 0; 07613 /* Let us detect callerid when the telco uses distinctive ring */ 07614 07615 curRingData[receivedRingT] = p->ringt; 07616 07617 if (p->ringt < p->ringt_base/2) 07618 break; 07619 /* Increment the ringT counter so we can match it against 07620 values in chan_dahdi.conf for distinctive ring */ 07621 if (++receivedRingT == ARRAY_LEN(curRingData)) 07622 break; 07623 } else if (i & DAHDI_IOMUX_READ) { 07624 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 07625 if (res < 0) { 07626 if (errno != ELAST) { 07627 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07628 callerid_free(cs); 07629 ast_hangup(chan); 07630 goto quit; 07631 } 07632 break; 07633 } 07634 if (p->ringt) 07635 p->ringt--; 07636 if (p->ringt == 1) { 07637 res = -1; 07638 break; 07639 } 07640 } 07641 } 07642 } 07643 if (p->usedistinctiveringdetection) { 07644 /* this only shows up if you have n of the dring patterns filled in */ 07645 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 07646 07647 for (counter = 0; counter < 3; counter++) { 07648 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 07649 channel */ 07650 /* this only shows up if you have n of the dring patterns filled in */ 07651 ast_verb(3, "Checking %d,%d,%d\n", 07652 p->drings.ringnum[counter].ring[0], 07653 p->drings.ringnum[counter].ring[1], 07654 p->drings.ringnum[counter].ring[2]); 07655 distMatches = 0; 07656 for (counter1 = 0; counter1 < 3; counter1++) { 07657 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 07658 if (p->drings.ringnum[counter].ring[counter1] == -1) { 07659 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 07660 curRingData[counter1]); 07661 distMatches++; 07662 } 07663 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 07664 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 07665 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 07666 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 07667 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 07668 distMatches++; 07669 } 07670 } 07671 if (distMatches == 3) { 07672 /* The ring matches, set the context to whatever is for distinctive ring.. */ 07673 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 07674 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 07675 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 07676 break; 07677 } 07678 } 07679 } 07680 /* Restore linear mode (if appropriate) for Caller*ID processing */ 07681 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 07682 #if 1 07683 restore_gains(p); 07684 #endif 07685 if (res < 0) { 07686 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); 07687 } 07688 } else 07689 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 07690 } 07691 } 07692 else 07693 cs = NULL; 07694 07695 if (number) 07696 ast_shrink_phone_number(number); 07697 ast_set_callerid(chan, number, name, number); 07698 07699 if (smdi_msg) 07700 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy); 07701 07702 if (cs) 07703 callerid_free(cs); 07704 /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */ 07705 if (flags & CID_MSGWAITING) { 07706 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel); 07707 notify_message(p->mailbox, 1); 07708 /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */ 07709 if (p->mwimonitor_rpas) { 07710 ast_hangup(chan); 07711 return NULL; 07712 } 07713 } else if (flags & CID_NOMSGWAITING) { 07714 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel); 07715 notify_message(p->mailbox, 0); 07716 /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */ 07717 if (p->mwimonitor_rpas) { 07718 ast_hangup(chan); 07719 return NULL; 07720 } 07721 } 07722 07723 ast_setstate(chan, AST_STATE_RING); 07724 chan->rings = 1; 07725 p->ringt = p->ringt_base; 07726 res = ast_pbx_run(chan); 07727 if (res) { 07728 ast_hangup(chan); 07729 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07730 } 07731 goto quit; 07732 default: 07733 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel); 07734 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07735 if (res < 0) 07736 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 07737 } 07738 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07739 if (res < 0) 07740 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 07741 ast_hangup(chan); 07742 quit: 07743 ast_mutex_lock(&ss_thread_lock); 07744 ss_thread_count--; 07745 ast_cond_signal(&ss_thread_complete); 07746 ast_mutex_unlock(&ss_thread_lock); 07747 return NULL; 07748 }
| static int start_pri | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 11985 of file chan_dahdi.c.
References ast_log(), ast_pthread_create_background, dahdi_close_pri_fd(), DAHDI_OVERLAPDIAL_BOTH, DAHDI_OVERLAPDIAL_OUTGOING, DCHAN_NOTINALARM, dahdi_pri::dchanavail, dahdi_pri::dchannels, dahdi_pri::dchans, DEFAULT_PRI_DEBUG, errno, dahdi_pri::fds, dahdi_pri::inbanddisconnect, LOG_ERROR, dahdi_pri::master, dahdi_pri::nodetype, dahdi_pri::nsf, dahdi_pri::overlapdial, dahdi_pri::pri, pri_dchannel(), dahdi_pri::resetpos, dahdi_pri::sig, SIG_BRI, SIG_BRI_PTMP, and dahdi_pri::switchtype.
Referenced by setup_dahdi().
11986 { 11987 int res, x; 11988 struct dahdi_params p; 11989 struct dahdi_bufferinfo bi; 11990 struct dahdi_spaninfo si; 11991 int i; 11992 11993 for (i = 0; i < NUM_DCHANS; i++) { 11994 if (!pri->dchannels[i]) 11995 break; 11996 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR); 11997 x = pri->dchannels[i]; 11998 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) { 11999 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno)); 12000 return -1; 12001 } 12002 memset(&p, 0, sizeof(p)); 12003 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p); 12004 if (res) { 12005 dahdi_close_pri_fd(pri, i); 12006 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno)); 12007 return -1; 12008 } 12009 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) { 12010 dahdi_close_pri_fd(pri, i); 12011 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x); 12012 return -1; 12013 } 12014 memset(&si, 0, sizeof(si)); 12015 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si); 12016 if (res) { 12017 dahdi_close_pri_fd(pri, i); 12018 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno)); 12019 } 12020 if (!si.alarms) 12021 pri->dchanavail[i] |= DCHAN_NOTINALARM; 12022 else 12023 pri->dchanavail[i] &= ~DCHAN_NOTINALARM; 12024 memset(&bi, 0, sizeof(bi)); 12025 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 12026 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 12027 bi.numbufs = 32; 12028 bi.bufsize = 1024; 12029 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) { 12030 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno)); 12031 dahdi_close_pri_fd(pri, i); 12032 return -1; 12033 } 12034 switch (pri->sig) { 12035 case SIG_BRI: 12036 pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype); 12037 break; 12038 case SIG_BRI_PTMP: 12039 pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype); 12040 break; 12041 default: 12042 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype); 12043 } 12044 /* Force overlap dial if we're doing GR-303! */ 12045 if (pri->switchtype == PRI_SWITCH_GR303_TMC) 12046 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH; 12047 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0); 12048 #ifdef HAVE_PRI_INBANDDISCONNECT 12049 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect); 12050 #endif 12051 /* Enslave to master if appropriate */ 12052 if (i) 12053 pri_enslave(pri->dchans[0], pri->dchans[i]); 12054 if (!pri->dchans[i]) { 12055 dahdi_close_pri_fd(pri, i); 12056 ast_log(LOG_ERROR, "Unable to create PRI structure\n"); 12057 return -1; 12058 } 12059 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG); 12060 pri_set_nsf(pri->dchans[i], pri->nsf); 12061 #ifdef PRI_GETSET_TIMERS 12062 for (x = 0; x < PRI_MAX_TIMERS; x++) { 12063 if (pritimers[x] != 0) 12064 pri_set_timer(pri->dchans[i], x, pritimers[x]); 12065 } 12066 #endif 12067 } 12068 /* Assume primary is the one we use */ 12069 pri->pri = pri->dchans[0]; 12070 pri->resetpos = -1; 12071 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) { 12072 for (i = 0; i < NUM_DCHANS; i++) { 12073 if (!pri->dchannels[i]) 12074 break; 12075 dahdi_close_pri_fd(pri, i); 12076 } 12077 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno)); 12078 return -1; 12079 } 12080 return 0; 12081 }
| static void swap_subs | ( | struct dahdi_pvt * | p, | |
| int | a, | |||
| int | b | |||
| ) | [static] |
Definition at line 1408 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().
01409 { 01410 int tchan; 01411 int tinthreeway; 01412 struct ast_channel *towner; 01413 01414 ast_debug(1, "Swapping %d and %d\n", a, b); 01415 01416 tchan = p->subs[a].chan; 01417 towner = p->subs[a].owner; 01418 tinthreeway = p->subs[a].inthreeway; 01419 01420 p->subs[a].chan = p->subs[b].chan; 01421 p->subs[a].owner = p->subs[b].owner; 01422 p->subs[a].inthreeway = p->subs[b].inthreeway; 01423 01424 p->subs[b].chan = tchan; 01425 p->subs[b].owner = towner; 01426 p->subs[b].inthreeway = tinthreeway; 01427 01428 if (p->subs[a].owner) 01429 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd); 01430 if (p->subs[b].owner) 01431 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd); 01432 wakeup_sub(p, a, NULL); 01433 wakeup_sub(p, b, NULL); 01434 }
| static int unalloc_sub | ( | struct dahdi_pvt * | p, | |
| int | x | |||
| ) | [static] |
Definition at line 1558 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_subchannel::chan, dahdi_pvt::channel, dahdi_subchannel::curconf, dahdi_close_sub(), dahdi_subchannel::inthreeway, dahdi_subchannel::linear, LOG_WARNING, dahdi_subchannel::owner, dahdi_pvt::polarity, POLARITY_IDLE, and dahdi_pvt::subs.
Referenced by attempt_transfer(), dahdi_handle_event(), dahdi_hangup(), and ss_thread().
01559 { 01560 if (!x) { 01561 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel); 01562 return -1; 01563 } 01564 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel); 01565 dahdi_close_sub(p, x); 01566 p->subs[x].linear = 0; 01567 p->subs[x].chan = 0; 01568 p->subs[x].owner = NULL; 01569 p->subs[x].inthreeway = 0; 01570 p->polarity = POLARITY_IDLE; 01571 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf)); 01572 return 0; 01573 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 14076 of file chan_dahdi.c.
References __unload_module(), ast_mutex_destroy(), linksets, lock, NUM_SPANS, and pris.
14077 { 14078 #if defined(HAVE_PRI) || defined(HAVE_SS7) 14079 int y; 14080 #endif 14081 #ifdef HAVE_PRI 14082 for (y = 0; y < NUM_SPANS; y++) 14083 ast_mutex_destroy(&pris[y].lock); 14084 #endif 14085 #ifdef HAVE_SS7 14086 for (y = 0; y < NUM_SPANS; y++) 14087 ast_mutex_destroy(&linksets[y].lock); 14088 #endif /* HAVE_SS7 */ 14089 return __unload_module(); 14090 }
| static int update_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1948 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, MAX_SLAVES, 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().
01949 { 01950 int needconf = 0; 01951 int x; 01952 int useslavenative; 01953 struct dahdi_pvt *slave = NULL; 01954 01955 useslavenative = isslavenative(p, &slave); 01956 /* Start with the obvious, general stuff */ 01957 for (x = 0; x < 3; x++) { 01958 /* Look for three way calls */ 01959 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) { 01960 conf_add(p, &p->subs[x], x, 0); 01961 needconf++; 01962 } else { 01963 conf_del(p, &p->subs[x], x); 01964 } 01965 } 01966 /* If we have a slave, add him to our conference now. or DAX 01967 if this is slave native */ 01968 for (x = 0; x < MAX_SLAVES; x++) { 01969 if (p->slaves[x]) { 01970 if (useslavenative) 01971 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 01972 else { 01973 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 01974 needconf++; 01975 } 01976 } 01977 } 01978 /* If we're supposed to be in there, do so now */ 01979 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 01980 if (useslavenative) 01981 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 01982 else { 01983 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 01984 needconf++; 01985 } 01986 } 01987 /* If we have a master, add ourselves to his conference */ 01988 if (p->master) { 01989 if (isslavenative(p->master, NULL)) { 01990 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 01991 } else { 01992 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 01993 } 01994 } 01995 if (!needconf) { 01996 /* Nobody is left (or should be left) in our conference. 01997 Kill it. */ 01998 p->confno = -1; 01999 } 02000 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf); 02001 return 0; 02002 }
Definition at line 1315 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_subchannel::owner, and dahdi_pvt::subs.
Referenced by pri_fixup_principle(), and swap_subs().
01319 { 01320 #ifdef HAVE_PRI 01321 if (pri) 01322 ast_mutex_unlock(&pri->lock); 01323 #endif 01324 for (;;) { 01325 if (p->subs[a].owner) { 01326 if (ast_channel_trylock(p->subs[a].owner)) { 01327 DEADLOCK_AVOIDANCE(&p->lock); 01328 } else { 01329 ast_queue_frame(p->subs[a].owner, &ast_null_frame); 01330 ast_channel_unlock(p->subs[a].owner); 01331 break; 01332 } 01333 } else 01334 break; 01335 } 01336 #ifdef HAVE_PRI 01337 if (pri) 01338 ast_mutex_lock(&pri->lock); 01339 #endif 01340 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "DAHDI Telephony w/PRI & SS7" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 15488 of file chan_dahdi.c.
| int alarm |
Definition at line 1713 of file chan_dahdi.c.
Referenced by alarm2str().
struct { ... } alarms[] [static] |
Referenced by alarm2str().
struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}} [static] |
Definition at line 1289 of file chan_dahdi.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 15488 of file chan_dahdi.c.
struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static] |
Definition at line 1270 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 1281 of file chan_dahdi.c.
const char config[] = "chan_dahdi.conf" [static] |
Definition at line 168 of file chan_dahdi.c.
int cur_adjpointcode = -1 [static] |
Definition at line 383 of file chan_dahdi.c.
int cur_cicbeginswith = -1 [static] |
Definition at line 382 of file chan_dahdi.c.
int cur_defaultdpc = -1 [static] |
Definition at line 385 of file chan_dahdi.c.
int cur_linkset = -1 [static] |
Definition at line 380 of file chan_dahdi.c.
int cur_networkindicator = -1 [static] |
Definition at line 384 of file chan_dahdi.c.
int cur_pointcode = -1 [static] |
Definition at line 381 of file chan_dahdi.c.
int cur_ss7type = -1 [static] |
Definition at line 379 of file chan_dahdi.c.
struct ast_cli_entry dahdi_cli[] [static] |
Definition at line 13309 of file chan_dahdi.c.
struct ast_cli_entry dahdi_pri_cli[] [static] |
Definition at line 12440 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static] |
Definition at line 3246 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_descrip [static] |
" DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n" " IE over the current channel.\n"
Definition at line 3250 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static] |
Definition at line 3248 of file chan_dahdi.c.
struct ast_cli_entry dahdi_ss7_cli[] [static] |
Definition at line 13987 of file chan_dahdi.c.
struct ast_channel_tech dahdi_tech [static] |
Definition at line 1197 of file chan_dahdi.c.
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 118 of file chan_dahdi.c.
char defaultcic[64] = "" [static] |
Definition at line 226 of file chan_dahdi.c.
char defaultozz[64] = "" [static] |
Definition at line 227 of file chan_dahdi.c.
int distinctiveringaftercid = 0 [static] |
Definition at line 238 of file chan_dahdi.c.
char* events[] [static] |
Definition at line 1690 of file chan_dahdi.c.
int firstdigittimeout = 16000 [static] |
Wait up to 16 seconds for first digit (FXO logic).
Definition at line 254 of file chan_dahdi.c.
Referenced by disa_exec().
int gendigittimeout = 8000 [static] |
How long to wait for following digits (FXO logic).
Definition at line 257 of file chan_dahdi.c.
struct ast_jb_conf global_jbconf [static] |
Definition at line 125 of file chan_dahdi.c.
Referenced by dahdi_new(), process_dahdi(), and setup_dahdi().
int ifcount = 0 [static] |
Definition at line 266 of file chan_dahdi.c.
Referenced by __unload_module(), action_dahdishowchannels(), chandup(), dahdi_destroy_channel_bynum(), dahdi_hangup(), dahdi_request(), dahdi_restart(), dahdi_set_dnd(), dahdi_set_hwgain(), dahdi_set_swgain(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), destroy_channel(), do_monitor(), find_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 263 of file chan_dahdi.c.
Referenced by __unload_module(), action_dahdishowchannels(), dahdi_hangup(), dahdi_request(), dahdi_set_dnd(), dahdi_set_hwgain(), dahdi_set_swgain(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), do_monitor(), and setup_dahdi().
struct ast_channel inuse [static] |
Definition at line 245 of file chan_dahdi.c.
Referenced by ast_jb_do_usecheck(), chanavail_exec(), load_module(), pri_assign_bearer(), pri_dchannel(), and update_call_counter().
const char* lbostr[] [static] |
Definition at line 106 of file chan_dahdi.c.
Definition at line 377 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_no_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 260 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 278 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 274 of file chan_dahdi.c.
Referenced by __unload_module(), dahdi_restart(), and restart_monitor().
ast_cond_t mwi_thread_complete [static] |
Definition at line 279 of file chan_dahdi.c.
int mwi_thread_count = 0 [static] |
Definition at line 284 of file chan_dahdi.c.
ast_mutex_t mwi_thread_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 281 of file chan_dahdi.c.
Referenced by dahdi_restart(), and mwi_send_thread().
int mwilevel = 512 [static] |
Definition at line 242 of file chan_dahdi.c.
char mwimonitornotify[PATH_MAX] = "" [static] |
Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled
Definition at line 232 of file chan_dahdi.c.
int mwisend_rpas = 0 [static] |
Definition at line 233 of file chan_dahdi.c.
| char* name |
Definition at line 1714 of file chan_dahdi.c.
int num_cadence = 4 [static] |
Definition at line 1267 of file chan_dahdi.c.
int num_restart_pending = 0 [static] |
Definition at line 286 of file chan_dahdi.c.
int numbufs = 4 [static] |
Definition at line 240 of file chan_dahdi.c.
char parkinglot[AST_MAX_EXTENSION] = "" [static] |
Default parking lot for this channel
Definition at line 229 of file chan_dahdi.c.
Referenced by __find_callno(), ast_iax2_new(), build_user(), check_access(), check_peer_ok(), create_addr_from_peer(), func_channel_write(), gtalk_load_config(), gtalk_new(), set_pvt_defaults(), sip_alloc(), and store_config_core().
int pridebugfd = -1 [static] |
Definition at line 249 of file chan_dahdi.c.
ast_mutex_t pridebugfdlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 269 of file chan_dahdi.c.
Referenced by dahdi_pri_error(), dahdi_pri_message(), handle_pri_set_debug_file(), handle_pri_show_debug(), and handle_pri_unset_debug_file().
char pridebugfilename[1024] = "" [static] |
Definition at line 250 of file chan_dahdi.c.
Definition at line 447 of file chan_dahdi.c.
Referenced by __unload_module(), build_channels(), complete_span_helper(), dahdi_pri_error(), dahdi_pri_message(), dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), handle_pri_debug(), handle_pri_no_debug(), handle_pri_really_debug(), handle_pri_show_debug(), handle_pri_show_span(), handle_pri_show_spans(), load_module(), mkintf(), pri_create_spanmap(), pri_create_trunkgroup(), pri_find_principle(), pri_resolve_span(), setup_dahdi(), and unload_module().
char progzone[10] = "" [static] |
Definition at line 235 of file chan_dahdi.c.
ast_mutex_t restart_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 283 of file chan_dahdi.c.
Referenced by dahdi_restart().
int ringt_base = DEFAULT_RINGT [static] |
Configured ring timeout base.
Definition at line 341 of file chan_dahdi.c.
| struct dahdi_pvt* round_robin[32] |
Definition at line 1224 of file chan_dahdi.c.
ast_cond_t ss_thread_complete [static] |
Definition at line 280 of file chan_dahdi.c.
int ss_thread_count = 0 [static] |
Definition at line 285 of file chan_dahdi.c.
ast_mutex_t ss_thread_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 282 of file chan_dahdi.c.
Referenced by dahdi_restart(), and ss_thread().
char* subnames[] [static] |
{
"Real",
"Callwait",
"Threeway"
}
Definition at line 486 of file chan_dahdi.c.
const char tdesc[] [static] |
Definition at line 159 of file chan_dahdi.c.
int usedistinctiveringdetection = 0 [static] |
Definition at line 237 of file chan_dahdi.c.
int user_has_defined_cadences = 0 [static] |
Definition at line 1268 of file chan_dahdi.c.
1.6.1